使用 Azure Key Vault 秘密提供者延伸模組,將秘密擷取至已啟用 Azure Arc 的 Kubernetes 叢集

針對 Secrets Store CSI Driver 的 Azure Key Vault 提供者可讓您透過 CSI 磁碟區,將 Azure Key Vault 與 Kubernetes 叢集整合為祕密存放區。 針對已啟用 Azure Arc 的 Kubernetes 叢集,您可以安裝 Azure Key Vault 秘密提供者延伸模組來擷取秘密。

Azure Key Vault 秘密提供者延伸模組的功能包括:

  • 使用 CSI 內嵌磁碟區將秘密/金鑰/憑證掛接至 Pod
  • 支援使用 SecretProviderClass CRD 的 Pod 可攜性
  • 支援 Linux 和 Windows 容器
  • 支援與 Kubernetes 秘密同步處理
  • 支援自動輪替秘密
  • 延伸模組元件會部署到可用性區域,使其達到區域備援

必要條件

  • 叢集,其支援的 Kubernetes 散發套件已連線至 Azure Arc。此案例目前支援下列 Kubernetes 散發套件:
    • 叢集 API Azure
    • Azure Stack HCI 上的 Azure Kubernetes Service (AKS) 叢集
    • 由 Azure Arc 啟用的 AKS
    • Google Kubernetes Engine
    • OpenShift Kubernetes 散發套件
    • Canonical Kubernetes 散發套件
    • Elastic Kubernetes Service
    • Tanzu Kubernetes Grid
    • Azure Red Hat OpenShift
  • 確定您已符合叢集延伸模組的一般必要條件。 您必須使用 0.4.0 版或更新版本的 k8s-extension Azure CLI 延伸模組。

在已啟用 Arc 的 Kubernetes 叢集上安裝 Azure Key Vault 秘密提供者延伸模組

您可以在 Azure 入口網站中、使用 Azure CLI 或藉由部署 ARM 範本,在已連線的叢集上安裝 Azure Key Vault 秘密提供者延伸模組。

每個已啟用 Azure Arc 的 Kubernetes 叢集上只能部署一個延伸模組執行個體。

提示

如果叢集位於輸出 Proxy 伺服器後方,請務必先使用 Proxy 組態選項將其連線到 Azure Arc,再安裝延伸模組。

Azure 入口網站

  1. Azure 入口網站中,瀏覽至 [Kubernetes - Azure Arc],然後選取您的叢集。

  2. 選取 [設定] 之下的 [延伸模組],然後選取 [+ 新增]

    Screenshot showing the Extensions page for an Arc-enabled Kubernetes cluster in the Azure portal.

  3. 從可用的延伸模組清單中,選取 [Azure Key Vault 秘密提供者] 以部署最新版的延伸模組。

    Screenshot of the Azure Key Vault Secrets Provider extension in the Azure portal.

  4. 遵循相關提示來部署延伸模組。 如有需要,請變更 [設定] 索引標籤上的預設選項來自訂安裝。

Azure CLI

  1. 設定環境變數:

    export CLUSTER_NAME=<arc-cluster-name>
    export RESOURCE_GROUP=<resource-group-name>
    
  2. 執行下列命令,以安裝秘密存放區 CSI 驅動程式和 Azure Key Vault 秘密提供者延伸模組:

    az k8s-extension create --cluster-name $CLUSTER_NAME --resource-group $RESOURCE_GROUP --cluster-type connectedClusters --extension-type Microsoft.AzureKeyVaultSecretsProvider --name akvsecretsprovider
    

您應該會看到類似此範例的輸出。 秘密提供者 Helm 圖表部署至叢集可能需要幾分鐘的時間。

{
  "aksAssignedIdentity": null,
  "autoUpgradeMinorVersion": true,
  "configurationProtectedSettings": {},
  "configurationSettings": {},
  "customLocationSettings": null,
  "errorInfo": null,
  "extensionType": "microsoft.azurekeyvaultsecretsprovider",
  "id": "/subscriptions/xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx/resourceGroups/$RESOURCE_GROUP/providers/Microsoft.Kubernetes/connectedClusters/$CLUSTER_NAME/providers/Microsoft.KubernetesConfiguration/extensions/akvsecretsprovider",
  "identity": {
    "principalId": "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx",
    "tenantId": null,
    "type": "SystemAssigned"
  },
  "location": null,
  "name": "akvsecretsprovider",
  "packageUri": null,
  "provisioningState": "Succeeded",
  "releaseTrain": "Stable",
  "resourceGroup": "$RESOURCE_GROUP",
  "scope": {
    "cluster": {
      "releaseNamespace": "kube-system"
    },
    "namespace": null
  },
  "statuses": [],
  "systemData": {
    "createdAt": "2022-05-12T18:35:56.552889+00:00",
    "createdBy": null,
    "createdByType": null,
    "lastModifiedAt": "2022-05-12T18:35:56.552889+00:00",
    "lastModifiedBy": null,
    "lastModifiedByType": null
  },
  "type": "Microsoft.KubernetesConfiguration/extensions",
  "version": "1.1.3"
}

