你当前正在访问 Microsoft Azure Global Edition 技术文档网站。 如果需要访问由世纪互联运营的 Microsoft Azure 中国技术文档网站,请访问 https://docs.azure.cn

将密钥管理服务 etcd 加密添加到 Azure Kubernetes 服务群集

本文介绍如何如何使用 Azure Key Vault 和密钥管理服务 (KMS) 插件在 etcd 键值存储中为 Azure Kubernetes 服务 (AKS) 机密启用静态加密。 可以使用 KMS 插件执行以下操作:

  • 使用密钥保管库中的密钥进行 etcd 加密。
  • 自带密钥。
  • 为存储在 etcd 中的机密提供静态加密。
  • 轮换密钥保管库中的密钥。

有关使用 KMS 的详细信息,请参阅使用 KMS 提供程序进行数据加密

先决条件

  • 具有活动订阅的 Azure 帐户。 免费创建帐户
  • Azure CLI 2.39.0 或更高版本。 运行 az --version 即可查找版本。 如需进行安装或升级,请参阅安装 Azure CLI

警告

从 2024 年 9 月 15 日开始,对于新订阅或以前未使用此配置的订阅,其私钥保管库不再支持 Konnectivity。 对于当前使用此配置或在过去 60 天内使用过它的订阅,支持将继续,直到 AKS 版本 1.30 停止社区支持。

KMS 对公钥保管库支持 Konnectivity 或 API 服务器 VNet 集成(预览版)

KMS 支持用于私钥和公钥保管库的 API 服务器 VNet 集成(预览版)

可以使用 kubectl get po -n kube-system 来验证结果,并显示 konnectivity-agent pod 正在运行。 如果 Pod 正在运行,则表示 AKS 群集正在使用 Konnectivity。 使用 API 服务器 VNet 集成时,可以运行 az aks show -g -n 命令来验证 enableVnetIntegration 设置是否设置为 true

限制

将 KMS etcd 加密与 AKS 集成时存在以下限制:

  • 不支持删除密钥、密钥保管库或关联的标识。
  • KMS etcd 加密不适用于系统分配的托管标识。 在启用该功能之前,必须设置密钥保管库访问策略。 在创建群集之前,系统分配的托管标识不可用。 请考虑循环依赖项。
  • 不支持使用防火墙设置“允许从特定虚拟网络和 IP 地址进行公共访问”或“禁用公共访问”的 Azure Key Vault,因为它会阻止从 KMS 插件到密钥保管库的流量。
  • 已启用 KMS 的群集支持的最大机密数为 2,000。 但是,请务必注意,KMS v2 不受此限制的限制,它可以处理更多机密。
  • 不支持来自其他租户的自带 (BYO) Azure Key Vault。
  • 启用 KMS 后,无法更改关联的密钥保管库模式(公共模式与专用模式)。 若要更新密钥保管库模式,必须先禁用 KMS,然后再次启用它。
  • 如果群集已启用 KMS 并且具有私钥保管库,则必须使用 API 服务器 VNet 集成(预览版)隧道。 不支持 Konnectivity。
  • 使用 Microsoft Azure 虚拟机规模集 API 将群集中的节点纵向缩减为零会解除分配节点。 然后,群集将出现故障并变得不可恢复。
  • 禁用 KMS 后,无法销毁密钥。 销毁密钥会导致 API 服务器停止工作。

KMS 支持公共密钥保管库专用密钥保管库

为公共密钥保管库启用 KMS

以下部分介绍如何为公共密钥保管库启用 KMS。

创建公共密钥保管库和密钥

警告

不支持删除密钥或密钥保管库,删除会导致群集中的机密不可恢复。

如果需要恢复密钥保管库或密钥,请参阅使用软删除和清除保护进行 Azure Key Vault 恢复管理

为非 RBAC 公共密钥保管库创建密钥保管库和密钥

使用 az keyvault create 创建密钥保管库,而不使用 Azure 基于角色的访问控制 (Azure RBAC):

az keyvault create --name MyKeyVault --resource-group MyResourceGroup

使用 az keyvault key create 创建密钥:

az keyvault key create --name MyKeyName --vault-name MyKeyVault

使用 az keyvault key show 导出密钥 ID:

export KEY_ID=$(az keyvault key show --name MyKeyName --vault-name MyKeyVault --query 'key.kid' -o tsv)
echo $KEY_ID

此示例将密钥 ID 存储在 KEY_ID 中。

为 RBAC 公共密钥保管库创建密钥保管库和密钥

