この記事では、Microsoft Entra ワークロード ID を使用してAzure Kubernetes Service (AKS) クラスターをデプロイおよび構成する方法について説明します。 この記事の手順は次のとおりです。
- OpenID Connect (OIDC) 発行者と Microsoft Entra ワークロード ID を有効にして、Azure CLI または Terraform を使用し、新しい AKS クラスターを作成するか、既存の AKS クラスターを更新します。
- ワークロード ID と Kubernetes サービス アカウントを作成します。
- トークンのフェデレーション用にマネージド ID を構成する。
- ワークロードをデプロイし、ワークロード ID を使用して認証を確認します。
- 必要に応じて、クラスター内のポッドに、Azure キー コンテナー内のシークレットへのアクセス権を付与します。
前提条件
- Azure アカウントがない場合は、開始する前に free アカウントを作成します。
- この記事では、バージョン 2.47.0 以降のAzure CLIが必要です。 Azure Cloud Shellを使用している場合は、最新バージョンが既にインストールされています。 バージョンを確認するには、
az --versionを実行します。 インストールまたはアップグレードする必要がある場合は、「Install Azure CLIを参照してください。 - クラスターの作成に使用している ID に、適切な最小限のアクセス許可が与えられていることを確認します。 詳細については、「Access と id オプションのAzure Kubernetes Service (AKS)を参照してください。
- 複数のAzure サブスクリプションがある場合は、
az account setコマンドを使用してリソースを課金する適切なサブスクリプション ID を選択します。
- Terraform がローカルにインストールされている。 インストール手順については、「 Terraform のインストール」を参照してください。
注
一部の手順を自動的に構成するのに役立てるために、Service Connector を使用できます。 詳細については、「
Terraform 構成ファイルを作成する
Terraform 構成ファイルは、Terraform が作成および管理するインフラストラクチャを定義します。
main.tfという名前のファイルを作成し、次のコードを追加して Terraform バージョンを定義し、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" {}再利用可能な変数を定義し、すべてのリソースの一意の名前を生成するために、次のコードを
main.tfに追加します。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}" }
リソース グループを作成する
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}"
次のコードを main.tf に追加して、Azure リソース グループを作成します。
location の値を、お好みのAzureリージョンと一致するように更新します。
resource "azurerm_resource_group" "this" {
name = local.resource_group_name
location = "eastus"
}
AKS クラスターで OIDC 発行者とMicrosoft Entra ワークロード ID を有効にする
新規または既存の AKS クラスターで OIDC 発行者とMicrosoft Entra ワークロード ID を有効にすることができます。
az aks create コマンドと --enable-oidc-issuer パラメーターを使用して AKS クラスターを作成し、OIDC 発行者と --enable-workload-identity パラメーターでMicrosoft Entra ワークロード ID を有効にします。 次の例では、1 つのノードを含むクラスターを作成します:
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
数分後、コマンドが完了し、クラスターに関する情報が JSON 形式で返されます。
次のコードを main.tf に追加して、OIDC 発行者を使用して AKS クラスターを作成し、Microsoft Entra ワークロード ID 有効にします。
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"
}
}
OIDC 発行者 URL を取得する
az aks show コマンドを使用して OIDC 発行者 URL を取得し、環境変数に保存します。
export AKS_OIDC_ISSUER="$(az aks show --name "${CLUSTER_NAME}" \
--resource-group "${RESOURCE_GROUP}" \
--query "oidcIssuerProfile.issuerUrl" \
--output tsv)"
環境変数には、次の例のような発行者 URL が含まれている必要があります:
https://eastus.oic.prod-aks.azure.com/00000000-0000-0000-0000-000000000000/11111111-1111-1111-1111-111111111111/
既定では、発行者はベース URL https://{region}.oic.prod-aks.azure.com/{tenant_id}/{uuid} を使用するように設定されています。ここで {region} の値は、AKS クラスターがデプロイされている場所と一致します。
{uuid}値は OIDC キーを表します。これは、クラスターごとにランダムに生成され、変更できない GUID です。
OIDC 発行者 URL を取得する main.tf に次のコードを追加します。
output "oidc_issuer_url" {
value = azurerm_kubernetes_cluster.this.oidc_issuer_url
}
マネージド ID の作成
az account showコマンドを使用して、サブスクリプション ID を取得し、環境変数に保存します。export SUBSCRIPTION="$(az account show --query id --output tsv)"az identity createコマンドを使用して、ユーザー割り当てマネージド ID を作成します。export USER_ASSIGNED_IDENTITY_NAME="myIdentity$RANDOM_ID" az identity create \ --name "${USER_ASSIGNED_IDENTITY_NAME}" \ --resource-group "${RESOURCE_GROUP}" \ --location "${LOCATION}" \ --subscription "${SUBSCRIPTION}"次の出力例は、マネージド ID の正常な作成を示しています:
{ "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" }マネージド ID のクライアント ID を取得し、
az identity showコマンドを使用して環境変数に保存します。export USER_ASSIGNED_CLIENT_ID="$(az identity show \ --resource-group "${RESOURCE_GROUP}" \ --name "${USER_ASSIGNED_IDENTITY_NAME}" \ --query 'clientId' \ --output tsv)"
マネージド ID を作成するために、次のコードを main.tf に追加します。
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
}
Kubernetes サービス アカウントを作成する
az aks get-credentialsコマンドを使用して AKS クラスターに接続します。az aks get-credentials --name "${CLUSTER_NAME}" --resource-group "${RESOURCE_GROUP}"kubernetes サービス アカウントを作成し、
kubectl applyコマンドを使用して次のマニフェストを適用して、マネージド ID のクライアント ID で注釈を付けます。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ワークロード IDが正常に作成された場合の出力の例は、次のとおりです:
serviceaccount/workload-identity-sa created
Kubernetes リソースの作成を許可するように Kubernetes アクセスを構成する
main.tfに次のコードを追加します。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) }Kubernetes サービス アカウントを作成し、マネージド ID のクライアント ID で注釈を付けるために、次のコードを
main.tfに追加します。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 } } }
フェデレーション ID 資格情報を作成する
az identity federated-credential create コマンドを使用して、マネージド ID、サービス アカウント発行者、サブジェクトの間にフェデレーション ID 資格情報を作成します。
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
注
フェデレーション ID 資格情報が追加された後に反映されるまでに数秒かかります。 フェデレーション ID 資格情報を追加した直後にトークン要求が行われると、キャッシュが更新されるまでの間、要求が失敗する可能性があります。 このイシューを回避するには、フェデレーション ID 資格情報を追加した後に若干の遅延を追加できます。
マネージド ID、サービス アカウント発行者、サブジェクトの間にフェデレーション ID 資格情報を作成する main.tf に次のコードを追加します。
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"]
}
Microsoft Entraのフェデレーション ID 資格情報の詳細については、「
Azure RBAC 承認を使用してキー コンテナーを作成する
次の例は、Azure ロールベースのアクセス制御 (Azure RBAC) 権限モデルを使用して、ポッドにキー ボールトへのアクセス権を付与する方法を紹介しています。 Azure Key Vault の Azure RBAC 権限モデルの詳細については、「Azure RBAC を使用して Azure Key Vault にアクセスするためのアプリケーションへの権限を付与する」を参照してください。
az keyvault createコマンドを使用して、消去保護とAzure RBAC 承認が有効になっているキー コンテナーを作成します。 消去保護と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-authorizationaz keyvault showコマンドを使用して、キー コンテナーのリソース ID を取得し、環境変数に保存します。export KEYVAULT_RESOURCE_ID=$(az keyvault show --resource-group "${RESOURCE_GROUP}" \ --name "${KEYVAULT_NAME}" \ --query id \ --output tsv)
次のコードを main.tf に追加して、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
}
キー コンテナー管理のために RBAC 権限を割り当てる
呼び出し元オブジェクト ID を取得し、
az ad signed-in-user showコマンドを使用して環境変数に保存します。export CALLER_OBJECT_ID=$(az ad signed-in-user show --query id -o tsv)Azure RBAC キー コンテナー シークレット責任者 ロールを割り当てて、
az role assignment createコマンドを使用して新しいキー コンテナーにシークレットを作成できるようにします。az role assignment create --assignee "${CALLER_OBJECT_ID}" \ --role "Key Vault Secrets Officer" \ --scope "${KEYVAULT_RESOURCE_ID}"
次のコードを main.tf に追加して、Azure RBAC Key Vault Secrets Officer ロールを割り当てます。これにより、新しいkey vaultでシークレットを作成し、Key Vault Secrets User ロールをユーザー割り当てマネージド ID に割り当てることができます。
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
}
シークレット アクセスの作成と構成
az keyvault secret setコマンドを使用して、Key Vault でシークレットを作成します。export KEYVAULT_SECRET_NAME="my-secret$RANDOM_ID" az keyvault secret set \ --vault-name "${KEYVAULT_NAME}" \ --name "${KEYVAULT_SECRET_NAME}" \ --value "Hello\!"ユーザー割り当てマネージド ID のプリンシパル ID を取得し、
az identity showコマンドを使用して環境変数に保存します。export IDENTITY_PRINCIPAL_ID=$(az identity show \ --name "${USER_ASSIGNED_IDENTITY_NAME}" \ --resource-group "${RESOURCE_GROUP}" \ --query principalId \ --output tsv)コマンドを使用して、
az role assignment createロールをユーザー割り当てマネージド ID に割り当てます。 この手順では、キー コンテナーからシークレットを読み取るアクセス許可をマネージド ID に付与します。az role assignment create \ --assignee-object-id "${IDENTITY_PRINCIPAL_ID}" \ --role "Key Vault Secrets User" \ --scope "${KEYVAULT_RESOURCE_ID}" \ --assignee-principal-type ServicePrincipalaz keyvault showコマンドを使用して、キー コンテナー URL の環境変数を作成します。export KEYVAULT_URL="$(az keyvault show \ --resource-group "${RESOURCE_GROUP}" \ --name ${KEYVAULT_NAME} \ --query properties.vaultUri \ --output tsv)"
次のコードを追加して main.tf キー コンテナーにシークレットを作成します。
resource "azurerm_key_vault_secret" "this" {
name = local.secret_name
value = "Hello from Key Vault"
key_vault_id = azurerm_key_vault.this.id
}
検証ポッドをデプロイしてアクセスをテストする
ポッドをデプロイして、ワークロード ID がキー コンテナー内のシークレットにアクセスできることを確認します。 次の例では、
ghcr.io/azure/azure-workload-identity/msal-goイメージを使用します。このイメージには、Microsoft Entra ワークロード ID を使用してAzure Key Vaultからシークレットを取得するサンプル アプリケーションが含まれています。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 EOFReadyコマンドを使用して、ポッドがkubectl wait状態になるまで待ちます。kubectl wait --namespace ${SERVICE_ACCOUNT_NAMESPACE} --for=condition=Ready pod/sample-workload-identity-key-vault --timeout=120sSECRET_NAMEコマンドを使用して、kubectl describe環境変数がポッドに設定されていることを確認します。kubectl describe pod sample-workload-identity-key-vault | grep "SECRET_NAME:"成功した場合、出力は次の例のようになります。
SECRET_NAME: ${KEYVAULT_SECRET_NAME}kubectl logsコマンドを使用して、ポッドがトークンを取得してリソースにアクセスできることを確認します。kubectl logs sample-workload-identity-key-vault成功した場合、出力は次の例のようになります。
I0114 10:35:09.795900 1 main.go:63] "successfully got secret" secret="Hello\\!"重要
Azure RBAC ロールの割り当てが反映されるまでに最大 10 分かかることがあります。 ポッドがシークレットにアクセスできない場合は、ロールの割り当てが反映されるまで待つ必要があります。 詳細については、Azure RBAC のトラブルシューティング を参照してください。
AKS クラスターでMicrosoft Entra ワークロード ID を無効にする
有効になっている AKS クラスターでMicrosoft Entra ワークロード ID を無効にし、az aks update コマンドを使用して --disable-workload-identity パラメーターを使用して AKS クラスターを更新します。
az aks update \
--resource-group "${RESOURCE_GROUP}" \
--name "${CLUSTER_NAME}" \
--disable-workload-identity
検証ポッドをデプロイする
次のコードを main.tf 追加して、ワークロード ID を使用してキー コンテナー内のシークレットにアクセスする検証ポッドをデプロイします。
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
}
}
}
}
Terraform を初期化する
main.tf コマンドを使用して、terraform init ファイルを含むディレクトリで Terraform を初期化します。 このコマンドは、Terraform を使用してAzureリソースを管理するために必要なAzure プロバイダーをダウンロードします。
terraform init
Terraform実行計画を作成する
terraform plan コマンドを使用して Terraform 実行プランを作成します。 このコマンドは、Terraform が Azure サブスクリプションで作成または変更するリソースを示します。
terraform plan
Terraform 構成を適用する
実行プランを確認して確認した後、 terraform apply コマンドを使用して Terraform 構成を適用します。 このコマンドは、Azure サブスクリプションの main.tf ファイルで定義されているリソースを作成または変更します。
terraform apply
デプロイメントを確認する
az aks get-credentialsコマンドを使用して AKS クラスターに接続します。az aks get-credentials --name <cluster-name> --resource-group <resource-group>kubectl get podsコマンドを使用して、検証ポッドの状態を確認します。ポッドが
Ready状態になったら、kubectl logsコマンドを使用してポッド ログを確認して、キー コンテナー シークレットにアクセスできることを確認します。kubectl logs workload-identity-test
関連コンテンツ
この記事では、Kubernetes クラスターをデプロイし、その資格情報で認証するアプリケーション ワークロードの準備としてMicrosoft Entra ワークロード ID を使用するように構成しました。 これで、アプリケーションをデプロイし、最新バージョンの Azure Identity クライアント ライブラリでワークロード ID を使用するように構成する準備ができました。 最新のクライアント ライブラリ バージョンを使用するようにアプリケーションを書き換えることができない場合は、ワークロード ID を短期的な移行ソリューションとして使ってマネージド ID を使用して認証するように、アプリケーション ポッドを設定できます。
Service Connector 統合により、AKS ワークロードとAzure バッキング サービスの接続構成を簡略化できます。 認証とネットワーク構成を安全に処理し、Azure サービスに接続するためのベスト プラクティスに従います。 詳細については、Microsoft Entra Workload Identity を使用して AKS の Foundry Models で Azure OpenAI に接続する方法と、Service Connector の概要を参照してください。