ARM 範本

  1. 使用下列格式建立 .json 檔案。 務必更新 <cluster-name> 值,以參考您的叢集。

    {
        "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#",
        "contentVersion": "1.0.0.0",
        "parameters": {
            "ConnectedClusterName": {
                "defaultValue": "<cluster-name>",
                "type": "String",
                "metadata": {
                    "description": "The Connected Cluster name."
                }
            },
            "ExtensionInstanceName": {
                "defaultValue": "akvsecretsprovider",
                "type": "String",
                "metadata": {
                    "description": "The extension instance name."
                }
            },
            "ExtensionVersion": {
                "defaultValue": "",
                "type": "String",
                "metadata": {
                    "description": "The version of the extension type."
                }
            },
            "ExtensionType": {
                "defaultValue": "Microsoft.AzureKeyVaultSecretsProvider",
                "type": "String",
                "metadata": {
                    "description": "The extension type."
                }
            },
            "ReleaseTrain": {
                "defaultValue": "stable",
                "type": "String",
                "metadata": {
                    "description": "The release train."
                }
            }
        },
        "functions": [],
        "resources": [
            {
                "type": "Microsoft.KubernetesConfiguration/extensions",
                "apiVersion": "2021-09-01",
                "name": "[parameters('ExtensionInstanceName')]",
                "identity": {
                 "type": "SystemAssigned"
                },
                "properties": {
                    "extensionType": "[parameters('ExtensionType')]",
                    "releaseTrain": "[parameters('ReleaseTrain')]",
                    "version": "[parameters('ExtensionVersion')]"
                },
                "scope": "[concat('Microsoft.Kubernetes/connectedClusters/', parameters('ConnectedClusterName'))]"
            }
        ]
    }
    
  2. 現在,使用下列 Azure CLI 命令來設定環境變數:

    export TEMPLATE_FILE_NAME=<template-file-path>
    export DEPLOYMENT_NAME=<desired-deployment-name>
    
  3. 最後,執行此 Azure CLI 命令以安裝 Azure Key Vault 秘密提供者延伸模組:

    az deployment group create --name $DEPLOYMENT_NAME --resource-group $RESOURCE_GROUP --template-file $TEMPLATE_FILE_NAME
    

您現在應該能夠檢視秘密提供者資源,並在您的叢集中使用延伸模組。

驗證延伸模組安裝

若要確認已成功安裝 Azure Key Vault 秘密提供者延伸模組,請執行下列命令。

az k8s-extension show --cluster-type connectedClusters --cluster-name $CLUSTER_NAME --resource-group $RESOURCE_GROUP --name akvsecretsprovider

您應該會看到類似此範例的輸出。

{
  "aksAssignedIdentity": null,
  "autoUpgradeMinorVersion": true,
  "configurationProtectedSettings": {},
  "configurationSettings": {},
  "customLocationSettings": null,
  "errorInfo": null,
  "extensionType": "microsoft.azurekeyvaultsecretsprovider",
  "id": "/subscriptions/xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx/resourceGroups/$RESOURCE_GROUP/providers/Microsoft.Kubernetes/connectedClusters/$CLUSTER_NAME/providers/Microsoft.KubernetesConfiguration/extensions/akvsecretsprovider",
  "identity": {
    "principalId": "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx",
    "tenantId": null,
    "type": "SystemAssigned"
  },
  "location": null,
  "name": "akvsecretsprovider",
  "packageUri": null,
  "provisioningState": "Succeeded",
  "releaseTrain": "Stable",
  "resourceGroup": "$RESOURCE_GROUP",
  "scope": {
    "cluster": {
      "releaseNamespace": "kube-system"
    },
    "namespace": null
  },
  "statuses": [],
  "systemData": {
    "createdAt": "2022-05-12T18:35:56.552889+00:00",
    "createdBy": null,
    "createdByType": null,
    "lastModifiedAt": "2022-05-12T18:35:56.552889+00:00",
    "lastModifiedBy": null,
    "lastModifiedByType": null
  },
  "type": "Microsoft.KubernetesConfiguration/extensions",
  "version": "1.1.3"
}

