使用机密容器和自动生成的策略部署 AKS 群集

本文使用 Azure CLI 部署 Azure Kubernetes 服务 (AKS) 群集,并使用自动生成的安全策略配置机密容器(预览版)。 然后可以将应用程序部署为机密容器。 若要了解详细信息,请参阅 AKS 机密容器概述

通常,AKS 机密容器入门涉及以下步骤。

  • 使用 Azure CLI 部署或升级 AKS 群集
  • 将注释添加到 Pod YAML 清单,以将 Pod 标记为使用机密容器
  • 将安全策略添加到 Pod YAML 清单
  • 在机密计算中部署应用程序

重要

2025 年 11 月 30 日开始,Azure Kubernetes 服务(AKS)不再支持或提供 Azure Linux 2.0 安全更新。 Azure Linux 2.0 节点映像在 202512.06.0 版中冻结。 从 2026 年 3 月 31 日开始,将删除节点映像,并且无法缩放节点池。 通过将 节点池升级到 受支持的 Kubernetes 版本或迁移到 osSku AzureLinux3,迁移到受支持的 Azure Linux 版本。 有关详细信息,请参阅 停用 GitHub 问题和Azure 更新停用公告。 若要随时了解公告和更新,请关注AKS 发行说明

先决条件

  • Azure CLI 版本 2.44.1 或更高版本。 可通过运行 az --version 查找版本,运行 az upgrade 升级版本。 如果需要安装或升级,请参阅 安装 Azure CLI

  • aks-preview Azure CLI 扩展版本 0.5.169 或更高版本。

  • confcom 机密容器 Azure CLI 扩展 0.3.3 或更高版本。 confcom 需要生成安全策略。

  • 在 Azure 订阅中注册 Preview 功能。

  • AKS 支持版本 1.25.0 及更高版本的机密容器(预览版)。

  • 工作负载标识和联合标识凭据。 使用工作负载标识凭据,Kubernetes 应用程序可以使用基于带注释的服务帐户通过 Microsoft Entra ID 安全地访问 Azure 资源。 如果不熟悉 Microsoft Entra 工作负载 ID,请参阅 Microsoft Entra 工作负载 ID 概述并查看工作负载标识如何与 AKS 配合使用

  • 用于创建群集的标识具有合适的的最低权限。 有关 AKS 的访问和标识的详细信息,请参阅 Azure Kubernetes 服务 (AKS) 的访问和标识选项

  • 若要管理 Kubernetes 群集,请使用 Kubernetes 命令行客户端 kubectl。 可以使用 az aks install-cli 命令在本地安装 kubectl。

  • AKS 上的机密容器提供用于证明和安全密钥发布的挎斗开放源代码容器。 该挎斗与 Azure 密钥保管库 等密钥管理服务 (KMS) 集成,以便在验证完成后将密钥发布到容器组。

安装 aks-preview Azure CLI 扩展

重要

AKS 预览功能可在自助服务和自愿选择的基础上启用。 预览版按“现状”和“视供应情况”提供,它们不包括在服务级别协议和有限保证范围内。 AKS 预览功能是由客户支持尽最大努力部分覆盖。 因此,这些功能并不适合用于生产。 有关详细信息,请参阅以下支持文章:

若要安装 aks-preview 扩展,请运行以下命令:

az extension add --name aks-preview

运行以下命令以更新到最新扩展版本:

az extension update --name aks-preview

安装 confcom Azure CLI 扩展

若要安装 confcom 扩展,请运行以下命令:

az extension add --name confcom

运行以下命令以更新到最新扩展版本:

az extension update --name confcom

注册 KataCcIsolationPreview 功能标志

使用 KataCcIsolationPreview 命令注册 功能标志,如以下示例所示:

az feature register --namespace "Microsoft.ContainerService" --name "KataCcIsolationPreview"

几分钟后,状态将显示为“已注册”。 使用 az feature show 命令验证注册状态:

az feature show --namespace "Microsoft.ContainerService" --name "KataCcIsolationPreview"

当状态显示“已注册”时,使用 az provider register 命令刷新 Microsoft.ContainerService 资源提供程序的注册

az provider register --namespace "Microsoft.ContainerService"

