Compartilhar via


Implantar e configurar ID de carga de trabalho do Microsoft Entra em um cluster AKS (Serviço de Kubernetes do Azure)

Neste artigo, você aprenderá a implantar e configurar um cluster AKS (Serviço de Kubernetes do Azure) com ID de carga de trabalho do Microsoft Entra. As etapas neste artigo incluem:

  • Crie um cluster novo ou atualize um AKS existente usando o CLI do Azure ou o Terraform com o emissor do OpenID Connect (OIDC) e o ID de carga de trabalho do Microsoft Entra habilitados.
  • Crie uma identidade de carga de trabalho e uma conta de serviço do Kubernetes.
  • Configurar a identidade gerenciada para federação de token.
  • Implantar a carga de trabalho e verificar a autenticação com a identidade da carga de trabalho.
  • Opcionalmente, conceda a um pod no cluster acesso a segredos em um cofre de chaves da Azure.

Pré-requisitos

  • Se você não tiver uma conta Azure, crie uma conta free antes de começar.
  • Este artigo requer a versão 2.47.0 ou posterior do CLI do Azure. Se estiver usando Azure Cloud Shell, a versão mais recente já está instalada. Execute az --version para encontrar a versão. Se precisar instalar ou atualizar, consulte Instalar CLI do Azure.
  • Verifique se a identidade que você está usando para criar seu cluster tem as permissões mínimas apropriadas. Para obter mais informações, consulte Acesso e opções de identidade para o AKS (Serviço de Kubernetes do Azure).
  • Se você tiver várias assinaturas Azure, selecione a ID de assinatura apropriada na qual os recursos devem ser cobrados usando o comando az account set.
  • Terraform instalado localmente. Para obter instruções de instalação, consulte Instalar o Terraform.

Observação

Você pode usar Service Connector para ajudá-lo a configurar algumas etapas automaticamente. Para obter mais informações, consulte Tutorial: conecte-se à conta de armazenamento Azure em AKS (Serviço de Kubernetes do Azure) com o Service Connector usando ID de carga de trabalho do Microsoft Entra.

Criar o arquivo de configuração do Terraform

Os arquivos de configuração do Terraform definem a infraestrutura que o Terraform cria e gerencia.

  1. Crie um arquivo chamado main.tf e adicione o seguinte código para definir a versão do Terraform e especificar o provedor de 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. Adicione o seguinte código para main.tf definir variáveis reutilizáveis e gerar nomes exclusivos para todos os recursos:

    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}"
    }
    

Criar um grupo de recursos

Crie um grupo de recursos usando o 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}"

Adicione o código a seguir para main.tf para criar um grupo de recursos Azure. Atualize o valor location para corresponder à sua região de Azure preferencial.

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

Habilitar o emissor OIDC e a ID de carga de trabalho Microsoft Entra em um cluster AKS

Você pode habilitar o emissor OIDC e a ID de Carga de Trabalho do Microsoft Entra em um cluster AKS novo ou existente.

Crie um cluster do AKS usando o comando az aks create com o parâmetro --enable-oidc-issuer para habilitar o emissor do OIDC e o parâmetro --enable-workload-identity para habilitar ID de carga de trabalho do Microsoft Entra. O exemplo a seguir cria um cluster com um único nó:

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

Após alguns minutos, o comando será concluído e retornará informações no formato JSON sobre o cluster.

Adicione o código a seguir em main.tf para criar um cluster AKS com o emissor OIDC e a identidade de carga de trabalho do Microsoft Entra habilitados:

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"
 }
}

Recuperar a URL do emissor do OIDC

Obtenha a URL do emissor OIDC usando o comando e salve-a az aks show em uma variável ambiental.

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

A variável de ambiente deve conter a URL do emissor, semelhante ao seguinte exemplo:

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

Por padrão, o emissor é definido para usar a URL base https://{region}.oic.prod-aks.azure.com/{tenant_id}/{uuid}, em que o valor para {region} corresponde ao local ao qual o cluster do AKS é implantado. O valor {uuid} representa a chave OIDC, que é um GUID gerado aleatoriamente e imutável para cada cluster.

Adicione o seguinte código em main.tf para recuperar a URL do emissor do OIDC:

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

