你当前正在访问 Microsoft Azure Global Edition 技术文档网站。 如果需要访问由世纪互联运营的 Microsoft Azure 中国技术文档网站,请访问 https://docs.azure.cn。
重要
建议对 Azure 云外部的群集使用 机密存储扩展 。 默认情况下,此扩展不会在 kubernetes 机密存储中永久存储机密,因此每当启动或重启机密消耗的 Pod 时,都需要连接到 Azure Key Vault。
使用适用于机密存储 CSI 驱动程序的 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 Local 上的 Azure Kubernetes 服务 (AKS) 群集
- Azure Arc 启用的 AKS
- Google Kubernetes 引擎
- OpenShift Kubernetes 发行版
- Canonical Kubernetes 发行版
- 弹性 Kubernetes 服务
- Tanzu Kubernetes 网格
- Azure Red Hat OpenShift
 
- 以下终结点的出站连接:- linuxgeneva-microsoft.azurecr.io
- upstreamarc.azurecr.io
- *.blob.core.windows.net
 
- 确保满足群集扩展的一般先决条件。 必须使用 k8s-extensionAzure CLI 扩展的 0.4.0 或更新版本。
在已启用 Arc 的 Kubernetes 群集上安装 Azure Key Vault 机密提供程序扩展
可以使用 Azure CLI 或通过部署 ARM 模板在 Azure 门户中将 Azure Key Vault 机密提供程序扩展安装在连接的群集上。
每个已启用 Azure Arc 的 Kubernetes 群集上只能部署一个扩展实例。
提示
如果群集位于出站代理服务器后面,请确保在安装扩展之前使用“代理配置”选项将其连接到 Azure Arc。
Azure 门户
- 在 Azure 门户中,导航到“Kubernetes - Azure Arc”并选择你的群集。 
- 在服务菜单中的“设置”下,选择“扩展”。 然后选择“+ 添加”。 
- 从可用扩展列表中,选择“Azure Key Vault 机密提供程序”以部署最新版本的扩展。   
- 按照提示部署扩展。 如果需要,请通过更改“配置”选项卡上的默认选项来自定义安装。 
Azure CLI
- 设置环境变量: - export CLUSTER_NAME=<arc-cluster-name> export RESOURCE_GROUP=<resource-group-name>
- 通过运行以下命令安装机密存储 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 模板
- 使用以下格式创建 .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'))]" } ] }
- 现在使用以下 Azure CLI 命令设置环境变量: - export TEMPLATE_FILE_NAME=<template-file-path> export DEPLOYMENT_NAME=<desired-deployment-name>
- 最后,运行此 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。 如果还没有 Key Vault,请使用以下命令创建一个新的 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
在继续下一部分之前,请注意以下属性:
- Key Vault 中机密对象的名称
- 对象类型(机密、密钥或证书)
- Key Vault 资源的名称
- Key Vault 所属订阅的 Azure 租户 ID
提供标识以访问 Azure Key Vault
目前,可以通过服务主体访问 Arc 启用的群集上的机密存储驱动程序。 请按照以下步骤提供可访问 Key Vault 的标识。
- 按照步骤在 Azure 中创建服务主体。 请记下此步骤中生成的客户端 ID 和客户端机密。 
- 使用第一步中记下的客户端 ID 和客户端密码在已连接的群集上创建 Kubernetes 机密: - kubectl create secret generic secrets-store-creds --from-literal clientid="<client-id>" --from-literal clientsecret="<client-secret>"
- 标记创建的机密: - kubectl label secret secrets-store-creds secrets-store.csi.k8s.io/used=true
- 使用以下 YAML 创建 - SecretProviderClass,填写要从 AKV 实例检索的密钥保管库名称、租户 ID 和对象的值:- # 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更改为- AzureUSGovernmentCloud(Azure 政府版)或- AzureChinaCloud(由世纪互联运营的 Microsoft Azure)。
- 将 SecretProviderClass 应用到群集: - kubectl apply -f secretproviderclass.yaml
- 使用以下 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
- 将 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 米 | 如果 enableSecretRotation为true,则此设置指定机密轮换轮询间隔持续时间。 可以根据所有 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 驱动程序的开源故障排除指南。
后续步骤
- 想尝试一下吗? 使用群集 API 快速开始使用 Azure Arc Jumpstart 场景。
- 详细了解 Azure Key Vault。
- 通过遵循已启用 Azure Arc 的 Kubernetes 安全手册中的指导,以其他方式帮助保护群集。
