Condividi tramite


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

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.

  1. Apri il portale di Azure.

  2. Passare all'applicazione Microsoft Entra esistente.

  3. Passare alla pagina Certificati e segreti . Creare quindi un nuovo segreto. Salvare il valore Segreto client da usare più avanti in questo articolo.

  4. 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.

  5. Passare all'account Azure Cosmos DB per NoSQL esistente.

  6. Registrare il valore dell'URI nella pagina Panoramica. Registrare anche i valori id sottoscrizione e gruppo di risorse. Questi valori verranno usati più avanti in questo 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.

  1. 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 la RoleName 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/*"
                ]
            }]
        }'
    
  2. 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": []
          }
        ],
        ...
      }
    ]
    
  3. 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'esecuzione id del az 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.

  1. Aprire l'area di lavoro di Azure Databricks.

  2. 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)
  3. 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 preceduto azure-cosmos-spark_3-4 dal prefisso nel cluster.

  4. Infine, creare un nuovo notebook.

    Suggerimento

    Per impostazione predefinita, il notebook è collegato al cluster creato di recente.

  5. 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>" 
    )
    
  6. 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>")
    
  7. 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>;")
    
  8. 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>')")
    
  9. 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)
    )
    
  10. 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.