使用 az keyvault create 通过 Azure RBAC 创建密钥保管库:

export KEYVAULT_RESOURCE_ID=$(az keyvault create --name MyKeyVault --resource-group MyResourceGroup  --enable-rbac-authorization true --query id -o tsv)

为自己分配创建密钥的权限:

az role assignment create --role "Key Vault Crypto Officer" --assignee-object-id $(az ad signed-in-user show --query id -o tsv) --assignee-principal-type "User" --scope $KEYVAULT_RESOURCE_ID

使用 az keyvault key create 创建密钥:

az keyvault key create --name MyKeyName --vault-name MyKeyVault

使用 az keyvault key show 导出密钥 ID:

export KEY_ID=$(az keyvault key show --name MyKeyName --vault-name MyKeyVault --query 'key.kid' -o tsv)
echo $KEY_ID

此示例将密钥 ID 存储在 KEY_ID 中。

为公共密钥保管库创建用户分配的托管标识

使用 az identity create 创建用户分配的托管标识:

az identity create --name MyIdentity --resource-group MyResourceGroup

使用 az identity show 获取标识对象 ID:

IDENTITY_OBJECT_ID=$(az identity show --name MyIdentity --resource-group MyResourceGroup --query 'principalId' -o tsv)
echo $IDENTITY_OBJECT_ID

前面的示例将标识对象 ID 的值存储在 IDENTITY_OBJECT_ID 中。

使用 az identity show 获取标识资源 ID:

IDENTITY_RESOURCE_ID=$(az identity show --name MyIdentity --resource-group MyResourceGroup --query 'id' -o tsv)
echo $IDENTITY_RESOURCE_ID

此示例将标识资源 ID 的值存储在 IDENTITY_RESOURCE_ID 中。

分配用于解密和加密公共密钥保管库的权限

以下部分介绍如何为专用密钥保管库分配解密和加密权限。

为非 RBAC 公共密钥保管库分配权限

如果未使用 --enable-rbac-authorization 设置密钥保管库,则可以使用 az keyvault set-policy 创建 Azure Key Vault 策略。

az keyvault set-policy --name MyKeyVault --key-permissions decrypt encrypt --object-id $IDENTITY_OBJECT_ID

为 BAC 公共密钥保管库分配权限

如果已使用 --enable-rbac-authorization 设置密钥保管库,请分配密钥保管库加密用户角色以授予解密和加密权限。

az role assignment create --role "Key Vault Crypto User" --assignee-object-id $IDENTITY_OBJECT_ID --assignee-principal-type "ServicePrincipal" --scope $KEYVAULT_RESOURCE_ID

创建具有公共密钥保管库并启用 KMS etcd 加密的 AKS 群集

若要启用 KMS etcd 加密,请使用 az aks create 命令创建 AKS 群集。 可以将 --enable-azure-keyvault-kms--azure-keyvault-kms-key-vault-network-access--azure-keyvault-kms-key-id 参数与 az aks create 一起使用。

az aks create \
    --name myAKSCluster \
    --resource-group MyResourceGroup \
    --assign-identity $IDENTITY_RESOURCE_ID \
    --enable-azure-keyvault-kms \
    --azure-keyvault-kms-key-vault-network-access "Public" \
    --azure-keyvault-kms-key-id $KEY_ID \
    --generate-ssh-keys

更新现有的 AKS 群集以启用公共密钥保管库的 KMS etcd 加密

若要为现有群集启用 KMS etcd 加密,请使用 az aks update 命令。 可以将 --enable-azure-keyvault-kms--azure-keyvault-kms-key-vault-network-access--azure-keyvault-kms-key-id 参数与 az-aks-update 一起使用。

az aks update --name myAKSCluster --resource-group MyResourceGroup --enable-azure-keyvault-kms --azure-keyvault-kms-key-vault-network-access "Public" --azure-keyvault-kms-key-id $KEY_ID

使用以下命令更新所有机密。 如果未运行此命令,则之前创建的机密不再加密。 对于较大的群集,可能需要按命名空间细分机密或创建更新脚本。

kubectl get secrets --all-namespaces -o json | kubectl replace -f -

轮换公共密钥保管库中的现有密钥

更改密钥 ID(包括更改密钥名称或密钥版本)后,可以使用 az aks update 命令。 可以将 --enable-azure-keyvault-kms--azure-keyvault-kms-key-vault-network-access--azure-keyvault-kms-key-id 参数与 az-aks-update 一起使用,以轮换 KMS 中的现有密钥。

