使用机密容器和自动生成的策略部署 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 年 10 月 31 日开始,将删除节点映像,并且无法缩放节点池。 通过将 节点池升级到 受支持的 Kubernetes 版本或迁移到 osSku AzureLinux3,迁移到受支持的 Azure Linux 版本。 有关详细信息,请参阅 停用 GitHub 问题和Azure 更新停用公告。 若要随时了解公告和更新,请关注AKS 发行说明。

先决条件

  • 最新版本的 Azure CLI。 可通过运行 az version 查找版本,运行 az upgrade 升级版本。 如果需要安装或升级,请参阅 安装 Azure CLI。
  • aks-preview Azure CLI 扩展的最新版本。
  • confcom机密容器 Azure CLI 扩展的最新版本。
  • 工作负载标识和联合标识凭据。 使用工作负载标识凭据,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) 集成,以便在验证完成后将密钥发布到容器组。 部署 Azure 密钥保管库 托管 HSM(硬件安全模块)是可选的,但建议支持容器级完整性和证明。 请参阅预配和激活托管 HSM 以部署托管 HSM。

安装 aks-preview Azure CLI 扩展

重要

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

  1. 运行以下命令以安装 aks-preview 扩展:

    az extension add --name aks-preview
    
  2. 运行以下命令以更新到最新扩展版本:

    az extension update --name aks-preview
    

安装 confcom Azure CLI 扩展

  1. 运行以下命令以安装 confcom 扩展:

    az extension add --name confcom
    
  2. 运行以下命令以更新到最新扩展版本:

    az extension update --name confcom
    

注册 KataCcIsolationPreview 功能标志

  1. az feature register运行以下命令以注册KataCcIsolationPreview功能标志,如以下示例所示:

    az feature register --namespace "Microsoft.ContainerService" --name "KataCcIsolationPreview"
    
  2. 等待几分钟,状态显示 已注册。 az feature show运行以下命令以验证注册状态:

    az feature show --namespace "Microsoft.ContainerService" --name "KataCcIsolationPreview"
    
  3. 当状态显示为 “已注册” 时,运行 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 大小都可以。
    • --enable-workload-identity:启用创建 Microsoft Entra Workload ID,使 Pod 能够使用 Kubernetes 标识。
    • --enable-oidc-issuer:启用 OpenID Connect (OIDC) 证书颁发者。 它允许 Microsoft Entra ID 或其他云提供商的标识和访问管理平台发现 API 服务器的公开签名密钥。
    • --workload-runtime:指定 KataCcIsolation 以在节点池上启用机密容器功能。
    az aks create --resource-group myResourceGroup --name myAKSCluster --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,其中有两个节点在 myResourceGroup 的 nodepool2 中:

    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_NAMESPACEkafka设置为,并在配置工作负荷标识之前运行命令kubectl create namespace kafka。

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

以下步骤使用由Azure 托管硬件安全模块(Managed HSM)管理的加密密钥,为 Kafka 消息配置端到端加密。 仅当 Kafka 消费者在机密容器中运行,且其所在的 pod 中注入了 Azure 证明机密预配容器时,才会发放该密钥。

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

  • 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 角色。

    注释

    • 托管标识是分配给 USER_ASSIGNED_IDENTITY_NAME 变量的值。

    • 若要添加角色分配,必须拥有 Microsoft.Authorization/roleAssignments/write 和 Microsoft.Authorization/roleAssignments/delete 权限,例如 密钥保管库 数据访问权限管理员、用户访问权限管理员或所有者。

    • 你必须使用 密钥保管库“高级”SKU 才能支持受 HSM 保护的密钥。

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

    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
    
  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 脚本 setup-key.sh 需要环境变量 MANAGED_IDENTITY。

    • 执行 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. 使用之前保存的文件部署 consumer 和 producer 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 container 和 kata-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 平台维护事件使用硬件隔离和控制。