Usare un'entità servizio con il connettore Spark 3 per Azure Cosmos DB per NoSQL
Questo articolo illustra come creare un'applicazione Microsoft Entra e un'entità servizio che possono essere usate con il controllo degli accessi in base al ruolo. È quindi possibile usare questa entità servizio per connettersi a un account Azure Cosmos DB per NoSQL da Spark 3.
Prerequisiti
- Un account Azure Cosmos DB for NoSQL già presente.
- Se si ha già una sottoscrizione di Azure, creare un nuovo account.
- Se non si ha una sottoscrizione di Azure, è possibile provare Azure Cosmos DB gratuitamente senza necessità di carta di credito.
- Un'area di lavoro di Azure Databricks esistente.
- Applicazione Microsoft Entra registrata e entità servizio.
- Se non si ha un'entità servizio e un'applicazione, registrare un'applicazione usando il portale di Azure.
Creare un segreto e registrare le credenziali
In questa sezione si crea un segreto client e si registra il valore da usare in un secondo momento.
Apri il portale di Azure.
Passare all'applicazione Microsoft Entra esistente.
Passare alla pagina Certificati e segreti . Creare quindi un nuovo segreto. Salvare il valore Segreto client da usare più avanti in questo articolo.
Passare alla pagina Panoramica. Individuare e registrare i valori per ID applicazione (client), ID oggetto e ID directory (tenant). Questi valori verranno usati anche più avanti in questo articolo.
Passare all'account Azure Cosmos DB per NoSQL esistente.
Registrare il valore dell'URI nella pagina Panoramica. Registrare anche i valori id sottoscrizione e gruppo di risorse. Questi valori vengono usati più avanti nell'articolo.
Creare una definizione e un'assegnazione
In questa sezione viene creata una definizione di ruolo ID Entra di Microsoft. Assegnare quindi il ruolo con le autorizzazioni per leggere e scrivere elementi nei contenitori.
Creare un ruolo usando il
az role definition create
comando . Passare il nome e il gruppo di risorse dell'account Azure Cosmos DB per NoSQL, seguiti da un corpo di JSON che definisce il ruolo personalizzato. Il ruolo ha anche come ambito il livello di account usando/
. Assicurarsi di specificare un nome univoco per il ruolo usando laRoleName
proprietà del corpo della richiesta.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/*" ] }] }'
Elencare la definizione del ruolo creata per recuperare l'identificatore univoco nell'output JSON. Registrare il
id
valore dell'output 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": [] } ], ... } ]
Usare
az cosmosdb sql role assignment create
per creare un'assegnazione di ruolo. Sostituire<aad-principal-id>
con l'ID oggetto registrato in precedenza in questo articolo.<role-definition-id>
Sostituire anche con il valore recuperato dall'esecuzioneid
delaz cosmosdb sql role definition list
comando in un passaggio precedente.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>"
Usare un’entità servizio
Ora che è stata creata un'applicazione e un'entità servizio Microsoft Entra, è stato creato un ruolo personalizzato e sono state assegnate le autorizzazioni del ruolo all'account Azure Cosmos DB per NoSQL, è necessario poter eseguire un notebook.
Aprire l'area di lavoro di Azure Databricks.
Nell'interfaccia dell'area di lavoro creare un nuovo cluster. Configurare il cluster con queste impostazioni, almeno:
Versione Valore Versione di runtime 13.3 LTS (Scala 2.12, Spark 3.4.1)
Usare l'interfaccia dell'area di lavoro per cercare i pacchetti Maven da Maven Central con un ID gruppo di
com.azure.cosmos.spark
. Installare il pacchetto in modo specifico per Spark 3.4 con un ID artefatto precedutoazure-cosmos-spark_3-4
dal prefisso nel cluster.Infine, creare un nuovo notebook.
Suggerimento
Per impostazione predefinita, il notebook è collegato al cluster creato di recente.
Nel notebook impostare le impostazioni di configurazione del connettore Spark di Azure Cosmos DB per l'endpoint dell'account NoSQL, il nome del database e il nome del contenitore. Usare i valori ID sottoscrizione, Gruppo di risorse, ID applicazione (client), ID directory (tenant) e Segreto client registrati in precedenza in questo articolo.
# 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>" )
Configurare l'API catalogo per gestire le risorse API per NoSQL usando 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>")
Creare un nuovo database usando
CREATE DATABASE IF NOT EXISTS
. Assicurarsi di specificare il nome del database.# 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>;")
Creare un nuovo contenitore usando il nome del database, il nome del contenitore, il percorso della chiave di partizione e i valori di velocità effettiva specificati.
# 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>')")
Creare un set di dati di esempio.
# 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) )
Usare
spark.createDataFrame
e la configurazione OLTP (Online Transaction Processing) salvata in precedenza per aggiungere dati di esempio al contenitore di destinazione.# 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()
Suggerimento
In questo esempio di avvio rapido le credenziali vengono assegnate alle variabili in testo non crittografato. Per motivi di sicurezza, è consigliabile usare i segreti. Per altre informazioni su come configurare i segreti, vedere Aggiungere segreti alla configurazione di Spark.