Azure Kubernetes Service (AKS) クラスターで Secrets Store CSI Driver 用 Azure Key Vault プロバイダーを使う

シークレット ストア コンテナー ストレージ インターフェイス (CSI) ドライバー用の Azure Key Vault プロバイダーを使用すると、シークレット ストアとして Azure Key Vault を CSI ボリューム経由で Azure Kubernetes Service (AKS) クラスターと統合できます。

機能

  • CSI ボリュームを使用してシークレット、キー、証明書をポッドにマウントします。
  • CSI インライン ボリュームをサポートします。
  • 複数のシークレット ストア オブジェクトを 1 つのボリュームとしてマウントすることがサポートされています。
  • SecretProviderClass カスタム リソース定義 (CRD) を使用してポッドの移植性をサポートします。
  • Windows コンテナーがサポートされています。
  • Kubernetes シークレットと同期します。
  • マウントされたコンテンツと同期された Kubernetes シークレットの自動ローテーションがサポートされています。

制限事項

  • ConfigMapまたはSecretsubPath ボリューム マウントとして使用するコンテナーは、シークレットがローテーションされるときに自動更新を受け取りません。これは Kubernetes の制限事項です。 変更を有効にするには、アプリケーションでファイル システムの変更を監視するか、ポッドを再起動して、変更されたファイルを再読み込みする必要があります。 詳細については、Secrets Store CSI Driver の既知の制限事項に関するページを参照してください。
  • アドオンは、ノード リソース グループ (azurekeyvaultsecretsprovider-xxxxx) に MC_ という名前のマネージド ID を作成し、仮想マシン スケール セットに自動的に割り当てます。 このマネージド ID または独自のマネージド ID を使用して、キー コンテナーにアクセスできます。 ID を作成できないようにすることはサポートされていません。

前提条件

  • Azure サブスクリプションをお持ちでない場合は、開始する前に 無料アカウント を作成してください。

  • バージョン 1.6 以降の Terraform。

  • Azure CLIインストールされ、ログインしています。最新バージョンをインストールします。

  • AKS と Key Vault リソースを作成するためのアクセス許可。

  • 次のコマンドを使用して、Azure CLIでAzure サブスクリプションを設定します。 <subscriptionId> は、サブスクリプション ID で置き換えてください。

    az account set --subscription <subscriptionId>
    

ネットワーク

役割

AKS クラスターを作成する

シークレット ストア CSI ドライバーのサポート用に Azure Key Vault プロバイダーを使用して AKS クラスターを作成します。

  1. コマンドで使用される変数を作成して、AKS クラスターと Key Vault を作成します。

    export RANDOM_STRING=$(printf '%05d%05d' "$RANDOM" "$RANDOM")
    export KEYVAULT_NAME=myKeyVault${RANDOM_STRING}
    export RESOURCE_GROUP=myResourceGroup
    export CLUSTER_NAME=myAKSCluster
    export LOCATION=eastus2
    

    Azure Key Vault の名前は、グローバルに一意である必要があります。英数字 (ハイフンを含む)、3 ~ 24 文字です。 キー コンテナー名は、 KEYVAULT_NAME 変数の myKeyVault 値と RANDOM_STRING 変数の 10 文字の文字列を連結します。

  2. az group create コマンドを使用して、Azure リソース グループを作成します。

    az group create --name $RESOURCE_GROUP --location $LOCATION
    
  3. az aks create コマンドと --enable-addons azure-keyvault-secrets-provider パラメーターを使って、シークレット ストア CSI ドライバー機能用に Azure Key Vault プロバイダーを含む AKS クラスターを作成します。

    --enable-addons パラメーターは、キー コンテナーに対する認証に使用できる azurekeyvaultsecretsprovider-xxxx という名前のユーザー割り当てマネージド ID を作成します。 マネージド ID はノード リソース グループ (MC_) に格納され、仮想マシン スケール セットに自動的に割り当てられます。 このマネージド ID または独自のマネージド ID を使用して、キー コンテナーにアクセスできます。 ID を作成できないようにすることはサポートされていません。

    az aks create \
      --name $CLUSTER_NAME \
      --resource-group $RESOURCE_GROUP \
      --enable-addons azure-keyvault-secrets-provider \
      --generate-ssh-keys
    

    ヒント

    Microsoft Entra ワークロード ID を使用する場合は、 az aks create コマンドに --enable-oidc-issuer パラメーターと --enable-workload-identity パラメーターを含める必要があります。

