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

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

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

有关使用 KMS 的详细信息,请参阅加密静态机密数据

先决条件

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

警告

KMS 支持 Konnectivity 或 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 加密不适用于系统分配的托管标识。 在启用该功能之前,必须设置密钥保管库访问策略。 在创建群集之前,系统分配的托管标识不可用。 请考虑循环依赖项。
  • 不支持具有允许公共访问的防火墙的 Azure Key Vault,因为它会阻止从 KMS 插件到密钥保管库的流量。
  • 已启用 KMS 的群集支持的最大机密数为 2,000。 但是,请务必注意,KMS v2 不受此限制的限制,它可以处理更多机密。
  • 不支持来自其他租户的自带 (BYO) Azure Key Vault。
  • 启用 KMS 后,无法更改关联的密钥保管库模式(公共模式与专用模式)。 若要更新密钥保管库模式,必须先禁用 KMS,然后再次启用它。
  • 如果群集已启用 KMS,具有专用密钥保管库,并且未使用 API 服务器 VNet 集成隧道,则无法停止并启动该群集。
  • 使用 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 --out 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 -n 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

更新现有的 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 中的现有密钥。

警告

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

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

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 群集的专用终结点连接。

创建私钥保管库和密钥

警告

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

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

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

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

不支持在没有专用终结点的专用密钥保管库中创建或更新密钥。 若要了解如何管理专用密钥保管库,请参阅使用 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 -n 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

更新现有的 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,而不会影响现有群集。

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

更改密钥保管库模式

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

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

使用更新的密钥保管库为群集启用 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,则会阻止升级到 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 -