Criar uma identidade gerenciada

  1. Obtenha sua ID de assinatura e salve-a em uma variável de ambiente usando o az account show comando.

    export SUBSCRIPTION="$(az account show --query id --output tsv)"
    
  2. Crie uma identidade gerenciada atribuída pelo usuário usando o 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}"
    

    O exemplo de saída a seguir mostra a criação bem-sucedida de uma identidade gerenciada:

    {
      "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. Obtenha a ID do cliente da identidade gerenciada e salve-a em uma variável de ambiente usando o 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)"
    

Adicione o seguinte código a main.tf para criar uma identidade gerenciada:

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
}

Criar uma conta de serviço do Kubernetes

  1. Conecte-se ao cluster do AKS usando o az aks get-credentials comando.

    az aks get-credentials --name "${CLUSTER_NAME}" --resource-group "${RESOURCE_GROUP}"
    
  2. Crie uma conta de serviço do Kubernetes e anote-a com a ID do cliente da identidade gerenciada aplicando o manifesto a seguir usando o 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
    

    A saída a seguir mostra a criação bem-sucedida da identidade da carga de trabalho:

    serviceaccount/workload-identity-sa created
    
  1. Adicione o seguinte código a main.tf para configurar o acesso ao Kubernetes e permitir a criação de recursos no 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. Adicione o código a seguir em main.tf para criar uma conta de serviço do Kubernetes e anotá-la com o ID do cliente da identidade gerenciada:

    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
       }
     }
    }
    

Criar a credencial de identidade federada

Crie uma credencial de identidade federada entre a identidade gerenciada, o emissor da conta de serviço e o assunto usando o az identity federated-credential create comando.

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

Observação

Leva alguns segundos para que a credencial de identidade federada se propague após a adição. Se uma solicitação de token for feita imediatamente após a adição da credencial de identidade federada, a solicitação poderá falhar até que o cache seja atualizado. Para evitar esse problema, você pode adicionar um pequeno atraso depois de adicionar a credencial de identidade federada.

Adicione o seguinte código a main.tf para criar uma credencial de identidade federada entre a identidade gerenciada, o emissor da conta de serviço e o sujeito:

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"]
}

Para obter mais informações sobre credenciais de identidade federadas em Microsoft Entra, consulte Overview das credenciais de identidade federadas em Microsoft Entra ID.

Criar um cofre de chaves com autorização do RBAC Azure

O exemplo a seguir mostra como usar o modelo de permissão do RBAC (controle de acesso baseado em função) do Azure para conceder ao pod acesso ao cofre de chaves. Para obter mais informações sobre o modelo de permissão Azure RBAC para o Azure Key Vault, consulte Conceder permissão para aplicativos acessarem um cofre de chaves do Azure usando Azure RBAC.

  1. Crie um cofre de chaves com proteção contra exclusão e autorização Azure RBAC habilitada usando o comando az keyvault create. Você também pode usar um cofre de chaves existente se ele estiver configurado para proteção contra exclusão e autorização do 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. Obtenha a ID do recurso do cofre de chaves e salve-a em uma variável de ambiente usando o az keyvault show comando.

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

Adicione o seguinte código a main.tf para criar um cofre de chaves com autorização 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
}

Atribuir permissões RBAC para gerenciamento de cofre de chaves

  1. Obtenha a ID do objeto de chamador e salve-a em uma variável de ambiente usando o az ad signed-in-user show comando.

    export CALLER_OBJECT_ID=$(az ad signed-in-user show --query id -o tsv)
    
  2. Atribua a si mesmo a função Azure RBAC Key Vault Secrets Officer para que você possa criar um segredo no novo key vault usando o comando az role assignment create.

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

Adicione o seguinte código a main.tf para atribuir a si mesmo a função Azure RBAC Key Vault Secrets Officer, para que você possa criar um segredo no novo key vault e atribuir a função Key Vault Secrets User à identidade gerenciada atribuída pelo usuário.

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
}

Criar e configurar o acesso secreto

  1. Crie um segredo no cofre de chaves usando o 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. Obtenha a ID principal da identidade gerenciada atribuída pelo usuário e salve-a em uma variável de ambiente usando o az identity show comando.

    export IDENTITY_PRINCIPAL_ID=$(az identity show \
        --name "${USER_ASSIGNED_IDENTITY_NAME}" \
        --resource-group "${RESOURCE_GROUP}" \
        --query principalId \
        --output tsv)
    
  3. Atribua a função Key Vault Secrets User à identidade gerenciada atribuída pelo usuário usando o comando az role assignment create. Esta etapa concede à identidade gerenciada permissão para ler segredos do cofre de chaves.

    az role assignment create \
        --assignee-object-id "${IDENTITY_PRINCIPAL_ID}" \
        --role "Key Vault Secrets User" \
        --scope "${KEYVAULT_RESOURCE_ID}" \
        --assignee-principal-type ServicePrincipal
    
  4. Crie uma variável de ambiente para a URL do cofre de chaves usando o az keyvault show comando.

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

