使用 Azure Key Vault 机密提供程序扩展将机密提取到已启用 Azure Arc 的 Kubernetes 群集
使用适用于机密存储 CSI 驱动程序的 Azure 密钥保管库提供程序,可以通过 CSI 卷将 Azure 密钥保管库作为机密存储与 Kubernetes 群集集成。 对于已启用 Azure Arc 的 Kubernetes 群集,可安装 Azure Key Vault 机密提供程序扩展以提取机密。
Azure Key Vault 机密提供程序扩展的功能包括:
- 使用 CSI 内联卷将机密/密钥/证书装载到 pod
- 支持使用 SecretProviderClass CRD 完成 Pod 移植
- 支持 Linux 和 Windows 容器
- 支持与 Kubernetes 机密同步
- 支持机密自动轮换
- 扩展组件部署到可用性区域,使其成为区域冗余组件
先决条件
具有受支持的 Kubernetes 发行版的群集已连接到 Azure Arc。对于此方案,目前支持以下 Kubernetes 发行版:
- Cluster API Azure
- Azure Stack HCI 上的 Azure Kubernetes 服务 (AKS) 群集
- Azure Arc 启用的 AKS
- Google Kubernetes Engine
- OpenShift Kubernetes Distribution
- Canonical Kubernetes Distribution
- 弹性 Kubernetes 服务
- Tanzu Kubernetes 网格
- Azure Red Hat OpenShift
以下终结点的出站连接:
linuxgeneva-microsoft.azurecr.cn
upstreamarc.azurecr.cn
*.blob.core.chinacloudapi.cn
请确保满足一般群集扩展先决条件。 必须使用
k8s-extension
Azure CLI 扩展的 0.4.0 或更新版本。
在已启用 Arc 的 Kubernetes 群集上安装 Azure Key Vault 机密提供程序扩展
可以使用 Azure CLI 或通过部署 ARM 模板在 Azure 门户中将 Azure 密钥保管库机密提供程序扩展安装在连接的群集上。
每个已启用 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 的群集上的机密存储 CSI 驱动程序。 请按照以下步骤提供可访问 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: AzureChinaCloud # Defaults to AzureCloud 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
若要与国家/地区云一起使用,请将世纪互联运营的 Azure 的
cloudName
更改为AzureChinaCloud
。将 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 m | 如果 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。