警告

请记住在密钥轮换后更新所有机密。 如果未更新所有机密,则如果之前创建的密钥不存在或不再有效,则无法访问这些机密。

KMS 同时使用 2 个密钥。 第一次密钥轮换后,需要确保旧密钥和新密钥在下次密钥轮换之前有效(未过期)。 第二次密钥轮换后,可安全地删除最早的密钥/使其过期

使用新的 keyId 轮换 KMS 密钥版本后,请检查 AKS 资源 json 中的 securityProfile.azureKeyVaultKms.keyId。 确保使用新的密钥版本。

az aks update --name myAKSCluster --resource-group MyResourceGroup  --enable-azure-keyvault-kms --azure-keyvault-kms-key-vault-network-access "Public" --azure-keyvault-kms-key-id $NEW_KEY_ID 

使用以下命令更新所有机密。 如果未运行此命令,则之前创建的机密仍将使用上一个密钥进行加密。 对于较大的群集,可能需要按命名空间细分机密或创建更新脚本。

kubectl get secrets --all-namespaces -o json | kubectl replace -f -

为专用密钥保管库启用 KMS

如果已为专用密钥保管库启用 KMS,则 AKS 会自动在节点资源组中创建专用终结点和专用链接。 密钥保管库将添加与 AKS 群集的专用终结点连接。

警告

KMS 对私钥保管库仅支持 API 服务器 VNet 集成(预览版)

创建私钥保管库和密钥

警告

不支持删除密钥或密钥保管库,删除会导致群集中的机密不可恢复。

如果需要恢复密钥保管库或密钥,请参阅使用软删除和清除保护进行 Azure Key Vault 恢复管理

使用 az keyvault create 创建专用密钥保管库:

az keyvault create --name MyKeyVault --resource-group MyResourceGroup --public-network-access Disabled

使用 az keyvault key create 创建密钥:

az keyvault key create --name MyKeyName --vault-name MyKeyVault

不支持在没有专用终结点的专用密钥保管库中创建或更新密钥。 若要了解如何管理专用密钥保管库,请参阅使用 Azure 专用链接集成密钥保管库

为专用密钥保管库创建用户分配的托管标识

使用 az identity create 创建用户分配的托管标识:

az identity create --name MyIdentity --resource-group MyResourceGroup

使用 az identity show 获取标识对象 ID:

IDENTITY_OBJECT_ID=$(az identity show --name MyIdentity --resource-group MyResourceGroup --query 'principalId' -o tsv)
echo $IDENTITY_OBJECT_ID

前面的示例将标识对象 ID 的值存储在 IDENTITY_OBJECT_ID 中。

使用 az identity show 获取标识资源 ID:

IDENTITY_RESOURCE_ID=$(az identity show --name MyIdentity --resource-group MyResourceGroup --query 'id' -o tsv)
echo $IDENTITY_RESOURCE_ID

此示例将标识资源 ID 的值存储在 IDENTITY_RESOURCE_ID 中。

分配用于解密和加密专用密钥保管库的权限

以下部分介绍如何为专用密钥保管库分配解密和加密权限。

为非 RBAC 专用密钥保管库分配权限

注意

使用专用密钥保管库时,AKS 无法验证标识的权限。 在启用 KMS 之前,请验证是否已向标识授予访问密钥保管库的权限。

如果未使用 --enable-rbac-authorization 设置密钥保管库,则可以使用 az keyvault set-policy 在 Azure 中创建密钥保管库策略:

az keyvault set-policy --name MyKeyVault --key-permissions decrypt encrypt --object-id $IDENTITY_OBJECT_ID

为 RBAC 专用密钥保管库分配权限

如果已使用 --enable-rbac-authorization 设置密钥保管库,请分配包含解密和加密权限的 Azure RBAC 角色:

az role assignment create --role "Key Vault Crypto User" --assignee-object-id $IDENTITY_OBJECT_ID --assignee-principal-type "ServicePrincipal" --scope $KEYVAULT_RESOURCE_ID

对于专用密钥保管库,需要密钥保管库参与者角色才能在专用密钥保管库和群集之间创建专用链接。

az role assignment create --role "Key Vault Contributor" --assignee-object-id $IDENTITY_OBJECT_ID --assignee-principal-type "ServicePrincipal" --scope $KEYVAULT_RESOURCE_ID

创建具有专用密钥保管库并启用 KMS etcd 加密的 AKS 群集

