Condividi tramite


Distribuire e configurare ID dei carichi di lavoro di Microsoft Entra su un cluster di Servizio Azure Kubernetes (AKS)

Questo articolo illustra come distribuire e configurare un cluster Servizio Azure Kubernetes (AKS) con ID dei carichi di lavoro di Microsoft Entra. I passaggi descritti in questo articolo includono:

  • Creare un nuovo cluster servizio Azure Kubernetes o aggiornare un cluster esistente utilizzando l'interfaccia della riga di comando di Azure o Terraform con il provider OpenID Connect (OIDC) e con ID dei carichi di lavoro di Microsoft Entra abilitato.
  • Creare un'identità di carico di lavoro e un account del servizio Kubernetes.
  • Configurare l'identità gestita per la federazione dei token.
  • Distribuire il carico di lavoro e verificare l'autenticazione con l'identità del carico di lavoro.
  • È possibile conferire a un pod nel cluster l'accesso ai segreti in un Key Vault di Azure.

Prerequisiti

  • Se non si ha un account Azure, creare un account free prima di iniziare.
  • Questo articolo richiede la versione 2.47.0 o successiva del interfaccia della riga di comando di Azure. Se si usa Azure Cloud Shell, la versione più recente è già installata. Eseguire az --version per trovare la versione. Se è necessario installare o aggiornare, vedere Installare interfaccia della riga di comando di Azure.
  • Assicurarsi che l'identità usata per creare il cluster disponga delle autorizzazioni minime appropriate. Per ulteriori informazioni, vedere le opzioni di accesso e identità per Servizio Azure Kubernetes (AKS).
  • Se sono presenti più sottoscrizioni Azure, selezionare l'ID sottoscrizione appropriato in cui le risorse devono essere fatturate usando il comando az account set.

Note

È possibile usare Service Connector per configurare automaticamente alcuni passaggi. Per altre informazioni, vedere Tutorial: Connettersi all'account di archiviazione Azure in Servizio Azure Kubernetes (AKS) con Service Connector usando ID dei carichi di lavoro di Microsoft Entra.

Creare il file di configurazione terraform

I file di configurazione terraform definiscono l'infrastruttura creata e gestita da Terraform.

  1. Creare un file denominato main.tf e aggiungere il codice seguente per definire la versione di Terraform e specificare il provider Azure:

    terraform {
     required_version = ">= 1.5.0"
     required_providers {
       azurerm = {
         source  = "hashicorp/azurerm"
         version = "~> 4.0"
       }
       kubernetes = {
         source  = "hashicorp/kubernetes"
         version = "~> 2.30"
       }
       random = {
         source  = "hashicorp/random"
         version = "~> 3.6"
       }
     }
    }
    provider "azurerm" {
     features {}
     subscription_id = var.subscription_id
    }
    data "azurerm_client_config" "current" {}
    
  2. Aggiungere il codice seguente a main.tf per definire variabili riutilizzabili e generare nomi univoci per tutte le risorse:

    resource "random_string" "suffix" {
     length  = 6
     upper   = false
     special = false
     numeric = true
    }
    locals {
     suffix = random_string.suffix.result
     resource_group_name       = "rg-aks-wi-${local.suffix}"
     cluster_name              = "akswi${local.suffix}"
     managed_identity_name     = "uami-wi-${local.suffix}"
     federated_credential_name = "fic-wi-${local.suffix}"
     key_vault_name            = lower(substr("kvwi${local.suffix}", 0, 24))
     secret_name               = "secret-${local.suffix}"
     service_account_name      = "workload-sa-${local.suffix}"
     service_account_namespace = "default"
     workload_identity_subject = "system:serviceaccount:${local.service_account_namespace}:${local.service_account_name}"
    }
    

Creare un gruppo di risorse

Creare un gruppo di risorse usando il comando az group create.

export RANDOM_ID="$(openssl rand -hex 3)"
export RESOURCE_GROUP="myResourceGroup$RANDOM_ID"
export LOCATION="<your-preferred-region>"
az group create --name "${RESOURCE_GROUP}" --location "${LOCATION}"

Aggiungere il codice seguente a main.tf per creare un gruppo di risorse Azure. Aggiornare il valore location in modo che corrisponda all'area Azure preferita.