Adicione o seguinte código em main.tf para criar um segredo no cofre de chaves:

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

Implantar um pod de verificação e testar o acesso

  1. Implante um pod para verificar se a identidade da carga de trabalho pode acessar o segredo no cofre de chaves. O exemplo a seguir usa a imagem ghcr.io/azure/azure-workload-identity/msal-go, que contém um aplicativo de exemplo que recupera um segredo de Azure Key Vault usando ID de carga de trabalho do 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. Aguarde até que o pod esteja no estado Ready usando o comando kubectl wait.

    kubectl wait --namespace ${SERVICE_ACCOUNT_NAMESPACE} --for=condition=Ready pod/sample-workload-identity-key-vault --timeout=120s
    
  3. Verifique se a SECRET_NAME variável de ambiente está definida no pod usando o kubectl describe comando.

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

    Se bem-sucedida, a saída deverá ser semelhante ao seguinte exemplo:

    SECRET_NAME: ${KEYVAULT_SECRET_NAME}
    
  4. Verifique se os pods podem obter um token e acessar o recurso usando o kubectl logs comando.

    kubectl logs sample-workload-identity-key-vault
    

    Se bem-sucedida, a saída deverá ser semelhante ao seguinte exemplo:

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

    Importante

    As atribuições de função no Azure RBAC podem levar até 10 minutos para serem propagadas. Se o pod não conseguir acessar o segredo, talvez seja necessário aguardar a propagação da atribuição de função. Para obter mais informações, consulte Troubleshoot Azure RBAC.

Desabilitar ID de carga de trabalho do Microsoft Entra em um cluster do AKS

Desabilite ID de carga de trabalho do Microsoft Entra no cluster do AKS em que ele foi habilitado e configurado, atualize o cluster do AKS usando o comando az aks update com o parâmetro --disable-workload-identity.

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

Implantar um pod de verificação

Adicione o código a seguir em main.tf para implantar um pod de verificação que utiliza a identidade de carga de trabalho para acessar o segredo no cofre de chaves:

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
     }
   }
 }
}

Inicializar Terraform

Inicialize o Terraform no diretório que contém o main.tf arquivo usando o terraform init comando. Esse comando baixa o provedor de Azure necessário para gerenciar Azure recursos com o Terraform.

terraform init

Criar um plano de execução do Terraform

Crie um plano de execução do Terraform usando o comando terraform plan. Este comando mostra os recursos que o Terraform criará ou modificará em sua assinatura Azure.

terraform plan

Aplicar a configuração do Terraform

Depois de examinar e confirmar o plano de execução, aplique a configuração do Terraform usando o terraform apply comando. Esse comando cria ou modifica os recursos definidos em seu arquivo main.tf em sua assinatura Azure.

terraform apply

Verificar a implantação

  1. Conecte-se ao cluster do AKS usando o az aks get-credentials comando.

    az aks get-credentials --name <cluster-name> --resource-group <resource-group>
    
  2. Verifique o status do pod de verificação usando o kubectl get pods comando.

  3. Assim que o pod atingir o estado Ready, verifique se ele consegue acessar o segredo do cofre de chaves consultando os logs com o comando kubectl logs.

    kubectl logs workload-identity-test
    

Neste artigo, você implantou um cluster kubernetes e o configurou para usar ID de carga de trabalho do Microsoft Entra em preparação para que as cargas de trabalho do aplicativo se autentiquem com essa credencial. Agora você está pronto para implantar seu aplicativo e configurá-lo para usar a identidade da carga de trabalho com a versão mais recente da biblioteca de clientes Azure Identity. Se você não conseguir reescrever seu aplicativo para usar a versão mais recente da biblioteca de clientes, poderá configurar o pod do aplicativo para autenticar usando a identidade gerenciada com identidade de carga de trabalho como uma solução de migração de curto prazo.

A integração Service Connector ajuda a simplificar a configuração de conexão das cargas de trabalho no AKS e serviços de suporte do Azure. Ele lida com segurança com autenticação e configurações de rede e segue as práticas recomendadas para se conectar a serviços de Azure. Para obter mais informações, consulte Conectar ao OpenAI do Azure em Modelos da Fábrica no AKS usando Identidade de Carga de Trabalho do Microsoft Entra e a introdução ao Conector de Serviço.