建立或選取 Azure Key Vault

接下來,指定要與已連線叢集搭配使用的 Azure Key Vault。 如果您還沒有金鑰保存庫,請使用下列命令建立新的金鑰保存庫。 請記住,金鑰保存庫的名稱必須是全域唯一的名稱。

設定下列環境變數:

export AKV_RESOURCE_GROUP=<resource-group-name>
export AZUREKEYVAULT_NAME=<AKV-name>
export AZUREKEYVAULT_LOCATION=<AKV-location>

接下來,執行下列命令:

az keyvault create -n $AZUREKEYVAULT_NAME -g $AKV_RESOURCE_GROUP -l $AZUREKEYVAULT_LOCATION

Azure Key Vault 可儲存金鑰、秘密和憑證。 在此範例中,您可以使用下列命令來設定稱為 DemoSecret 的純文字秘密:

az keyvault secret set --vault-name $AZUREKEYVAULT_NAME -n DemoSecret --value MyExampleSecret

在繼續進行下一節之前,請記下下列屬性:

  • 金鑰保存庫中的祕密物件名稱
  • 物件類型 (祕密、金鑰或憑證)
  • 金鑰保存庫資源的名稱
  • 金鑰保存庫所屬訂用帳戶的 Azure 租用戶識別碼

提供身分識別以存取 Azure Key Vault

目前,可以透過服務主體存取已啟用 Arc 的叢集上的秘密存放區 CSI 驅動程式。 請遵循下列步驟來提供可存取您的金鑰保存庫的身分識別。

  1. 請遵循步驟以在 Azure 中建立服務主體。 記下此步驟中產生的用戶端識別碼和用戶端密碼。

  2. 接下來, 確保 Azure Key Vault 具有所建立服務主體的 GET 權限

  3. 使用第 1 個步驟的用戶端識別碼和用戶端密碼,在連線的叢集上建立 Kubernetes 秘密:

    kubectl create secret generic secrets-store-creds --from-literal clientid="<client-id>" --from-literal clientsecret="<client-secret>"
    
  4. 為所建立的秘密加上標籤:

    kubectl label secret secrets-store-creds secrets-store.csi.k8s.io/used=true
    
  5. 使用下列 YAML 建立 SecretProviderClass,並填入金鑰保存庫名稱、租用戶識別碼和物件的值,以便從 AKV 執行個體擷取:

    # This is a SecretProviderClass example using service principal to access Keyvault
    apiVersion: secrets-store.csi.x-k8s.io/v1
    kind: SecretProviderClass
    metadata:
      name: akvprovider-demo
    spec:
      provider: azure
      parameters:
        usePodIdentity: "false"
        keyvaultName: <key-vault-name>
        cloudName:                           # Defaults to AzurePublicCloud
        objects:  |
          array:
            - |
              objectName: DemoSecret
              objectType: secret             # object types: secret, key or cert
              objectVersion: ""              # [OPTIONAL] object versions, default to latest if empty
        tenantId: <tenant-Id>                # The tenant ID of the Azure Key Vault instance
    

    若要搭配國家雲使用,請將 cloudName 變更為 Azure Government 的 AzureUSGovernmentCloud,或變更為 21Vianet 營運的 AzureChinaCloud for Microsoft Azure。

  6. 將 SecretProviderClass 套用至您的叢集:

    kubectl apply -f secretproviderclass.yaml
    
  7. 使用下列 YAML 建立 Pod,並填入您的身分識別名稱:

    # This is a sample pod definition for using SecretProviderClass and service principal to access Keyvault
    kind: Pod
    apiVersion: v1
    metadata:
      name: busybox-secrets-store-inline
    spec:
      containers:
        - name: busybox
          image: k8s.gcr.io/e2e-test-images/busybox:1.29
          command:
            - "/bin/sleep"
            - "10000"
          volumeMounts:
          - name: secrets-store-inline
            mountPath: "/mnt/secrets-store"
            readOnly: true
      volumes:
        - name: secrets-store-inline
          csi:
            driver: secrets-store.csi.k8s.io
            readOnly: true
            volumeAttributes:
              secretProviderClass: "akvprovider-demo"
            nodePublishSecretRef:                       
              name: secrets-store-creds
    
  8. 將 Pod 套用至您的叢集:

    kubectl apply -f pod.yaml
    