若要为专用密钥保管库启用 KMS etcd 加密,请使用 az aks create 命令创建 AKS 群集。 可以将 --enable-azure-keyvault-kms--azure-keyvault-kms-key-id--azure-keyvault-kms-key-vault-network-access--azure-keyvault-kms-key-vault-resource-id 参数与 az-aks-create 一起使用。

az aks create \
    --name myAKSCluster \
    --resource-group MyResourceGroup \
    --assign-identity $IDENTITY_RESOURCE_ID \
    --enable-azure-keyvault-kms \
    --azure-keyvault-kms-key-id $KEY_ID \
    --azure-keyvault-kms-key-vault-network-access "Private" \
    --azure-keyvault-kms-key-vault-resource-id $KEYVAULT_RESOURCE_ID \
    --generate-ssh-keys

更新现有的 AKS 群集以启用专用密钥保管库的 KMS etcd 加密

若要在具有专用密钥保管库的现有群集上启用 KMS etcd 加密,请使用 az aks update 命令。 可以将 --enable-azure-keyvault-kms--azure-keyvault-kms-key-id--azure-keyvault-kms-key-vault-network-access--azure-keyvault-kms-key-vault-resource-id 参数与 az-aks-update 一起使用。

az aks update --name myAKSCluster --resource-group MyResourceGroup --enable-azure-keyvault-kms --azure-keyvault-kms-key-id $KEY_ID --azure-keyvault-kms-key-vault-network-access "Private" --azure-keyvault-kms-key-vault-resource-id $KEYVAULT_RESOURCE_ID

使用以下命令更新所有机密。 如果未运行此命令,则之前创建的机密不会加密。 对于较大的群集,可能需要按命名空间细分机密或创建更新脚本。

kubectl get secrets --all-namespaces -o json | kubectl replace -f -

轮换专用密钥保管库中的现有密钥

更改密钥 ID(包括密钥名称和密钥版本)后,可以使用 az aks update 命令。 可以将 --enable-azure-keyvault-kms--azure-keyvault-kms-key-id--azure-keyvault-kms-key-vault-network-access--azure-keyvault-kms-key-vault-resource-id 参数与 az-aks-update 一起使用,以轮换 KMS 的现有密钥。

警告

请记住在密钥轮换后更新所有机密。 如果未更新所有机密,则如果之前创建的密钥不存在或不再有效,则无法访问这些机密。

轮换密钥后,仍会缓存上一个密钥 (key1),不应删除它。 如果要立即删除上一个密钥 (key1),则需要轮换密钥两次。 然后缓存 key2 和 key3,并且可以删除 key1,而不会影响现有群集。

使用新的 keyId 轮换 KMS 密钥版本后,请检查 AKS 资源 json 中的 securityProfile.azureKeyVaultKms.keyId。 确保使用新的密钥版本。

az aks update --name myAKSCluster --resource-group MyResourceGroup  --enable-azure-keyvault-kms --azure-keyvault-kms-key-id $NewKEY_ID --azure-keyvault-kms-key-vault-network-access "Private" --azure-keyvault-kms-key-vault-resource-id $KEYVAULT_RESOURCE_ID

使用以下命令更新所有机密。 如果未更新所有机密,则之前创建的机密将使用上一个密钥进行加密。 对于较大的群集,可能需要按命名空间细分机密或创建更新脚本。

kubectl get secrets --all-namespaces -o json | kubectl replace -f -

更新密钥保管库模式

注意

若要更改具有不同模式(无论是公共还是专用)的不同密钥保管库,可以直接运行 az aks update。 若要更改附加的密钥保管库的模式,必须先禁用 KMS,然后使用新的密钥保管库 ID 再次打开它。

以下部分介绍如何将附加的公共密钥保管库迁移到专用模式。 这些步骤还可用于从专用迁移到公共。

禁用群集上的 KMS

禁用现有群集上的 KMS 并释放密钥保管库:

az aks update --name myAKSCluster --resource-group MyResourceGroup --disable-azure-keyvault-kms

使用以下命令更新所有机密。 如果未运行此命令,则之前创建的机密仍将使用上一个密钥进行加密。 对于较大的群集,可能需要按命名空间细分机密或创建更新脚本。

kubectl get secrets --all-namespaces -o json | kubectl replace -f -

更改密钥保管库模式

将密钥保管库从公共保管库更新为专用保管库:

az keyvault update --name MyKeyVault --resource-group MyResourceGroup --public-network-access Disabled

若要从专用到公共,在上述命令中将 --public-network-access 设置为 Enabled

使用更新的密钥保管库为群集启用 KMS