AKS クラスターを作成する

main.tf ファイルを作成し、次のテスト済みのサンプル構成をコピーします。 Azure Terraform GitHub リポジトリでは、サンプルが保持されます。 このサンプルでは、リソース グループ、AKS クラスター、Azure Key Vault、シークレットの例、必要なロールの割り当てを作成します。

terraform {
  required_version = ">= 1.5.0"

  required_providers {
    azurerm = {
      source  = "hashicorp/azurerm"
      version = "~> 3.116"
    }
    random = {
      source  = "hashicorp/random"
      version = "~> 3.6"
    }
  }
}

provider "azurerm" {
  features {
    resource_group {
      prevent_deletion_if_contains_resources = false
    }
  }
}

data "azurerm_client_config" "current" {}

resource "random_string" "suffix" {
  length  = 6
  upper   = false
  special = false
}

locals {
  location            = "eastus"
  resource_group_name = "rg-aks-kv-csi-demo-${random_string.suffix.result}"
  aks_name            = "aks-kv-csi-demo"
  key_vault_name      = "kvcsidemo${random_string.suffix.result}"
  secret_name         = "ExampleSecret"
}

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

resource "azurerm_log_analytics_workspace" "this" {
  name                = "law-aks-kv-csi-demo"
  location            = azurerm_resource_group.this.location
  resource_group_name = azurerm_resource_group.this.name
  sku                 = "PerGB2018"
  retention_in_days   = 30
}

resource "azurerm_kubernetes_cluster" "this" {
  name                      = local.aks_name
  location                  = azurerm_resource_group.this.location
  resource_group_name       = azurerm_resource_group.this.name
  dns_prefix                = "akskvcsidemo"
  kubernetes_version        = null
  oidc_issuer_enabled       = true
  workload_identity_enabled = true

  default_node_pool {
    name       = "system"
    node_count = 1
    vm_size    = "Standard_D2s_v3"

    upgrade_settings {
      drain_timeout_in_minutes      = 0
      max_surge                     = "10%"
      node_soak_duration_in_minutes = 0
    }
  }

  identity {
    type = "SystemAssigned"
  }

  key_vault_secrets_provider {
    secret_rotation_enabled = false
  }

  oms_agent {
    log_analytics_workspace_id = azurerm_log_analytics_workspace.this.id
  }

  network_profile {
    network_plugin    = "azure"
    load_balancer_sku = "standard"
  }

  tags = {
    scenario = "aks-keyvault-csi"
  }
}

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"
  purge_protection_enabled      = false
  soft_delete_retention_days    = 7
  enable_rbac_authorization     = true
  public_network_access_enabled = true
}

resource "azurerm_role_assignment" "current_user_kv_admin" {
  scope                = azurerm_key_vault.this.id
  role_definition_name = "Key Vault Administrator"
  principal_id         = data.azurerm_client_config.current.object_id
}

resource "azurerm_key_vault_secret" "example" {
  name         = local.secret_name
  value        = "HelloFromKeyVault"
  key_vault_id = azurerm_key_vault.this.id

  depends_on = [
    azurerm_role_assignment.current_user_kv_admin
  ]
}

resource "azurerm_role_assignment" "aks_csi_secrets_user" {
  scope                = azurerm_key_vault.this.id
  role_definition_name = "Key Vault Secrets User"
  # This is the managed identity automatically created by the AKS Key Vault CSI addon.
  principal_id = azurerm_kubernetes_cluster.this.key_vault_secrets_provider[0].secret_identity[0].object_id
}

output "resource_group_name" {
  value = azurerm_resource_group.this.name
}

output "aks_cluster_name" {
  value = azurerm_kubernetes_cluster.this.name
}

output "key_vault_name" {
  value = azurerm_key_vault.this.name
}

output "key_vault_secret_name" {
  value = azurerm_key_vault_secret.example.name
}

output "tenant_id" {
  value = data.azurerm_client_config.current.tenant_id
}

output "aks_csi_client_id" {
  value = azurerm_kubernetes_cluster.this.key_vault_secrets_provider[0].secret_identity[0].client_id
}