部署一个新群集

  1. 使用 az aks create 命令并指定以下参数创建 AKS 群集:

    • --os-sku:AzureLinux。 在此预览版本中,只有 Azure Linux os-sku 支持此功能。
    • --node-vm-size:支持 AMD SEV-SNP 保护的子 VM 的任何 Azure VM 大小都有效。 例如[Standard_DC8as_cc_v5][DC8as 系列] 虚拟机(VMs)。
    • --enable-workload-identity:启用创建 Microsoft Entra 工作负载 ID,使 Pod 能够使用 Kubernetes 标识。
    • --enable-oidc-issuer:启用 OpenID Connect (OIDC) 证书颁发者。 它允许 Microsoft Entra ID 或其他云提供商标识和访问管理平台发现 API 服务器的公钥签名密钥。
    • --workload-runtime:指定 KataCcIsolation 以在节点池上启用机密容器功能。
    az aks create --resource-group myResourceGroup --name myAKSCluster --kubernetes-version <1.25.0 and above> --os-sku AzureLinux --node-vm-size Standard_DC8as_cc_v5 --workload-runtime KataCcIsolation --node-count 1 --enable-oidc-issuer --enable-workload-identity --generate-ssh-keys
    

    片刻之后,该命令将会完成,并返回有关群集的 JSON 格式信息。

  2. 群集准备就绪后,使用 az aks get-credentials 命令获取群集凭据。

    az aks get-credentials --resource-group myResourceGroup --name myAKSCluster
    

部署到现有群集

若要将此功能用于现有 AKS 群集,必须满足以下要求:

使用以下命令通过创建节点池来托管机密容器(预览版)。

  1. 使用 az aks nodepool add 命令将节点池添加到 AKS 群集。 指定下列参数:

    • --resource-group:输入要在其中创建 AKS 群集的现有资源组的名称
    • --cluster-name:输入 AKS 群集的唯一名称,例如 myAKSCluster
    • --name:输入群集节点池的唯一名称,例如 nodepool2
    • --workload-runtime:指定 KataCcIsolation 以在节点池上启用该功能。 除了 --workload-runtime 参数外,这些其他参数应满足以下要求。 否则,该命令将失败,并报告相应参数的问题。
    • --os-sku:AzureLinux。 在此预览版本中,只有 Azure Linux os-sku 支持此功能。
    • --node-vm-size:支持 AMD SEV-SNP 保护的子 VM 嵌套虚拟化的任何 Azure VM 大小都有效。

    以下示例将用户节点池添加到 myAKSCluster,其中有两个节点在 myResourceGroupnodepool2 中:

    az aks nodepool add --resource-group myResourceGroup --name nodepool2 –-cluster-name myAKSCluster --node-count 2 --os-sku AzureLinux --node-vm-size Standard_DC8as_cc_v5 --workload-runtime KataCcIsolation
    

    片刻之后,该命令将会完成,并返回有关群集的 JSON 格式信息。

  2. 运行 az aks update 命令以在群集上启用机密容器(预览版)。

    az aks update --name myAKSCluster --resource-group myResourceGroup
    

    片刻之后,该命令将会完成,并返回有关群集的 JSON 格式信息。

  3. 群集准备就绪后,使用 az aks get-credentials 命令获取群集凭据。

    az aks get-credentials --resource-group myResourceGroup --name myAKSCluster
    

配置容器

在配置对 Azure 密钥保管库 和机密的访问权限并将应用程序部署为机密容器之前,需要完成工作负载标识的配置。

若要配置工作负载标识,请执行部署和配置工作负载标识一文中所述的以下步骤:

  • 检索 OIDC 颁发者 URL
  • 创建托管标识
  • 创建 Kubernetes 服务帐户
  • 建立联合标识凭据

重要

你需要根据部署和配置工作负载标识一文中的“导出环境变量”部分来设置环境变量,以继续完成本教程。 请记得将变量 SERVICE_ACCOUNT_NAMESPACE 设置为 kafka,并在配置工作负载标识之前执行命令 kubectl create namespace kafka

使用 kata-cc 和证明容器部署受信任的应用程序

以下步骤使用 Azure 托管硬件安全模块(mHSM)管理的加密密钥为 Kafka 消息配置端到端加密。 仅当 Kafka 使用者在机密容器中运行并且 Azure 证明机密预配容器注入到 Pod 中时,才会释放密钥。

此配置基于以下四个组件:

  • Kafka 群集:在群集上的 Kafka 命名空间中部署的简单 Kafka 群集。
  • Kafka 生成者:作为 Vanilla Kubernetes Pod 运行的 Kafka 生成者,使用公钥将加密的用户配置的消息发送到 Kafka 主题。
  • Kafka 使用者:使用 kata-cc 运行时运行的 Kafka 使用者 Pod,配备了安全密钥发布容器,用于检索私钥,以解密 Kafka 消息并将消息呈现到 Web UI。