resource "azurerm_resource_group" "this" {
 name     = local.resource_group_name
 location = "eastus"
}

Abilitare l'emittente OIDC e l'ID di carico di lavoro Microsoft Entra su un cluster di AKS (servizio Azure Kubernetes)

È possibile abilitare l'emittente OIDC e il ID dei carichi di lavoro di Microsoft Entra su un cluster AKS nuovo o esistente.

Creare un cluster AKS utilizzando il comando az aks create con il parametro --enable-oidc-issuer per abilitare l'autorità emittente OIDC e il parametro --enable-workload-identity per abilitare ID dei carichi di lavoro di Microsoft Entra. L'esempio seguente crea un cluster con un singolo nodo:

export CLUSTER_NAME="myAKSCluster$RANDOM_ID"
az aks create \
    --resource-group "${RESOURCE_GROUP}" \
    --name "${CLUSTER_NAME}" \
    --enable-oidc-issuer \
    --enable-workload-identity \
    --generate-ssh-keys

Il comando viene completato dopo pochi minuti e vengono restituite informazioni in formato JSON sul cluster.

Aggiungere il codice seguente a main.tf per creare un cluster di Servizio Azure Kubernetes con emittente OIDC e ID dei carichi di lavoro di Microsoft Entra abilitati.

resource "azurerm_kubernetes_cluster" "this" {
 name                              = local.cluster_name
 location                          = azurerm_resource_group.this.location
 resource_group_name               = azurerm_resource_group.this.name
 dns_prefix                        = local.cluster_name
 oidc_issuer_enabled               = true
 workload_identity_enabled         = true
 role_based_access_control_enabled = true
 default_node_pool {
   name       = "system"
   node_count = 1
   vm_size    = "Standard_B4ms"
 }
 identity {
   type = "SystemAssigned"
 }
}

Recuperare l'URL dell'autorità di certificazione OIDC

Ottenere l'URL dell'autorità emittente OIDC usando il az aks show comando e salvarlo in una variabile di ambiente.

export AKS_OIDC_ISSUER="$(az aks show --name "${CLUSTER_NAME}" \
    --resource-group "${RESOURCE_GROUP}" \
    --query "oidcIssuerProfile.issuerUrl" \
    --output tsv)"

La variabile di ambiente deve contenere l'URL dell'autorità di certificazione, in modo simile all'esempio seguente:

https://eastus.oic.prod-aks.azure.com/00000000-0000-0000-0000-000000000000/11111111-1111-1111-1111-111111111111/

Per impostazione predefinita, l'autorità di certificazione è impostata per usare l'URL di base https://{region}.oic.prod-aks.azure.com/{tenant_id}/{uuid}, dove il valore per {region} corrisponde alla posizione in cui è distribuito il cluster del servizio Azure Kubernetes. Il valore {uuid} rappresenta la chiave OIDC, che è un GUID generato in modo casuale e non modificabile per ogni cluster.

Aggiungere il codice seguente a main.tf per recuperare l'URL dell'autorità emittente OIDC.

output "oidc_issuer_url" {
 value = azurerm_kubernetes_cluster.this.oidc_issuer_url
}

Creare un'identità gestita

  1. Ottieni l'ID della sottoscrizione e salvalo in una variabile di ambiente, usando il comando az account show.

    export SUBSCRIPTION="$(az account show --query id --output tsv)"
    
  2. Creare un'identità gestita assegnata dall'utente usando il comando az identity create.

    export USER_ASSIGNED_IDENTITY_NAME="myIdentity$RANDOM_ID"
    az identity create \
        --name "${USER_ASSIGNED_IDENTITY_NAME}" \
        --resource-group "${RESOURCE_GROUP}" \
        --location "${LOCATION}" \
        --subscription "${SUBSCRIPTION}"
    

    L'esempio di output seguente mostra la corretta creazione di un'identità gestita:

    {
      "clientId": "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx",
      "id": "/subscriptions/xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx/resourcegroups/myResourceGroupxxxxxx/providers/Microsoft.ManagedIdentity/userAssignedIdentities/myIdentityxxxxxx",
      "location": "eastus",
      "name": "myIdentityxxxxxx",
      "principalId": "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx",
      "resourceGroup": "myResourceGroupxxxxxx",
      "systemData": null,
      "tags": {},
      "tenantId": "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx",
      "type": "Microsoft.ManagedIdentity/userAssignedIdentities"
    }
    
  3. Ottenere l'ID client dell'identità gestita e salvarlo in una variabile di ambiente usando il az identity show comando .

    export USER_ASSIGNED_CLIENT_ID="$(az identity show \
        --resource-group "${RESOURCE_GROUP}" \
        --name "${USER_ASSIGNED_IDENTITY_NAME}" \
        --query 'clientId' \
        --output tsv)"
    