output "aks_csi_object_id" {
  value = azurerm_kubernetes_cluster.this.key_vault_secrets_provider[0].secret_identity[0].object_id
}
  1. 構成をデプロイします。 Bash セッションから、次のコマンドを実行してリソースをデプロイします。

    terraform init
    terraform validate
    terraform plan
    terraform apply
    
  2. Terraform 出力の残りのコマンドで使用される変数を設定します。

    export RESOURCE_GROUP=$(terraform output -raw resource_group_name)
    export CLUSTER_NAME=$(terraform output -raw aks_cluster_name)
    export KEYVAULT_NAME=$(terraform output -raw key_vault_name)
    

既存の AKS クラスターを更新する

シークレット ストア CSI ドライバーのサポートのために、Azure Key Vault プロバイダーを使用して既存の AKS クラスターを更新します。

  1. コマンドで使用される変数を作成します。 既存の AKS クラスターまたは Key Vault を更新するために必要に応じて値を置き換えます。

    たとえば、既存のキー コンテナーを使用している場合は、RANDOM_STRING変数を使用せずに、KEYVAULT_NAME変数の値を置き換えます。

    キー コンテナーがない場合、Azure Key Vault の名前はグローバルに一意で、ハイフンを含む英数字、3 から 24 文字である必要があります。 キー コンテナー名は、 KEYVAULT_NAME 変数の myKeyVault 値と RANDOM_STRING 変数の 10 文字の文字列を連結します。 キー ボールトは、この記事の後半で作成できます。

    export RANDOM_STRING=$(printf '%05d%05d' "$RANDOM" "$RANDOM")
    export KEYVAULT_NAME=myKeyVault${RANDOM_STRING}
    export RESOURCE_GROUP=myResourceGroup
    export CLUSTER_NAME=myAKSCluster
    export LOCATION=eastus2
    
  2. az aks enable-addons コマンドを使用して、Azure Key Vault プロバイダー for Secrets Store CSI Driver 機能を使用して既存の AKS クラスターを更新し、azure-keyvault-secrets-provider アドオンを有効にします。 このアドオンでは、キー コンテナーの認証に使用できるユーザー割り当てマネージド ID が作成されます。

    az aks enable-addons \
      --addons azure-keyvault-secrets-provider \
      --name $CLUSTER_NAME \
      --resource-group $RESOURCE_GROUP
    

    Azure Key Vault シークレット プロバイダーを有効にすると、AKS によって azurekeyvaultsecretsprovider-xxxx という名前のマネージド ID が作成され、キー コンテナーに対する認証に使用できます。 マネージド ID はノード リソース グループ (MC_) に格納され、仮想マシン スケール セットに自動的に割り当てられます。 このマネージド ID または独自のマネージド ID を使用して、キー コンテナーにアクセスできます。 ID を作成できないようにすることはサポートされていません。

マネージド ID とキー コンテナー プロバイダーのインストールを確認する

次のコマンドでは、 $CLUSTER_NAME 変数と $RESOURCE_GROUP 変数を使用します。 Azure CLIワークフローは、これらの変数を以前に定義し、Terraform ワークフローはデプロイ後に出力から変数を設定します。

マネージド ID を確認する

次の手順を使用して、マネージド ID が作成され、クラスターの仮想マシン スケール セットに割り当てられていることを確認します。

  1. az aks show コマンドを使用して、マネージド ID が作成され、クラスターに割り当てられたかどうかを確認します。

    az aks show \
      --name $CLUSTER_NAME \
      --resource-group $RESOURCE_GROUP \
      --query addonProfiles
    
    {
      "azureKeyvaultSecretsProvider": {
        "config": {
          "enableSecretRotation": "false",
          "rotationPollInterval": "2m"
        },
        "enabled": true,
        "identity": {
          "clientId": "00001111-aaaa-2222-bbbb-3333cccc4444",
          "objectId": "aaaaaaaa-0000-1111-2222-bbbbbbbbbbbb",
          "resourceId": "/subscriptions/<subscriptionID>/resourcegroups/MC_myResourceGroup_myAKSCluster_eastus2/providers/Microsoft.ManagedIdentity/userAssignedIdentities/azurekeyvaultsecretsprovider-myakscluster"
        }
      }
    }
    

    resourceId プロパティには、リソース グループと ID の名前azurekeyvaultsecretsprovider-myaksclusterが表示されます。

  2. マネージド ID がノード リソース グループの仮想マシン スケール セットに割り当てられていることを確認します。

    NODE_RG=$(az aks show \
      --name $CLUSTER_NAME \
      --resource-group $RESOURCE_GROUP \
      --query nodeResourceGroup --output tsv)
    
    VMSS_NAME=$(az vmss list \
      --resource-group $NODE_RG \
      --query [].name --output tsv)
    
    az vmss show --name $VMSS_NAME --resource-group $NODE_RG --query '[id, identity]'
    

    この出力には、仮想マシン スケール セットMicrosoft.Compute/virtualMachineScaleSetsリソース ID と、ID が仮想マシン スケール セットに割り当てられていることを確認するuserAssignedIdentitiesのリソース ID を持つ azurekeyvaultsecretsprovider-myakscluster プロパティが表示されます。