驗證秘密

Pod 啟動之後,便可使用您在部署 YAML 中指定的磁碟區路徑上掛接的內容。

## show secrets held in secrets-store
kubectl exec busybox-secrets-store-inline -- ls /mnt/secrets-store/

## print a test secret 'DemoSecret' held in secrets-store
kubectl exec busybox-secrets-store-inline -- cat /mnt/secrets-store/DemoSecret

其他組態選項

Azure Key Vault 秘密提供者延伸模組支援 Helm 圖表組態

下列組態設定經常用於 Azure Key Vault 秘密提供者延伸模組:

組態設定 預設 描述
enableSecretRotation false 布林值類型。 如果 true,請定期使用來自外部秘密存放區的最新內容來更新 Pod 掛接和 Kubernetes 秘密
rotationPollInterval 2 公尺 如果 enableSecretRotationtrue,此設定會指定秘密輪替輪詢間隔持續時間。 您可以根據需要重新同步所有 Pod 和 Kubernetes 秘密的掛接內容的頻率,調整此持續時間。
syncSecret.enabled false 布林值輸入。 在某些情況下,您可以建立 Kubernetes 秘密來鏡像處理掛接的內容。 如果 true,則 SecretProviderClass 允許 secretObjects 欄位定義已同步 Kubernetes 秘密物件的所需狀態。

使用 az k8s-extension create 命令安裝延伸模組時,可以指定這些設定:

az k8s-extension create --cluster-name $CLUSTER_NAME --resource-group $RESOURCE_GROUP --cluster-type connectedClusters --extension-type Microsoft.AzureKeyVaultSecretsProvider --name akvsecretsprovider --configuration-settings secrets-store-csi-driver.enableSecretRotation=true secrets-store-csi-driver.rotationPollInterval=3m secrets-store-csi-driver.syncSecret.enabled=true

您也可使用 az k8s-extension update 命令,在安裝之後變更這些設定:

az k8s-extension update --cluster-name $CLUSTER_NAME --resource-group $RESOURCE_GROUP --cluster-type connectedClusters --name akvsecretsprovider --configuration-settings secrets-store-csi-driver.enableSecretRotation=true secrets-store-csi-driver.rotationPollInterval=3m secrets-store-csi-driver.syncSecret.enabled=true

您可以視需要使用其他組態設定來進行部署。 例如,若要在建立叢集時變更 kubelet 根目錄,請修改 az k8s-extension create 命令:

az k8s-extension create --cluster-name $CLUSTER_NAME --resource-group $RESOURCE_GROUP --cluster-type connectedClusters --extension-type Microsoft.AzureKeyVaultSecretsProvider --name akvsecretsprovider --configuration-settings linux.kubeletRootDir=/path/to/kubelet secrets-store-csi-driver.linux.kubeletRootDir=/path/to/kubelet

解除安裝 Azure Key Vault 秘密提供者延伸模組

請執行下列命令來解除安裝延伸模組:

az k8s-extension delete --cluster-type connectedClusters --cluster-name $CLUSTER_NAME --resource-group $RESOURCE_GROUP --name akvsecretsprovider

注意

解除安裝延伸模組不會刪除在安裝延伸模組時所建立的自訂資源定義 (CRD)。

若要確認延伸模組執行個體已遭刪除,請執行下列命令:

az k8s-extension list --cluster-type connectedClusters --cluster-name $CLUSTER_NAME --resource-group $RESOURCE_GROUP

如果已成功移除延伸模組,您就看不到輸出中所列的 Azure Key Vault 秘密提供者延伸模組。 如果您的叢集上未安裝任何其他延伸模組,您會看到空的陣列。

如果您不再需要它,務必執行下列命令來刪除與服務主體相關聯的 Kubernetes 秘密:

kubectl delete secret secrets-store-creds

協調和疑難排解

Azure Key Vault 秘密提供者延伸模組正在自我修復。 如果有人嘗試變更或刪除在安裝延伸模組時所部署的延伸模組元件,該元件會與其原始狀態協調。 唯一的例外狀況是自訂資源定義 (CRD)。 如果 CRD 已遭刪除,就不會予以協調。 若要還原已刪除的 CRD,請再次搭配現有的延伸模組執行個體名稱使用 az k8s-extension create 命令。

如需解決常見問題的詳細資訊,請參閱適用於秘密存放區 CSI 驅動程式的 Azure Key Vault 提供者秘密存放區 CSI 驅動程式的開放原始碼疑難排解指南。

下一步