Aggiungere il codice seguente a main.tf per creare un'identità gestita:

resource "azurerm_user_assigned_identity" "this" {
 name                = local.managed_identity_name
 location            = azurerm_resource_group.this.location
 resource_group_name = azurerm_resource_group.this.name
}

Creare un account del servizio Kubernetes

  1. Connettiti al cluster del servizio Azure Kubernetes usando il comando az aks get-credentials.

    az aks get-credentials --name "${CLUSTER_NAME}" --resource-group "${RESOURCE_GROUP}"
    
  2. Creare un account del servizio Kubernetes e annotarlo con l'ID client dell'identità gestita applicando il manifesto seguente usando il kubectl apply comando .

    export SERVICE_ACCOUNT_NAME="workload-identity-sa$RANDOM_ID"
    export SERVICE_ACCOUNT_NAMESPACE="default"
    cat <<EOF | kubectl apply -f -
    apiVersion: v1
    kind: ServiceAccount
    metadata:
      annotations:
        azure.workload.identity/client-id: "${USER_ASSIGNED_CLIENT_ID}"
      name: "${SERVICE_ACCOUNT_NAME}"
      namespace: "${SERVICE_ACCOUNT_NAMESPACE}"
    EOF
    

    L'output seguente mostra la corretta creazione dell'identità del carico di lavoro:

    serviceaccount/workload-identity-sa created
    
  1. Aggiungere il codice seguente a main.tf per configurare l'accesso a Kubernetes per consentire la creazione di risorse Kubernetes.

    data "azurerm_kubernetes_cluster" "this" {
     name                = azurerm_kubernetes_cluster.this.name
     resource_group_name = azurerm_resource_group.this.name
    }
    provider "kubernetes" {
     host                   = data.azurerm_kubernetes_cluster.this.kube_config[0].host
     client_certificate     = base64decode(data.azurerm_kubernetes_cluster.this.kube_config[0].client_certificate)
     client_key             = base64decode(data.azurerm_kubernetes_cluster.this.kube_config[0].client_key)
     cluster_ca_certificate = base64decode(data.azurerm_kubernetes_cluster.this.kube_config[0].cluster_ca_certificate)
    }
    
  2. Aggiungere il codice seguente a main.tf per creare un account di servizio Kubernetes e annotare l'ID client dell'identità gestita.

    resource "kubernetes_service_account" "this" {
     metadata {
       name      = local.service_account_name
       namespace = local.service_account_namespace
       annotations = {
         "azure.workload.identity/client-id" = azurerm_user_assigned_identity.this.client_id
       }
     }
    }
    

Creare le credenziali dell'identità federata

Creare una credenziale di identità federata tra l'identità gestita, l'autorità emittente dell'account del servizio e il soggetto usando il comando az identity federated-credential create.

export FEDERATED_IDENTITY_CREDENTIAL_NAME="myFedIdentity$RANDOM_ID"
az identity federated-credential create \
    --name ${FEDERATED_IDENTITY_CREDENTIAL_NAME} \
    --identity-name "${USER_ASSIGNED_IDENTITY_NAME}" \
    --resource-group "${RESOURCE_GROUP}" \
    --issuer "${AKS_OIDC_ISSUER}" \
    --subject system:serviceaccount:"${SERVICE_ACCOUNT_NAMESPACE}":"${SERVICE_ACCOUNT_NAME}" \
    --audience api://AzureADTokenExchange

Note