Secrets Store CSI Driver 用 Azure Key Vault プロバイダーのインストールを確認する

  1. az aks get-credentials コマンドを使用して、AKS クラスターの資格情報を取得します。

    az aks get-credentials \
      --name $CLUSTER_NAME \
      --resource-group $RESOURCE_GROUP
    
  2. kubectl get pods コマンドを使用してインストールが完了したことを確認します。このコマンドでは、secrets-store-csi-driversecrets-store-provider-azureラベルを持つすべてのポッドがkube-system名前空間に一覧表示されます。

    kubectl get pods -n kube-system -l 'app in (secrets-store-csi-driver,secrets-store-provider-azure)' -o wide
    

    -o wide フラグを使用すると、各ポッドが実行されているノードが出力に含まれます。

    出力は次の出力例のようになります。

    NAME                                     READY   STATUS    RESTARTS   AGE    NODE
    aks-secrets-store-csi-driver-4vpkj       3/3     Running   2          4m25s  aks-nodepool1-12345678-vmss000002
    aks-secrets-store-csi-driver-ctjq6       3/3     Running   2          4m21s  aks-nodepool1-12345678-vmss000001
    aks-secrets-store-csi-driver-tlvlq       3/3     Running   2          4m24s  aks-nodepool1-12345678-vmss000000
    aks-secrets-store-provider-azure-5p4nb   1/1     Running   0          4m21s  aks-nodepool1-12345678-vmss000000
    aks-secrets-store-provider-azure-6pqmv   1/1     Running   0          4m24s  aks-nodepool1-12345678-vmss000001
    aks-secrets-store-provider-azure-f5qlm   1/1     Running   0          4m25s  aks-nodepool1-12345678-vmss000002
    

新しいキー コンテナーを作成する

az keyvault create コマンドを実行して、Azure RBAC が有効になっている新しいキー コンテナーを作成します。

az keyvault create \
  --name $KEYVAULT_NAME \
  --resource-group $RESOURCE_GROUP \
  --location $LOCATION \
  --enable-rbac-authorization

--enable-rbac-authorization パラメーターを含めない場合でも、新しいキー コンテナーを作成すると、Azure RBAC は既定で有効になります。

key vaultアクセス許可モデルとAzure RBAC の詳細については、「ロールベースのアクセス制御を使用した Azure Key Vault キー、証明書、シークレットへのアクセスの準備」を参照してください。

既存のキーボールトを更新する

az keyvault update コマンドを実行して、Azure ロールベースのアクセス制御 (Azure RBAC) を使用して、既存のキーコンテナーを更新します。 --enable-rbac-authorization パラメーターは、AZURE RBAC が無効になっている既存のキー コンテナーを更新するときに、Azure RBAC を有効にするために必要です。

az keyvault update \
  --name $KEYVAULT_NAME \
  --resource-group $RESOURCE_GROUP \
  --enable-rbac-authorization

キー コンテナーのアクセス許可モデルと Azure RBAC の詳細については、「Azure ロールベースのアクセス制御を使用して Key Vault キー、証明書、シークレットへのアクセスを提供する」を参照してください。

