Uso de una entidad de servicio con el conector Spark 3 para Azure Cosmos DB for NoSQL
En este artículo, aprenderá a crear una aplicación de Microsoft Entra y una entidad de servicio que se puede usar con el control de acceso basado en rol. Después, puede usar esta entidad de servicio para conectarse a una cuenta de Azure Cosmos DB for NoSQL desde Spark 3.
Requisitos previos
- Una cuenta existente de Azure Cosmos DB for NoSQL.
- Si tiene una suscripción de Azure, cree una nueva cuenta.
- ¿No tiene una suscripción de Azure? Puede probar Azure Cosmos DB de forma gratuita, sin necesidad de usar su tarjeta de crédito.
- Un área de trabajo existente de Azure Databricks.
- Aplicación y entidad de servicio de Microsoft Entra registradas.
- Si no tiene una entidad de servicio y una aplicación, registre una aplicación mediante Azure Portal.
Creación de credenciales secretas y de registro
En esta sección, crearemos un secreto de cliente y registraremos el valor para usarlo más adelante.
Abra Azure Portal.
Vaya a la aplicación Microsoft Entra existente.
En la página Certificados y secretos: Después, cree un secreto. Guarde el secreto de cliente para usarlo más adelante en esta guía.
Vaya a la página Información general. Busque y registre los valores de Id. de aplicación (cliente), Id. de objeto e Id. de directorio (inquilino). Estos valores se usarán más adelante en el tutorial.
Vaya a su cuenta Azure Cosmos DB for NoSQL existente.
Registre el valor del URI en la página Información general. Registre también los valores de Id. de suscripción y Grupo de recursos. Usará estos valores más adelante en este artículo.
Creación de una definición y una asignación
En esta sección, creará una definición de rol de id. de Entra de Microsoft. A continuación, asigne ese rol con permisos para leer y escribir elementos en los contenedores.
Cree un rol utilizando el comando
az role definition create
. Pase el nombre de la cuenta y el grupo de recursos de Azure Cosmos DB for NoSQL, seguido de un cuerpo de JSON que defina el rol personalizado. El rol también tiene como ámbito el nivel de cuenta mediante/
. Asegúrese de proporcionar un nombre único para el rol mediante la propiedadRoleName
del cuerpo de la solicitud.az cosmosdb sql role definition create \ --resource-group "<resource-group-name>" \ --account-name "<account-name>" \ --body '{ "RoleName": "<role-definition-name>", "Type": "CustomRole", "AssignableScopes": ["/"], "Permissions": [{ "DataActions": [ "Microsoft.DocumentDB/databaseAccounts/readMetadata", "Microsoft.DocumentDB/databaseAccounts/sqlDatabases/containers/items/*", "Microsoft.DocumentDB/databaseAccounts/sqlDatabases/containers/*" ] }] }'
Enumere la definición de rol que creó para capturar su identificador único en la salida JSON. Registre el valor
id
de la salida JSON.az cosmosdb sql role definition list \ --resource-group "<resource-group-name>" \ --account-name "<account-name>"
[ { ..., "id": "/subscriptions/<subscription-id>/resourceGroups/<resource-grou-name>/providers/Microsoft.DocumentDB/databaseAccounts/<account-name>/sqlRoleDefinitions/<role-definition-id>", ... "permissions": [ { "dataActions": [ "Microsoft.DocumentDB/databaseAccounts/readMetadata", "Microsoft.DocumentDB/databaseAccounts/sqlDatabases/containers/items/*", "Microsoft.DocumentDB/databaseAccounts/sqlDatabases/containers/*" ], "notDataActions": [] } ], ... } ]
Use
az cosmosdb sql role assignment create
para crear una asignación de roles. Reemplace<aad-principal-id>
por el identificador de objeto que registró anteriormente en esta guía. Además, reemplace<role-definition-id>
por el valorid
capturado al ejecutar el comandoaz cosmosdb sql role definition list
que ejecutó en un paso anterior.az cosmosdb sql role assignment create \ --resource-group "<resource-group-name>" \ --account-name "<account-name>" \ --scope "/" \ --principal-id "<account-name>" \ --role-definition-id "<role-definition-id>"
Uso de una entidad de servicio
Ahora que ha creado una aplicación de Microsoft Entra y una entidad de servicio, ha creado un rol personalizado y ha asignado los permisos de ese rol a su cuenta de Azure Cosmos DB for NoSQL, debería ser capaz de ejecutar un cuaderno.
Abra el área de trabajo de Azure Databricks.
En la interfaz del área de trabajo, cree un nuevo clúster. Configure el clúster con estas opciones, como mínimo:
Versión Valor Versión del entorno de ejecución 13.3 LTS (Scala 2.12, Spark 3.4.1)
Use la interfaz del área de trabajo para buscar paquetes de Maven desde Central de Maven con un Id. de grupo de
com.azure.cosmos.spark
. Instale el paquete específicamente para Spark 3.4 con unId.de Artefacto prefijo conazure-cosmos-spark_3-4
en el clúster.Por último, cree un nuevo cuaderno.
Sugerencia
De manera predeterminada, el cuaderno está asociado al clúster creado recientemente.
Dentro del cuaderno, establezca los ajustes de configuración del conector Spark de Azure Cosmos DB para el punto final de la cuenta NoSQL, el nombre de la base de datos y el nombre del contenedor. Use los valores Id.de suscripción, Grupo de recursos, Id. de aplicación (cliente), Id.de directorio (inquilino) y Secreto de cliente registrados anteriormente en esta guía.
# Set configuration settings config = { "spark.cosmos.accountEndpoint": "<nosql-account-endpoint>", "spark.cosmos.auth.type": "ServicePrincipal", "spark.cosmos.account.subscriptionId": "<subscription-id>", "spark.cosmos.account.resourceGroupName": "<resource-group-name>", "spark.cosmos.account.tenantId": "<entra-tenant-id>", "spark.cosmos.auth.aad.clientId": "<entra-app-client-id>", "spark.cosmos.auth.aad.clientSecret": "<entra-app-client-secret>", "spark.cosmos.database": "<database-name>", "spark.cosmos.container": "<container-name>" }
// Set configuration settings val config = Map( "spark.cosmos.accountEndpoint" -> "<nosql-account-endpoint>", "spark.cosmos.auth.type" -> "ServicePrincipal", "spark.cosmos.account.subscriptionId" -> "<subscription-id>", "spark.cosmos.account.resourceGroupName" -> "<resource-group-name>", "spark.cosmos.account.tenantId" -> "<entra-tenant-id>", "spark.cosmos.auth.aad.clientId" -> "<entra-app-client-id>", "spark.cosmos.auth.aad.clientSecret" -> "<entra-app-client-secret>", "spark.cosmos.database" -> "<database-name>", "spark.cosmos.container" -> "<container-name>" )
Configure la API de catálogo para administrar la API para recursos NoSQL mediante Spark.
# Configure Catalog Api spark.conf.set("spark.sql.catalog.cosmosCatalog", "com.azure.cosmos.spark.CosmosCatalog") spark.conf.set("spark.sql.catalog.cosmosCatalog.spark.cosmos.accountEndpoint", "<nosql-account-endpoint>") spark.conf.set("spark.sql.catalog.cosmosCatalog.spark.cosmos.auth.type", "ServicePrincipal") spark.conf.set("spark.sql.catalog.cosmosCatalog.spark.cosmos.account.subscriptionId", "<subscription-id>") spark.conf.set("spark.sql.catalog.cosmosCatalog.spark.cosmos.account.resourceGroupName", "<resource-group-name>") spark.conf.set("spark.sql.catalog.cosmosCatalog.spark.cosmos.account.tenantId", "<entra-tenant-id>") spark.conf.set("spark.sql.catalog.cosmosCatalog.spark.cosmos.auth.aad.clientId", "<entra-app-client-id>") spark.conf.set("spark.sql.catalog.cosmosCatalog.spark.cosmos.auth.aad.clientSecret", "<entra-app-client-secret>")
// Configure Catalog Api spark.conf.set(s"spark.sql.catalog.cosmosCatalog", "com.azure.cosmos.spark.CosmosCatalog") spark.conf.set(s"spark.sql.catalog.cosmosCatalog.spark.cosmos.accountEndpoint", "<nosql-account-endpoint>") spark.conf.set(s"spark.sql.catalog.cosmosCatalog.spark.cosmos.auth.type", "ServicePrincipal") spark.conf.set(s"spark.sql.catalog.cosmosCatalog.spark.cosmos.account.subscriptionId", "<subscription-id>") spark.conf.set(s"spark.sql.catalog.cosmosCatalog.spark.cosmos.account.resourceGroupName", "<resource-group-name>") spark.conf.set(s"spark.sql.catalog.cosmosCatalog.spark.cosmos.account.tenantId", "<entra-tenant-id>") spark.conf.set(s"spark.sql.catalog.cosmosCatalog.spark.cosmos.auth.aad.clientId", "<entra-app-client-id>") spark.conf.set(s"spark.sql.catalog.cosmosCatalog.spark.cosmos.auth.aad.clientSecret", "<entra-app-client-secret>")
Cree una nueva base de datos mediante
CREATE DATABASE IF NOT EXISTS
. Asegúrese de proporcionar el nombre de la base de datos.# Create a database using the Catalog API spark.sql("CREATE DATABASE IF NOT EXISTS cosmosCatalog.{};".format("<database-name>"))
// Create a database using the Catalog API spark.sql(s"CREATE DATABASE IF NOT EXISTS cosmosCatalog.<database-name>;")
Cree un contenedor con el nombre de la base de datos, el nombre del contenedor, la ruta de acceso de clave de partición y los valores de rendimiento que especifique.
# Create a products container using the Catalog API spark.sql("CREATE TABLE IF NOT EXISTS cosmosCatalog.{}.{} USING cosmos.oltp TBLPROPERTIES(partitionKeyPath = '{}', manualThroughput = '{}')".format("<database-name>", "<container-name>", "<partition-key-path>", "<throughput>"))
// Create a products container using the Catalog API spark.sql(s"CREATE TABLE IF NOT EXISTS cosmosCatalog.<database-name>.<container-name> using cosmos.oltp TBLPROPERTIES(partitionKeyPath = '<partition-key-path>', manualThroughput = '<throughput>')")
Cree un conjunto de datos de ejemplo.
# Create sample data products = ( ("68719518391", "gear-surf-surfboards", "Yamba Surfboard", 12, 850.00, False), ("68719518371", "gear-surf-surfboards", "Kiama Classic Surfboard", 25, 790.00, True) )
// Create sample data val products = Seq( ("68719518391", "gear-surf-surfboards", "Yamba Surfboard", 12, 850.00, false), ("68719518371", "gear-surf-surfboards", "Kiama Classic Surfboard", 25, 790.00, true) )
Use
spark.createDataFrame
y la configuración de procesamiento de transacciones en línea (OLTP) guardadas anteriormente para agregar datos de ejemplo al contenedor de destino.# Ingest sample data spark.createDataFrame(products) \ .toDF("id", "category", "name", "quantity", "price", "clearance") \ .write \ .format("cosmos.oltp") \ .options(config) \ .mode("APPEND") \ .save()
// Ingest sample data spark.createDataFrame(products) .toDF("id", "category", "name", "quantity", "price", "clearance") .write .format("cosmos.oltp") .options(config) .mode("APPEND") .save()
Sugerencia
En este ejemplo de inicio rápido, las credenciales se asignan a variables en texto no cifrado. Por motivos de seguridad, se recomienda usar secretos. Para más información sobre cómo configurar secretos, consulte Adición de secretos a la configuración de Spark.