使用更新的专用密钥保管库启用 KMS:

az aks update --name myAKSCluster --resource-group MyResourceGroup  --enable-azure-keyvault-kms --azure-keyvault-kms-key-id $NewKEY_ID --azure-keyvault-kms-key-vault-network-access "Private" --azure-keyvault-kms-key-vault-resource-id $KEYVAULT_RESOURCE_ID

设置 KMS 后,可以启用“用于检查加密日志的密钥保管库的诊断设置”。

禁用 KMS

在禁用 KMS 之前,可以使用以下 Azure CLI 命令检查 KMS 是否已启用:

az aks list --query "[].{Name:name, KmsEnabled:securityProfile.azureKeyVaultKms.enabled, KeyId:securityProfile.azureKeyVaultKms.keyId}" -o table

如果结果确认 KMS 已启用,请运行以下命令以禁用群集上的 KMS:

az aks update --name myAKSCluster --resource-group MyResourceGroup --disable-azure-keyvault-kms

使用以下命令更新所有机密。 如果未运行此命令,则之前创建的机密仍将使用上一个密钥进行加密,并且仍需要对密钥保管库的加密和解密权限。 对于较大的群集,可能需要按命名空间细分机密或创建更新脚本。

kubectl get secrets --all-namespaces -o json | kubectl replace -f -

KMS v2 支持

从 AKS 版本 1.27 开始,启用 KMS 功能将配置 KMS v2。 使用 KMS v2 时,你不受早期版本支持的 2,000 个机密的限制。 有关详细信息,请参阅 KMS V2 改进

迁移到 KMS v2

如果群集版本低于 1.27,而你已启用 KMS,系统会阻止升级到群集 1.27 或更高版本。 使用以下步骤迁移到 KMS v2:

  1. 禁用群集上的 KMS。
  2. 执行存储迁移。
  3. 将群集升级到版本 1.27 或更高版本。
  4. 启用群集上的 KMS。
  5. 执行存储迁移。

禁用 KMS 以迁移存储

若要禁用现有群集上的 KMS,请将 az aks update 命令与 --disable-azure-keyvault-kms 参数一起使用:

az aks update --name myAKSCluster --resource-group MyResourceGroup --disable-azure-keyvault-kms

迁移存储

若要更新所有机密,请将 kubectl get secrets 命令与 --all-namespaces 参数一起使用:

kubectl get secrets --all-namespaces -o json | kubectl replace -f -

升级 AKS 群集

若要升级 AKS 群集,请使用 az aks upgrade 命令。 使用 --kubernetes-version 参数将版本设置为 1.27.x 或更高版本。

az aks upgrade --resource-group myResourceGroup --name myAKSCluster --kubernetes-version <AKS version>

下面是一个示例:

az aks upgrade --resource-group myResourceGroup --name myAKSCluster --kubernetes-version 1.27.1

在迁移存储后启用 KMS

可以再次启用群集上的 KMS 功能以加密机密。 之后,AKS 群集将使用 KMS v2。 如果不想迁移到 KMS v2,你可以创建已启用 KMS 的 1.27 或更高版本的新群集。

迁移 KMS v2 的存储

若要重新加密 KMS v2 中的所有机密,请将 kubectl get secrets 命令与 --all-namespaces 参数一起使用:

kubectl get secrets --all-namespaces -o json | kubectl replace -f -

KMS 可观测性

AKS 资源 JSON

可以通过以下方法检查 AKS 资源 json 中的 KMS 配置:

  1. 使用 az aks show 命令
  2. 通过 Azure 门户

securityProfile.azureKeyVaultKms 部分显示 KMS 配置,包括密钥保管库、密钥、当前和以前的密钥版本。

诊断和解决问题

由于 KMS 插件是 kube-apiserver Pod 的边车,因此无法直接访问它。 若要提高 KMS 的可观测性,可以通过以下方式检查 KMS 状态:

  1. 打开 AKS 群集的 Azure 门户页
  2. 转到 Diagnose and solve problems,然后搜索 KMS
  3. KMS 检测器中,可以看到 KMS 的状态,以及它是否在一些已知的故障方案中

KeyExpired: Operation encrypt is not allowed on an expired key 为例:

由于 AKS KMS 插件目前仅允许 BYO 密钥保管库和密钥,因此你有责任管理密钥生命周期。 如果密钥过期,KMS 插件将无法解密现有机密。 你需要

  1. 延长密钥到期日期以使 KMS 正常工作
  2. 轮换密钥版本