ロールの割り当てとシークレットをキー コンテナーに追加する

  1. az keyvault show コマンドを実行して、キー コンテナーで Azure RBAC が有効になっていることを確認します。

    az keyvault show \
      --name $KEYVAULT_NAME \
      --resource-group $RESOURCE_GROUP \
      --query properties.enableRbacAuthorization
    

    出力は trueする必要があります。

  2. 次の手順でキー コンテナー シークレットを追加できるように、 az role assignment create コマンドを使用して、ユーザー アカウントのロールの割り当てをキー コンテナー スコープに追加します。

    一意識別子 を持つ b86a8fe4-44ce-4948-aee5-eccb2c155cd7 ロールが追加され、名前または一意識別子のいずれかを使用できます。 ロール名が変更された場合の問題を防ぐために、一意の識別子を使用することをお勧めします。

    KEYVAULT_ID=$(az keyvault show \
      --name $KEYVAULT_NAME \
      --resource-group $RESOURCE_GROUP \
      --query id -o tsv)
    
    MYID=$(az ad signed-in-user show --query id --output tsv)
    
    az role assignment create \
      --assignee-object-id $MYID \
      --role "b86a8fe4-44ce-4948-aee5-eccb2c155cd7" \
      --scope $KEYVAULT_ID \
      --assignee-principal-type User
    

    ロールの割り当てが有効になるまで数分かかる場合があります。 ロールの割り当てが作成されたことを確認するには、次のコマンドを使用します。

    az role assignment list \
      --assignee-object-id $MYID \
      --scope $KEYVAULT_ID \
      --query '[].{Role:roleDefinitionName, Scope:scope}' \
      --output table
    
  3. ExampleSecret コマンドを使用して、キー コンテナーに az keyvault secret set という名前のプレーンテキスト シークレットを作成します。

    キー コンテナーには、キー、シークレット、証明書を格納できます。 value パラメーターは、RANDOM_STRING変数を使用してシークレットの一意の値を作成します。

    az keyvault secret set \
      --vault-name $KEYVAULT_NAME \
      --name ExampleSecret \
      --value MyAKSExampleSecret${RANDOM_STRING}
    
  4. az keyvault secret show コマンドを使用して、シークレットがキー コンテナーに追加されたことを確認します。

    az keyvault secret show --vault-name $KEYVAULT_NAME --name ExampleSecret
    

新しいキー コンテナーを作成する

前述の Terraform サンプルでは、Azure RBAC が有効になっている新しいキー コンテナーを作成し、必要なロールを割り当てて、ExampleSecretを作成します。 個別の構成の更新は必要ありません。

  1. Terraform の出力から Key Vault 名を取得します。

    KEYVAULT_NAME=$(terraform output -raw key_vault_name)
    
  2. az keyvault secret show コマンドを使用して、ExampleSecretがキー コンテナーに追加されたことを確認します。

    az keyvault secret show \
     --vault-name $KEYVAULT_NAME \
     --name ExampleSecret
    

リソースをクリーンアップする

次の記事に進み、これらのリソースが必要な場合は、次の手順を無視してください。 それ以外の場合は、完了し、次の記事に進む予定がない場合は、不要なコストを回避するために、この記事で作成したリソースを削除する必要があります。

  1. ローカルの .kube/config ファイルからクラスターの資格情報を削除します。

    KUBE_CONTEXT=$(kubectl config current-context)
    kubectl config delete-context $KUBE_CONTEXT
    
  2. MC_ コマンドを使用して、ノード リソース グループ (az group delete) 内のリソースを含む、リソース グループとその中のすべてのリソースを削除します。

    az group delete --name $RESOURCE_GROUP --yes --no-wait
    

terraform destroy コマンドは、現在の Terraform 構成および状態ファイルで定義されているすべてのリソースを削除します。 このコマンドは、この記事で使用されている作業ディレクトリからのみ実行してください。

Warnung

既存のリソースまたは運用リソースを使用している場合は、実行する前に実行プランを慎重に確認してください。

terraform plan -destroy

削除しても安全である場合を除き、共有またはインポートされたインフラストラクチャに対して terraform destroy を実行しないでください。 詳細については、Terraform destroy コマンドの Terraform ドキュメントを参照してください。

  1. ローカルの .kube/config ファイルからクラスターの資格情報を削除します。

    KUBE_CONTEXT=$(kubectl config current-context)
    kubectl config delete-context $KUBE_CONTEXT
    
  2. 次のコマンドを実行して、この記事で作成したリソースを削除します。

    terraform destroy
    

次のステップ

この記事では、AKS クラスターで Secrets Store CSI Driver 用 Azure Key Vault プロバイダーを使う方法について説明しました。 Terraform サンプルでは、アドオン ID に Key Vault 内のシークレットへのアクセス権を付与します。 SecretProviderClassを構成するか、別の ID を使用するには、次の記事に進みます。