La propagazione delle credenziali dell'identità federata richiede alcuni secondi dopo l'aggiunta. Se una richiesta di token viene effettuata immediatamente dopo l'aggiunta della credenziale dell'identità federata, la richiesta potrebbe non riuscire finché non viene aggiornata la cache. Per evitare questo problema, è possibile aggiungere un lieve ritardo dopo l'aggiunta delle credenziali di identità federate.

Aggiungere il seguente codice a main.tf per creare una credenziale di identità federata tra l'identità gestita, l'autorità emittente dell'account del servizio e l'oggetto:

resource "azurerm_federated_identity_credential" "this" {
 name                = local.federated_credential_name
 resource_group_name = azurerm_resource_group.this.name
 parent_id           = azurerm_user_assigned_identity.this.id
 issuer              = azurerm_kubernetes_cluster.this.oidc_issuer_url
 subject             = local.workload_identity_subject
 audience            = ["api://AzureADTokenExchange"]
}

Per altre informazioni sulle credenziali di identità federate in Microsoft Entra, vedere Panoramica delle credenziali di identità federate in Microsoft Entra ID.

Creare un Key Vault di Azure con autorizzazione Azure RBAC

Nell'esempio seguente viene illustrato come usare il modello di autorizzazione del controllo degli accessi in base al ruolo di Azure (Azure RBAC) per concedere al pod l'accesso al Key Vault. Per altre informazioni sul modello di autorizzazione del controllo degli accessi in base al ruolo (RBAC) di Azure per Azure Key Vault, vedere Concedere l'autorizzazione alle applicazioni per accedere a un Key Vault di Azure usando RBAC di Azure.

  1. Creare un insieme di credenziali con protezione dall'eliminazione e l'autorizzazione del controllo degli accessi in base al ruolo di Azure abilitata usando il comando az keyvault create. È anche possibile usare un Key Vault esistente se è configurato sia per la protezione dalla cancellazione che per l'autorizzazione Azure RBAC.

    export KEYVAULT_NAME="keyvault-workload-id$RANDOM_ID" # Ensure the key vault name is between 3-24 characters
    az keyvault create \
        --name "${KEYVAULT_NAME}" \
        --resource-group "${RESOURCE_GROUP}" \
        --location "${LOCATION}" \
        --enable-purge-protection \
        --enable-rbac-authorization
    
  2. Recuperare l'ID risorsa dell'insieme di credenziali delle chiavi e salvarlo in una variabile di ambiente usando il comando az keyvault show.

    export KEYVAULT_RESOURCE_ID=$(az keyvault show --resource-group "${RESOURCE_GROUP}" \
        --name "${KEYVAULT_NAME}" \
        --query id \
        --output tsv)
    

Aggiungere il codice seguente a main.tf per creare un Key Vault con autorizzazione Azure RBAC:

resource "azurerm_key_vault" "this" {
 name                          = local.key_vault_name
 location                      = azurerm_resource_group.this.location
 resource_group_name           = azurerm_resource_group.this.name
 tenant_id                     = data.azurerm_client_config.current.tenant_id
 sku_name                      = "standard"
 rbac_authorization_enabled    = true
}

Assegnare autorizzazioni di controllo degli accessi in base al ruolo per la gestione dell'insieme di credenziali delle chiavi

  1. Ottenere l'ID oggetto chiamante e salvarlo in una variabile di ambiente usando il az ad signed-in-user show comando .

    export CALLER_OBJECT_ID=$(az ad signed-in-user show --query id -o tsv)
    
  2. Assegnati il ruolo Azure RBAC Key Vault Secrets Officer per poter creare un segreto nel nuovo key vault utilizzando il comando az role assignment create.

    az role assignment create --assignee "${CALLER_OBJECT_ID}" \
        --role "Key Vault Secrets Officer" \
        --scope "${KEYVAULT_RESOURCE_ID}"
    

Aggiungere il codice seguente a main.tf per assegnarti il ruolo Azure RBAC Key Vault Secrets Officer in modo da poter creare un segreto nel nuovo key vault e assegnare il ruolo Key Vault Secrets User all'identità gestita assegnata dall'utente:

resource "azurerm_role_assignment" "user" {
 scope                = azurerm_key_vault.this.id
 role_definition_name = "Key Vault Secrets Officer"
 principal_id         = data.azurerm_client_config.current.object_id
}
resource "azurerm_role_assignment" "identity" {
 scope                = azurerm_key_vault.this.id
 role_definition_name = "Key Vault Secrets User"
 principal_id         = azurerm_user_assigned_identity.this.principal_id
}

Creare e configurare l'accesso segreto

  1. Creare un segreto nell'insieme di credenziali delle chiavi usando il comando az keyvault secret set.

    export KEYVAULT_SECRET_NAME="my-secret$RANDOM_ID"
    az keyvault secret set \
        --vault-name "${KEYVAULT_NAME}" \
        --name "${KEYVAULT_SECRET_NAME}" \
        --value "Hello\!"
    
  2. Ottenere l'ID principale dell'identità gestita assegnata dall'utente e salvarlo in una variabile di ambiente usando il comando az identity show.

    export IDENTITY_PRINCIPAL_ID=$(az identity show \
        --name "${USER_ASSIGNED_IDENTITY_NAME}" \
        --resource-group "${RESOURCE_GROUP}" \
        --query principalId \
        --output tsv)
    
  3. Assegnare il ruolo Utente dei segreti di Key Vault all'identità gestita assegnata a un utente usando il comando az role assignment create. Questo passaggio concede all'identità gestita l'autorizzazione per leggere i segreti dal Key Vault.

    az role assignment create \
        --assignee-object-id "${IDENTITY_PRINCIPAL_ID}" \
        --role "Key Vault Secrets User" \
        --scope "${KEYVAULT_RESOURCE_ID}" \
        --assignee-principal-type ServicePrincipal
    
  4. Creare una variabile di ambiente per l'URL dell'insieme di credenziali usando il comando az keyvault show.

    export KEYVAULT_URL="$(az keyvault show \
        --resource-group "${RESOURCE_GROUP}" \
        --name ${KEYVAULT_NAME} \
        --query properties.vaultUri \
        --output tsv)"
    

Aggiungere il seguente codice a main.tf per creare un segreto nell'insieme di credenziali delle chiavi:

resource "azurerm_key_vault_secret" "this" {
 name         = local.secret_name
 value        = "Hello from Key Vault"
 key_vault_id = azurerm_key_vault.this.id
}

Distribuire un pod di validazione e testare l'accesso

  1. Distribuire un pod per verificare che l'identità del carico di lavoro possa accedere al segreto nell'insieme di credenziali delle chiavi. L'esempio seguente usa l'immagine ghcr.io/azure/azure-workload-identity/msal-go, che contiene un'applicazione di esempio che recupera un segreto da Azure Key Vault usando ID dei carichi di lavoro di Microsoft Entra:

    kubectl apply -f - <<EOF
    apiVersion: v1
    kind: Pod
    metadata:
        name: sample-workload-identity-key-vault
        namespace: ${SERVICE_ACCOUNT_NAMESPACE}
        labels:
            azure.workload.identity/use: "true"
    spec:
        serviceAccountName: ${SERVICE_ACCOUNT_NAME}
        containers:
          - image: ghcr.io/azure/azure-workload-identity/msal-go
            name: oidc
            env:
              - name: KEYVAULT_URL
                value: ${KEYVAULT_URL}
              - name: SECRET_NAME
                value: ${KEYVAULT_SECRET_NAME}
        nodeSelector:
            kubernetes.io/os: linux
    EOF
    
  2. Attendere che il pod sia nello stato Ready usando il comando kubectl wait.

    kubectl wait --namespace ${SERVICE_ACCOUNT_NAMESPACE} --for=condition=Ready pod/sample-workload-identity-key-vault --timeout=120s
    
  3. Verificare che la SECRET_NAME variabile di ambiente sia impostata nel pod usando il kubectl describe comando .

    kubectl describe pod sample-workload-identity-key-vault | grep "SECRET_NAME:"
    

    In caso di esito positivo, l'output dovrebbe essere simile all'esempio seguente:

    SECRET_NAME: ${KEYVAULT_SECRET_NAME}
    
  4. Verificare che i pod possano ottenere un token e accedere alla risorsa usando il kubectl logs comando .

    kubectl logs sample-workload-identity-key-vault
    

    In caso di esito positivo, l'output dovrebbe essere simile all'esempio seguente:

    I0114 10:35:09.795900       1 main.go:63] "successfully got secret" secret="Hello\\!"
    

    Importante

    La propagazione delle assegnazioni di ruolo del controllo degli accessi in base al ruolo di Azure può richiedere fino a 10 minuti. Se il pod non riesce ad accedere al segreto, potrebbe essere necessario attendere la propagazione dell'assegnazione di ruolo. Per altre informazioni, vedere Troubleshoot Azure RBAC.