对于此预览版,建议出于测试和评估目的创建或使用现有的 Azure 密钥保管库 高级层资源来支持在硬件安全模块 (HSM) 中存储密钥。 不建议使用生产密钥保管库。 如果没有 Azure 密钥保管库,请参阅使用 Azure CLI 创建密钥保管库

  1. 授予之前创建的托管标识以及帐户对密钥保管库的访问权限。 分配 标识 密钥保管库 Crypto Officer 和 密钥保管库 Crypto User Azure RBAC 角色。

    注释

    运行以下命令来设置范围:

    AKV_SCOPE=$(az keyvault show --name <AZURE_AKV_RESOURCE_NAME> --query id --output tsv)
    

    运行以下命令以分配 密钥保管库 Crypto Officer 角色。

    az role assignment create --role "Key Vault Crypto Officer" --assignee "${USER_ASSIGNED_IDENTITY_NAME}" --scope $AKV_SCOPE
    

    运行以下命令以分配 密钥保管库 Crypto User 角色。

    az role assignment create --role "Key Vault Crypto User" --assignee "${USER_ASSIGNED_IDENTITY_NAME}" --scope $AKV_SCOPE
    
  2. 运行以下命令,在 kafka 命名空间中安装 Kafka 群集:

    kubectl create -f 'https://strimzi.io/install/latest?namespace=kafka' -n kafka
    
  3. 运行以下命令以应用 kafka 群集 CR 文件。

    kubectl apply -f https://strimzi.io/examples/latest/kafka/kafka-persistent-single.yaml -n kafka
    
  4. 使用 GitHub 中工作负载的 bash 脚本来准备 RSA 加密/解密密钥。 将文件另存为 setup-key.sh

  5. 运行以下命令,将 MAA_ENDPOINT 环境变量设置为证明 URI 的 FQDN。

    export MAA_ENDPOINT="$(az attestation show --name "myattestationprovider" --resource-group "MyResourceGroup" --query 'attestUri' -o tsv | cut -c 9-)"
    

    检查证明 URI 的 FQDN 是否采用了正确的格式(MAA_ENDPOINT不应包含前缀“https://”):

    echo $MAA_ENDPOINT
    

    注释

    若要设置 Azure 证明,请参阅[快速入门:使用 Azure CLI 设置 Azure 证明][attestation-quickstart-azure-cli]。

  6. 复制以下 YAML 清单并将其另存为 consumer.yaml

    apiVersion: v1
    kind: Pod
    metadata:
      name: kafka-golang-consumer
      namespace: kafka
      labels:
        azure.workload.identity/use: "true"
        app.kubernetes.io/name: kafka-golang-consumer
    spec:
      serviceAccountName: workload-identity-sa
      runtimeClassName: kata-cc-isolation
      containers:
        - image: "mcr.azk8s.cn/aci/skr:2.7"
          imagePullPolicy: Always
          name: skr
          env:
            - name: SkrSideCarArgs
              value: ewogICAgImNlcnRjYWNoZSI6IHsKCQkiZW5kcG9pbnRfdHlwZSI6ICJMb2NhbFRISU0iLAoJCSJlbmRwb2ludCI6ICIxNjkuMjU0LjE2OS4yNTQvbWV0YWRhdGEvVEhJTS9hbWQvY2VydGlmaWNhdGlvbiIKCX0gIAp9
          command:
            - /bin/skr
          volumeMounts:
            - mountPath: /opt/confidential-containers/share/kata-containers/reference-info-base64
              name: endor-loc
        - image: "mcr.azk8s.cn/acc/samples/kafka/consumer:1.0"
          imagePullPolicy: Always
          name: kafka-golang-consumer
          env:
            - name: SkrClientKID
              value: kafka-encryption-demo
            - name: SkrClientMAAEndpoint
              value: sharedeus2.eus2.test.attest.chinacloudapi.cn
            - name: SkrClientAKVEndpoint
              value: "myKeyVault.vault.azure.cn"
            - name: TOPIC
              value: kafka-demo-topic
          command:
            - /consume
          ports:
            - containerPort: 3333
              name: kafka-consumer
          resources:
            limits:
              memory: 1Gi
              cpu: 200m
      volumes:
        - name: endor-loc
          hostPath:
            path: /opt/confidential-containers/share/kata-containers/reference-info-base64
    ---
    apiVersion: v1
    kind: Service
    metadata:
      name: consumer
      namespace: kafka
    spec:
      type: LoadBalancer
      selector:
        app.kubernetes.io/name: kafka-golang-consumer
      ports:
        - protocol: TCP
          port: 80
          targetPort: kafka-consumer
    

    注释

    更新 Pod 环境变量 SkrClientAKVEndpoint 的值以匹配 Azure 密钥保管库 的 URL,不包括协议值 https://。 当前值占位符值为 myKeyVault.vault.azure.cn。 将 Pod 环境变量 SkrClientMAAEndpoint 的值更新为 MAA_ENDPOINT 的值。 可以通过运行命令 MAA_ENDPOINT 或命令 echo $MAA_ENDPOINT 来查找 az attestation show --name "myattestationprovider" --resource-group "MyResourceGroup" --query 'attestUri' -o tsv | cut -c 9- 的值。

  7. 运行以下命令,为 Kafka 使用者 YAML 清单生成安全策略,并获取存储在 WORKLOAD_MEASUREMENT 变量中的安全策略的哈希:

    export WORKLOAD_MEASUREMENT=$(az confcom katapolicygen -y consumer.yaml --print-policy | base64 -d | sha256sum | cut -d' ' -f1)
    
  8. 若要生成 RSA 非对称密钥对(公钥和私钥),请使用以下命令运行 setup-key.sh 脚本。 <Azure 密钥保管库 URL> 值应为 <your-unique-keyvault-name>.vault.azure.cn

    export MANAGED_IDENTITY=${USER_ASSIGNED_CLIENT_ID}
    bash setup-key.sh "kafka-encryption-demo" <Azure Key Vault URL>
    

    注释

    • Bash 脚本 MANAGED_IDENTITY 需要环境变量 setup-key.sh

    • 执行 bash 脚本后,公钥将另存为 kafka-encryption-demo-pub.pem

    重要

    如果收到错误 ForbiddenByRbac,则你可能需要等待最多 24 小时,因为托管标识的后端服务将每个资源 URI 的缓存保留最多 24 小时。 另请参阅:Azure RBAC 故障排除

  9. 为验证密钥是否已成功上传到密钥保管库,请运行以下命令:

    az account set --subscription <Subscription ID>
    az keyvault key list --vault-name <KeyVault Name> -o table
    
  10. 复制以下 YAML 清单并将其另存为 producer.yaml

    apiVersion: v1
    kind: Pod
    metadata:
      name: kafka-producer
      namespace: kafka
    spec:
      containers:
        - image: "mcr.azk8s.cn/acc/samples/kafka/producer:1.0"
          name: kafka-producer
          command:
            - /produce
          env:
            - name: TOPIC
              value: kafka-demo-topic
            - name: MSG
              value: "Azure Confidential Computing"
            - name: PUBKEY
              value: |-
                -----BEGIN PUBLIC KEY-----
                MIIBojAN***AE=
                -----END PUBLIC KEY-----
          resources:
            limits:
              memory: 1Gi
              cpu: 200m
    

    注释

    将以 -----BEGIN PUBLIC KEY----- 开头且以 -----END PUBLIC KEY----- 字符串结尾的值更新为在上一步中创建的 kafka-encryption-demo-pub.pem 中的内容。

  11. 使用之前保存的文件部署 consumerproducer YAML 清单。

    kubectl apply -f consumer.yaml
    
    kubectl apply -f producer.yaml
    
  12. 使用以下命令获取 Web 服务的 IP 地址:

    kubectl get svc consumer -n kafka
    
  13. 将使用者服务的外部 IP 地址复制并粘贴到浏览器中,并观察解密的消息。

    命令的输出类似于以下示例:

    Welcome to Confidential Containers on AKS!
    Encrypted Kafka Message:
    Msg 1: Azure Confidential Computing
    
  14. 还应尝试通过移除 skr containerkata-cc runtime class 规范以常规 Kubernetes Pod 的形式运行使用者。由于未使用 kata-cc 运行时类运行使用者,因此不再需要该策略。

  15. 删除整个策略,并在重新部署工作负载后在浏览器中再次观察消息。 消息显示为 base64 编码的已加密文本,因为无法检索私钥。 无法检索密钥,因为使用者不再在机密环境中运行,并且缺少 skr container,从而无法解密消息。

清理行动

完成此功能的评估后,为避免 Azure 费用,请清理不必要的资源。 如果在评估或测试过程中部署了新群集,则可以使用 az aks delete 命令删除该群集。

az aks delete --resource-group myResourceGroup --name myAKSCluster

如果在现有群集上启用了机密容器(预览版),则可以使用 kubectl delete pod 命令删除 Pod。

kubectl delete pod pod-name

后续步骤

  • 详细了解如何对 AKS 群集中的节点使用 Azure 专用主机,以便对 Azure 平台维护事件使用硬件隔离和控制。