对 Azure Kubernetes 服务 (AKS) 中的 Azure 托管磁盘使用自带密钥 (BYOK)

Azure 会加密托管磁盘中的所有静态数据。 默认情况下,数据使用 Azure 管理的密钥进行加密。 为了更进一步控制加密密钥,可以提供客户托管密钥,将其用于对 AKS 群集的 OS 和数据磁盘进行静态加密。

详细了解 LinuxWindows 上的客户管理密钥。

先决条件

  • 使用密钥保管库加密托管磁盘时,必须为 Azure 密钥保管库启用软删除和清除保护。
  • 需要 Azure CLI 版本 2.11.1 或更高版本。
  • Kubernetes 版本 1.24 及更高版本支持数据磁盘加密和客户管理的密钥。
  • 如果选择定期轮换(更改)密钥,请参阅客户管理的密钥和 Azure 托管磁盘加密以了解详细信息。

限制

  • 只有在创建 AKS 群集时才能启用通过客户管理的密钥对 OS 磁盘加密的功能。

  • 不支持虚拟节点。

  • 使用客户管理的密钥加密已启用临时 OS 磁盘的节点池时,如果要在 Azure 密钥保管库中轮换密钥,则需要:

    • 将节点池数量纵向缩减为 0
    • 轮换密钥
    • 将节点池纵向扩展为原始数量。

创建 Azure Key Vault 实例

使用 Azure Key Vault 实例来存储密钥。 可以通过 Azure 门户使用 Azure Key Vault 配置客户管理的密钥

创建一个新的资源组,然后创建一个新的密钥保管库实例,并启用软删除和清除保护。 确保对每个命令使用同一区域和资源组名称。

# Optionally retrieve Azure region short names for use on upcoming commands
az account list-locations
# Create new resource group in a supported Azure region
az group create --location myAzureRegionName --name myResourceGroup

# Create an Azure Key Vault resource in a supported Azure region
az keyvault create --name myKeyVaultName --resource-group myResourceGroup --location myAzureRegionName  --enable-purge-protection true

创建 DiskEncryptionSet 的实例

myKeyVaultName 替换为你的密钥保管库的名称。 若要完成以下步骤,还需一个存储在 Azure 密钥保管库中的“密钥”。 将现有密钥存储在通过前面的步骤创建的密钥保管库中,或者生成新密钥并将 myKeyName 替换为你的密钥的名称。

# Retrieve the Key Vault Id and store it in a variable
keyVaultId=$(az keyvault show --name myKeyVaultName --query "[id]" -o tsv)

# Retrieve the Key Vault key URL and store it in a variable
keyVaultKeyUrl=$(az keyvault key show --vault-name myKeyVaultName --name myKeyName --query "[key.kid]" -o tsv)

# Create a DiskEncryptionSet
az disk-encryption-set create --name myDiskEncryptionSetName --location myAzureRegionName --resource-group myResourceGroup --source-vault $keyVaultId --key-url $keyVaultKeyUrl

重要

确保 DiskEncryptionSet 与你的 AKS 群集位于同一区域,并确保 AKS 群集标识对 DiskEncryptionSet 具有读取访问权限。

向 DiskEncryptionSet 授予对密钥保管库的访问权限

使用在前面的步骤中创建的 DiskEncryptionSet 和资源组,并授予 DiskEncryptionSet 资源对 Azure 密钥保管库的访问权限。

# Retrieve the DiskEncryptionSet value and set a variable
desIdentity=$(az disk-encryption-set show --name myDiskEncryptionSetName --resource-group myResourceGroup --query "[identity.principalId]" -o tsv)

# Update security policy settings
az keyvault set-policy --name myKeyVaultName --resource-group myResourceGroup --object-id $desIdentity --key-permissions wrapkey unwrapkey get

创建一个新的 AKS 群集,并对 OS 磁盘加密

创建新的资源组,或者选择托管其他 AKS 群集的现有资源组,然后使用密钥加密采用了网络连接型 OS 磁盘或临时 OS 磁盘的群集。 默认情况下,群集将尽可能结合 VM 大小和 OS 磁盘大小来使用临时 OS 磁盘。

请运行以下命令以检索 DiskEncryptionSet 值并设置变量:

diskEncryptionSetId=$(az disk-encryption-set show --name mydiskEncryptionSetName --resource-group myResourceGroup --query "[id]" -o tsv)

如果要为群集创建新的资源组,请运行以下命令:

az group create --name myResourceGroup --location myAzureRegionName

若要创建采用网络连接型 OS 磁盘的常规群集并使用你的密钥进行加密,可通过指定 --node-osdisk-type=Managed 参数来实现。

az aks create --name myAKSCluster --resource-group myResourceGroup --node-osdisk-diskencryptionset-id $diskEncryptionSetId --generate-ssh-keys --node-osdisk-type Managed

若要创建采用临时 OS 磁盘的群集并使用你的密钥进行加密,可通过指定 --node-osdisk-type=Ephemeral 参数来实现。 你还需要指定 --node-vm-size 参数,因为默认 VM 大小太小,无法支持临时 OS 磁盘。

az aks create --name myAKSCluster --resource-group myResourceGroup --node-osdisk-diskencryptionset-id $diskEncryptionSetId --generate-ssh-keys --node-osdisk-type Ephemeral --node-vm-size Standard_DS3_v2

向该群集添加新的节点池时,会使用在创建过程中提供的客户管理的密钥对 OS 磁盘进行加密。 以下示例显示了如何部署具有临时 OS 磁盘的新节点池。

az aks nodepool add --cluster-name $CLUSTER_NAME --resource-group $RG_NAME --name $NODEPOOL_NAME --node-osdisk-type Ephemeral

对 AKS 群集数据磁盘进行加密

如果在创建群集时已经提供了磁盘加密集,则默认选项是使用相同的磁盘加密集加密数据磁盘。 因此,此步骤为可选。 但是,如果要使用不同的磁盘加密集对数据磁盘进行加密,则可以按照以下步骤操作。

重要

确保你具有正确的 AKS 凭据。 对于在其中部署了 diskencryptionset 的资源组,托管标识需要有参与者访问权限。 否则,你会收到一个错误,提示托管标识没有权限。

要为 AKS 群集标识分配 diskencryptionset 的参与者角色,请执行以下命令:

aksIdentity=$(az aks show --resource-group $RG_NAME --name $CLUSTER_NAME --query "identity.principalId")
az role assignment create --role "Contributor" --assignee $aksIdentity --scope $diskEncryptionSetId

创建一个名为 byok-azure-disk.yaml 的文件,在其中包含以下信息。 将 myAzureSubscriptionId、myResourceGroup 和 myDiskEncrptionSetName 替换为你的值并应用 yaml。 请确保使用在其中部署了 DiskEncryptionSet 的资源组。

kind: StorageClass
apiVersion: storage.k8s.io/v1
metadata:
  name: byok
provisioner: disk.csi.azure.com # replace with "kubernetes.io/azure-disk" if aks version is less than 1.21
parameters:
  skuname: StandardSSD_LRS
  kind: managed
  diskEncryptionSetID: "/subscriptions/{myAzureSubscriptionId}/resourceGroups/{myResourceGroup}/providers/Microsoft.Compute/diskEncryptionSets/{myDiskEncryptionSetName}"

接下来,运行以下命令来更新 AKS 群集:

# Get credentials
az aks get-credentials --name myAksCluster --resource-group myResourceGroup --output table

# Update cluster
kubectl apply -f byok-azure-disk.yaml

后续步骤

查看 AKS 群集安全性最佳做法