Disabilitare ID dei carichi di lavoro di Microsoft Entra su un cluster AKS

Disabilitare ID dei carichi di lavoro di Microsoft Entra nel cluster del servizio Azure Kubernetes in cui è stato abilitato e configurato, aggiornare il cluster del servizio Azure Kubernetes usando il comando az aks update con il parametro --disable-workload-identity.

az aks update \
    --resource-group "${RESOURCE_GROUP}" \
    --name "${CLUSTER_NAME}" \
    --disable-workload-identity

Distribuire un pod di verifica

Aggiungere il codice seguente a main.tf per distribuire un pod di verifica che utilizza l'identità del workload per accedere al segreto nell'insieme di credenziali delle chiavi (Key Vault):

resource "kubernetes_pod" "test" {
 metadata {
   name      = "workload-identity-test"
   namespace = local.service_account_namespace
   labels = {
     "azure.workload.identity/use" = "true"
   }
 }
 spec {
   service_account_name = kubernetes_service_account.this.metadata[0].name
   container {
     name  = "test"
     image = "ghcr.io/azure/azure-workload-identity/msal-go"
     env {
       name  = "KEYVAULT_URL"
       value = azurerm_key_vault.this.vault_uri
     }
     env {
       name  = "SECRET_NAME"
       value = azurerm_key_vault_secret.this.name
     }
   }
 }
}

Inizializzare Terraform

Inizializzare Terraform nella directory contenente il main.tf file usando il terraform init comando . Questo comando scarica il provider di Azure necessario per gestire le risorse Azure con Terraform.

terraform init

Crea un piano di esecuzione di Terraform

Creare un piano di esecuzione terraform usando il comando terraform plan. Questo comando mostra le risorse che Terraform creerà o modificherà nella sottoscrizione Azure.

terraform plan

Applicare la configurazione di Terraform

Dopo aver esaminato e confermato il piano di esecuzione, applicare la configurazione di Terraform usando il terraform apply comando . Questo comando crea o modifica le risorse definite nel file main.tf nella sottoscrizione Azure.

terraform apply

Verificare la distribuzione

  1. Connettiti al cluster del servizio Azure Kubernetes usando il comando az aks get-credentials.

    az aks get-credentials --name <cluster-name> --resource-group <resource-group>
    
  2. Controllare lo stato del pod di verifica usando il comando kubectl get pods.

  3. Quando il pod raggiunge uno stato Ready, verificare che possa accedere al segreto dell'insieme di credenziali delle chiavi controllando i log del pod usando il comando kubectl logs.

    kubectl logs workload-identity-test
    

In questo articolo, hai distribuito un cluster Kubernetes e lo hai configurato per utilizzare ID dei carichi di lavoro di Microsoft Entra per preparare i carichi di lavoro dell'applicazione ad autenticarsi con tale credenziale. A questo punto è possibile distribuire l'applicazione e configurarla per l'uso dell'identità del carico di lavoro con la versione più recente della libreria client Azure Identity. Se non è possibile riscrivere l'applicazione per usare la versione più recente della libreria client, è possibile configurare il pod dell'applicazione per eseguire l'autenticazione usando l'identità gestita con l'identità dei carichi di lavoro come soluzione di migrazione a breve termine.

L'integrazione Service Connector semplifica la configurazione delle connessioni per i carichi di lavoro di AKS e i servizi di supporto di Azure. Gestisce in modo sicuro le configurazioni di autenticazione e di rete e segue le procedure consigliate per la connessione ai servizi di Azure. Per altre informazioni, vedere Connettere ad Azure OpenAI in Modelli di Fonderia in servizio Azure Kubernetes utilizzando Identità del carico di lavoro Microsoft Entra e Introduzione al Connettore di servizi.