【技术预览】创建支持TDX物理机机密沙箱容器的ACK节点池

您可以在容器服务 Kubernetes 版ACK集群Pro中创建TDX机密沙箱容器节点池,以保障业务数据的机密性、完整性。通过ACK机密物理机节点池和安全沙箱容器技术,您无需改造应用本身,仅需调整PodruntimeClass,便可无缝切换应用的最小化信任域的高安全水位,适用于金融风控、医疗隐私数据、AIGCLLM推理和微调、机密数据库、大数据应用等多种机密计算场景。本文介绍如何创建支持TDX物理机机密沙箱容器的ACK节点池,并结合应用部署示例介绍基于TDX实例的CoCo机密容器方案的部分核心特性。

前提条件

  • 已获得本方案的内测资格。

    目前本方案为技术预览方案,正在内测中。如需使用,请提交工单联系容器服务团队。

  • 已在华北2(北京)地域创建一个ACK集群Pro,具体操作,请参见创建Kubernetes托管版集群。且集群符合以下要求:

    • 集群版本需为1.26.3-aliyun.1及以上。如低于此版本,请升级ACK集群

    • 集群的网络插件需选择Flannel。

    • 集群内安装的csi-plugin组件版本为v1.28.1-ad4bd6a-aliyun及以上。

      此组件版本目前处于内测中。请提交工单联系容器服务团队。

功能介绍

随着企业与个人对数据隐私保护日益关切,机密计算技术应运而生。其核心技术之一是在芯片中创建一个可信执行环境TEE(Trusted Execution Environment),以保证数据和计算过程的机密性、完整性,并保障您的应用免受其他应用、其他租户、第三方平台甚至自己内部团队带来的潜在安全隐患。

容器服务 Kubernetes 版CoCo机密容器、Intel® TDX、龙蜥社区安全容器RunD通力合作,推出基于ACK TDX物理机机密沙箱容器的技术参考架构,提供端到端零信任(End-to-End Zero Trust)的应用、数据和模型保护。

展开查看CoCo机密容器的介绍

云原生基金会(CNCF)旗下的一个沙箱项目,使用硬件TEE为容器化的工作负载提供机密性和完整性保障,确保应用和数据安全可信。CoCo机密容器的威胁模型(Threat Modeling)更为严苛,将Kubernetes控制面和宿主机组件排除在可信计算基(Trusted Computing Base,TCB)之外。

通过将机密计算引入云原生领域,CoCo机密容器增强了虚拟机管理器程序VMM TCB内镜像加解密以及对象存储等数据的加解密能力,最小化数据面的攻击面,还支持以云原生的方式轻松部署、扩展和运维高安全水位应用。

CoCo机密容器支持多种机密计算场景,例如AI推理和微调、机密数据、大数据应用等。

展开查看Intel® TDX的介绍

第四代Intel®至强®可扩展处理器内置的虚拟机级别的TEE。通过硬件级内存加密和远程证明技术,保障数据的机密性(确保数据使用过程中不外泄)和完整性(确保数据处理过程中不被篡改),实现用户数据的程序访问安全,无恶意代码植入。

展开查看龙蜥社区安全容器RunD的介绍

龙蜥社区开源的下一代容器解决方案,包含Rust Kata runtimeDragonball VMM。安全容器RunD2022年由龙蜥云原生SIG开源至Kata Containers社区,且作为Kata Container 3.0.0 release的重要特性。

展开查看阿里云远程证明服务的介绍

支持租户级别的远程证明服务,可以建立对TEE从硬件到软件的全栈信任,从而实现密钥注入、证书注入等核心的安全需求。

展开查看ACK机密沙箱容器节点池的介绍

可以为机密计算节点提供无缝的扩缩容能力,还可以提升主机操作系统和硬件的机密性。您可以以云原生的方式将应用轻松部署到ACK机密沙箱容器节点池,以扩展和运维高安全水位的应用。ACK机密沙箱容器节点池支持多种机密计算场景,例如金融风控、医疗健康数据隐私保护、AIGCLLM推理和微调、机密数据库、大数据应用等。

image

AIGC/LLM场景为例,下图介绍如何结合TDX、AMX等多种硬件能力以及对模型数据的全链路保护,实现端到端的安全推理。

image

步骤一:创建自定义镜像

  1. 登录ECS管理控制台

  2. 在左侧导航栏,选择实例与镜像 > 镜像

  3. 在页面左侧顶部,选择目标资源所在的地域,华北2(北京)

  4. 镜像页面,单击共享镜像页签,选择目标镜像(内测申请通过后,账号自动显示共享镜像),然后在操作列单击复制镜像,并按照页面提示完成配置。

    关于复制镜像的配置信息,请参见复制镜像

步骤二:创建节点池

  1. 登录容器服务管理控制台,在左侧导航栏选择集群

  2. 集群列表页面,单击目标集群名称,然后在左侧导航栏,选择节点管理 > 节点池

  3. 在页面右上角,单击创建节点池,按照页面提示完成配置,然后单击确认配置

    下文仅介绍主要配置项。更多信息,请参见创建节点池

    配置项

    描述

    虚拟交换机

    华北2(北京)可用区L下的虚拟交换机。

    实例规格

    选择内测中的TDX弹性裸金属服务器实例规格。

    期望节点数

    节点池初始节点数量。填写为1,确保集群内节点池中至少有1个可供调度的节点。

    以下为高级配置(页面下拉,单击显示高级选项

    节点标签

    为了便于将Pod调度到该节点池,建议设置节点标签。

    • 键:coco-workload-worker

    • 值:true

    自定义镜像

    按照页面提示选择步骤一创建的自定义镜像。

步骤三:部署远程证明服务的核心组件

您可以通过以下步骤在ACK集群Pro中部署CoCo机密容器方案中远程证明服务的两个核心组件:KBS(Confidential Containers Key Broker Service)和 AS(Attestation Service)。

  1. 执行以下命令,使用Helm部署远程证明服务。

    helm install -n coco-kbs --create-namespace coco-kbs \
    	--set keyprovider.service.loadBalancerType=public \
    	https://aliacs-app-catalog.oss-cn-hangzhou.aliyuncs.com/pre/charts-incubator/coco-kbs-0.2.0.tgz

    预期输出:

    NAME: coco-kbs
    LAST DEPLOYED: Sun Oct 29 13:30:48 2023
    NAMESPACE: coco-kbs
    STATUS: deployed
    REVISION: 1
    TEST SUITE: None
  2. 等待几分钟后,检查Pod状态,确保运行正常。

    kubectl -n coco-kbs get pod

    预期输出:

    NAME                                                READY   STATUS    RESTARTS      AGE
    attestation-service-765454f84c-b2nxw                1/1     Running   0             38s
    kbs-0                                               2/2     Running   0             38s
    keyprovider-858b7f586f-tz5p4                        1/1     Running   0             38s
    reference-value-provider-service-6b69978c56-pptkz   1/1     Running   0             38s

    预期输出表明,KBSAS组件均已成功部署。

步骤四:部署机密容器Operator

您可以部署CoCo机密容器的Operator,为您的TDX实例自动部署和配置CoCo机密容器所需的Kata运行时kata-qemu-tdx和龙蜥社区的Dragonball机密容器运行时kata-dragonball-tdx。

  1. 执行以下命令,获取步骤三部署的KBS服务的对外访问地址。

    kubectl -n coco-kbs get svc kbs-slb-intranet

    预期输出:

    NAME               TYPE           CLUSTER-IP      EXTERNAL-IP   PORT(S)           AGE
    kbs-slb-intranet   LoadBalancer   192.168.X.X     10.1.X.X      60000:30057/TCP   7m45s

    记录此处EXTERNAL-IP供下一步使用。

  2. 执行以下命令,使用Helm部署Operator。

    需将<KBS-EXTERNAL-IP>替换为上一步获取的EXTERNAL-IP

    helm install -n coco-system --create-namespace coco-operator \
    https://aliacs-app-catalog.oss-cn-hangzhou.aliyuncs.com/pre/charts-incubator/coco-operator-0.2.0.tgz \
    --set kbs_addr=http://<KBS-EXTERNAL-IP>:60000

    预期输出:

    NAME: coco-operator
    LAST DEPLOYED: Sun Oct 29 13:39:58 2023
    NAMESPACE: coco-system
    STATUS: deployed
    REVISION: 1
    TEST SUITE: None
  3. 等几分钟后,检查Pod状态,确保运行正常。

    kubectl -n coco-system get pod

    预期输出:

    NAME                                              READY   STATUS    RESTARTS   AGE
    cc-operator-controller-manager-5564444fbb-pjkqw   2/2     Running   0          57s
    cc-operator-daemon-install-zts5d                  2/2     Running   0          44s
    cc-operator-pre-install-daemon-d2wjz              1/1     Running   0          48s
    cc-qgsd-multiplexer-hlg58                         2/2     Running   0          58s
  4. 执行以下命令,查看集群中的容器运行时,确认部署正常。

    kubectl get runtimeclass

    预期输出:

    NAME                  HANDLER               AGE
    kata                  kata-qemu             3m7s
    kata-dragonball-tdx   kata-dragonball-tdx   3m9s
    kata-qemu             kata-qemu             3m8s
    kata-qemu-tdx         kata-qemu-tdx         3m8s

    预期输出中包含两种基于TDX安全特性实现的机密容器运行时:

    • kata-dragonball-tdx:龙蜥社区的Dragonball运行时。

    • kata-qemu-tdx:CoCo机密容器的机密容器运行时。

步骤五:部署示例应用

本小节将部署几类示例应用,介绍如何在ACK集群Pro中基于TDX实例实现CoCo机密容器方案的部分核心特性。关于CoCo机密容器方案的更多特性,请参考Confidential Containers

说明

部署应用时,您可以通过配置PodruntimeClassName字段,指定使用不同的机密容器运行时:kata-dragonball-tdxkata-qemu-tdx。

部署普通应用

  1. 将以下内容保存为hello-tdx.yaml。

    apiVersion: v1
    kind: Pod
    metadata:
      name: hello-tdx
    spec:
      runtimeClassName: kata-dragonball-tdx
      containers:
      - name: hello
        image: alibaba-cloud-linux-3-registry.cn-hangzhou.cr.aliyuncs.com/alinux3/alinux3:latest
        imagePullPolicy: Always
        command:
         - sh
         - -c
         - 'echo hello && sleep infinity'
  2. 执行以下命令,在TDX节点上部署一个名为hello-tdx、使用CoCo机密容器的应用。

    kubectl apply -f hello-tdx.yaml

    预期输出:

    pod/hello-tdx created
  3. 验证Pod对应的Kata虚拟机内存是否加密。

    基于TDX安全特性实现的CoCo机密容器方案中,每个Pod对应的Kata虚拟机的内存是加密的。可以通过以下方式进行验证。

    1. 登录部署当前应用的TDX节点。

    2. 执行以下命令,找到应用对应的Kata虚拟机进程。

      ps -ef|grep qemu-system-x86_64-tdx

      预期输出:

      root     3097264 3097253  3 16:22 ?        00:00:04 /opt/kata/bin/qemu-system-x86_64-tdx-experimental 

      记录此处进程实际PID,即预期输出的第二个值,例如3097264,供下一步使用。

    3. 执行以下命令,验证Kata虚拟机内存是否加密。

      需将<pid>替换为上一步预期输出中的进程PID。

      gcore <pid>
      strings core.<pid> |grep sleep

      命令执行完成后,grep命令的预期输出为空,表明core.<pid>文件中的内存数据中不包含应用的启动命令。普通容器未加密时,coredump文件中会包含对应的应用启动命令以及其他敏感内存数据。

部署使用对象存储OSS的应用

CoCo机密容器方案支持直接在Kata虚拟机中挂载应用依赖的OSS Bucket。相较于传统方式下在节点上挂载OSS Bucket,CoCo机密容器方案安全性更高。

  1. 华北2(北京)地域创建一个测试用的OSS Bucket。具体操作,请参见创建存储空间

  2. 准备一个拥有OSS测试Bucket读写操作权限的RAM用户,并记录此RAM用户的Access KeyAccess Key Secret。

    相关操作,请参见创建RAM用户RAM用户授权查看RAM用户的AccessKey信息

  3. 执行以下命令,将RAM用户的Access KeyAccess Key Secret存储到KBS中。

    CoCo机密容器方案也支持将OSS访问凭证存储到阿里云密钥管理服务KMS中。更多信息,请参见Confidential Containers官方文档

    需将<akid>替换为RAM用户的Access Key,<akSecret>替换为RAM用户的Access Key Secret。

    echo -n '<akid>' > akId.txt
    echo -n '<akSecret>' > akSecret.txt
    
    kubectl -n coco-kbs create secret generic kbs-resource-oss-keys \
    --from-file default.credential.oss-akId=akId.txt \
    --from-file default.credential.oss-akSecret=akSecret.txt
    
    kubectl -n coco-kbs label secret kbs-resource-oss-keys coco-kbs-resource=true
  4. 执行以下命令,创建引用这个凭证的Sealed Secret。

    Sealed SecretCoCo机密容器社区提出的一种Secret加密方案。

    展开查看完整代码

    cat <<EOF > vault-kbs-oss-ak.json
    {
      "version": "0.1.0",
      "type": "vault",
      "name": "kbs:///default/credential/oss-akId",
      "provider": "kbs",
      "provider_settings": {},
      "annotations": {}
    }
    EOF
    
    cat <<EOF > vault-kbs-oss-sk.json
    {
      "version": "0.1.0",
      "type": "vault",
      "name": "kbs:///default/credential/oss-akSecret",
      "provider": "kbs",
      "provider_settings": {},
      "annotations": {}
    }
    EOF
    
    cat <<EOF > vault-kbs-gocryptfs-passwd.json
    {
      "version": "0.1.0",
      "type": "vault",
      "name": "kbs:///default/credential/oss-gocryptfs-passwd",
      "provider": "kbs",
      "provider_settings": {},
      "annotations": {}
    }
    EOF
    
    printf "sealed.fakejwsheader.%s.fakejwssignature" `cat vault-kbs-oss-ak.json | base64 -w 0` > sealed-akId.txt
    
    printf "sealed.fakejwsheader.%s.fakejwssignature" `cat vault-kbs-oss-sk.json | base64 -w 0` > sealed-akSecret.txt
    
    kubectl create secret generic sealed-secret-oss \
    	--from-file akId=sealed-akId.txt \
    	--from-file akSecret=sealed-akSecret.txt
  5. 将以下内容保存为coco-oss-direct-assigned.yaml,用于在CoCo机密容器环境中部署名为oss-direct-assigned、使用OSS的应用。

    需将<bucket_name>替换为您OSS Bucket的名称。

    展开查看完整的YAML文件

    ---
    apiVersion: v1
    kind: PersistentVolume
    metadata:
      name: pv-oss-direct-assigned
      labels:
        alicloud-pvname: pv-oss-direct-assigned
    spec:
      capacity:
        storage: 5Gi
      accessModes:
        - ReadWriteMany
      persistentVolumeReclaimPolicy: Retain
      csi:
        driver: ossplugin.csi.alibabacloud.com
        volumeHandle: pv-oss-direct-assigned
        volumeAttributes:
          direct: "true"
          bucket: "<bucket_name>"
          url: "oss-cn-beijing.aliyuncs.com"
          otherOpts: "-o max_stat_cache_size=0 -o allow_other"
          path: "/"
        nodePublishSecretRef:
          namespace: default
          name: sealed-secret-oss
    
    ---
    apiVersion: v1
    kind: PersistentVolumeClaim
    metadata:
      name: pvc-oss-direct-assigned
    spec:
      accessModes:
        - ReadWriteMany
      resources:
        requests:
          storage: 5Gi
      selector:
        matchLabels:
          alicloud-pvname: pv-oss-direct-assigned
    
    ---
    apiVersion: v1
    kind: Pod
    metadata:
      name: oss-direct-assigned
    spec:
      runtimeClassName: kata-dragonball-tdx
      containers:
      - image: alibaba-cloud-linux-3-registry.cn-hangzhou.cr.aliyuncs.com/alinux3/alinux3:latest
        imagePullPolicy: Always
        name: hello
        command:
         - sh
         - -c
         - 'echo hello && sleep infinity'
        volumeMounts:
          - name: pvc-oss
            mountPath: "/data"
      volumes:
        - name: pvc-oss
          persistentVolumeClaim:
            claimName: pvc-oss-direct-assigned
  6. 执行以下命令,部署示例应用。

    kubectl apply -f coco-oss-direct-assigned.yaml

    预期输出:

    persistentvolume/pv-oss-direct-assigned created
    persistentvolumeclaim/pvc-oss-direct-assigned created
    pod/oss-direct-assigned created

    应用成功运行后,Pod容器内的/data目录将挂载您所指定的OSS Bucket目录下的内容。您还可以登录部署应用的TDX节点,确认节点下并未挂载对应的OSS Bucket。

部署使用加密镜像的应用

您可以通过以下步骤创建一个加密镜像,再将其部署到使用机密容器的节点池中。

  1. 华北2(北京)地域创建一个ACR企业版实例。具体操作,请参见创建企业版实例。同时,还需完成使用ACR企业版实例的前置工作,包括绑定源代码平台、创建命名空间、创建镜像仓库等。具体操作,请参见使用企业版实例构建镜像的步骤一至三。

  2. 下载并安装skopeo命令行工具。具体操作,请参见skopeo

    skopeo是一个用于在容器镜像之间复制、转换和检查的命令行工具。

  3. 配置skopeo。

    1. 执行以下命令,获取步骤三所部署的Keyprovider服务的对外访问地址。

      kubectl -n coco-kbs get svc keyprovider-slb-public

      预期输出:

      NAME                       TYPE           CLUSTER-IP       EXTERNAL-IP   PORT(S)           AGE
      keyprovider-slb-public     LoadBalancer   192.168.X.X      10.1.X.X      60001:31195/TCP   4h41m

      记录此处的EXTERNAL-IP供下一步使用。

    2. 通过以下命令配置skopeo。

      需将<keyprovider_ip>替换为上一步获取到的EXTERNAL-IP

      $ cat ocicrypt_keyprovider.conf
      {
              "key-providers": {
                      "attestation-agent": {
                          "grpc": "<keyprovider_ip>:60001"
      
                      }
              }
      }
      
      
      $ export OCICRYPT_KEYPROVIDER_CONFIG=ocicrypt_keyprovider.conf
  4. 推送一个加密镜像。

    1. 执行以下命令,下载示例镜像。

      skopeo copy --all \
          docker://alibaba-cloud-linux-3-registry.cn-hangzhou.cr.aliyuncs.com/alinux3/alinux3:latest \
      		oci:raw-alinux3:latest

      预期输出:

      Getting image list signatures
      Copying 2 of 2 images in list
      Copying image sha256:4c1f42a5e24d337e291d1120ce94ed8e4b3ed7333d788b2a8c6804********** (1/2)
      Getting image source signatures
      Copying blob 66727bf7**** done
      Copying blob 4ce27f50**** done
      Copying config 007dd1**** done
      Writing manifest to image destination
      Storing signatures
      Copying image sha256:7e9391ad510b008c18f285827b71cbb942f8b878c954dd12923dbc********** (2/2)
      Getting image source signatures
      Copying blob ad0b3bcf**** done
      Copying blob 2b2d78fe**** done
      Copying config 64720e**** done
      Writing manifest to image destination
      Storing signatures
      Writing manifest list to image destination
      Storing list signatures
    2. 执行以下命令,登录ACR镜像仓库。

      需将<acr_ee_registry>替换为您的ACR企业版实例的访问域名。您可以在ACR实例详情页的左侧导航栏,选择仓库管理>访问控制,获取专有网络或公网访问域名。

      使用专有网络域名时,需保证命令执行环境与ACR实例所处的专有网络环境互通。

      展开查看如何配置镜像仓库专有网络

      访问控制页面,单击添加专有网络,选择ACK集群的专有网络和镜像节点的交换机,然后单击确定

      添加后,等待专有网络列表的状态列变更为已生效,表明添加成功。

      说明

      您可以登录容器服务管理控制台,在集群列表页面,单击目标集群名称,按照如下步骤获取相应地址。

      • 获取ACK集群专有网络:在左侧导航栏,选择集群信息,然后单击集群资源页签,查看集群虚拟专有网络VPC地址。

      • 获取镜像节点的交换机:在左侧导航栏,选择节点管理 > 节点池,单击目标节点池名称,然后单击基本信息页签,在节点配置区域,获取节点虚拟交换机地址。

      skopeo login <acr_ee_registry>
    3. 执行以下命令,加密示例镜像,然后将加密镜像推送到您的镜像仓库中。

      需将<acr_ee_registry>替换为ACR企业版实例的访问域名,<acr_namespace>替换为加密镜像所属的命名空间。

      skopeo copy --encryption-key provider:attestation-agent --all \
          oci:raw-alinux3:latest  \
          docker://<acr_ee_registry>/<acr_namespace>/encrypted-alinux3:latest

      预期输出:

      Getting image list signatures
      Copying 2 of 2 images in list
      Copying image sha256:1170c7c5e3a58bce9d9be9b55a40aa1f15de685c074b99928b938c0********** (1/2)
      Getting image source signatures
      Copying blob 4ce27f5**** done
      Copying blob 66727bf**** done
      Copying config 007dd**** done
      Writing manifest to image destination
      Storing signatures
      Copying image sha256:f3a57e83afad5bca8a3515e175e4f4108677a0083cb326d139ac7b9********** (2/2)
      Getting image source signatures
      Copying blob 2b2d78fe**** done
      Copying blob ad0b3bcf**** done
      Copying config 64720e**** done
      Writing manifest to image destination
      Storing signatures
      Writing manifest list to image destination
      Storing list signatures
  5. 执行以下命令,确认推送的镜像已加密。

    需将<acr_ee_registry>替换为ACR企业版实例的访问域名,<acr_namespace>替换为加密镜像所属的命名空间。

    docker pull <acr_ee_registry>/<acr_namespace>/encrypted-alinux3:latest

    预期输出:

    latest: Pulling from <acr_namespace>/encrypted-alinux3
    9276d588****: Extracting [==================================================>]  62.17MB/62.17MB
    3e722277****: Download complete
    failed to register layer: Error processing tar file(exit status 1): archive/tar: invalid tar header
  6. 执行以下命令,为CoCo机密容器配置镜像拉取密码。

    需将<auth>替换为ACR实例的镜像拉取凭证。该凭证的格式为:base64编码后的用户名:密码字符串,不包括换行符。您可以通过命令echo -n 用户名:密码 | base64 -w 0来生成。

    $ cat  image-auths.json
    {
        "auths": {
            "imgcrypt-demo-registry.cn-beijing.cr.aliyuncs.com": {
                "auth": "<auth>"
            }
        }
    }
    
    
    kubectl -n coco-kbs create secret generic kbs-resource-image-auths \
    --from-file default.credential.image-auths.json=image-auths.json
    
    kubectl -n coco-kbs label secret kbs-resource-image-auths coco-kbs-resource=true
  7. 执行以下命令,部署名为encrypted-alinux3、使用加密镜像的应用。

    需将<acr_ee_registry>替换为ACR企业版实例的访问域名,<acr_namespace>替换为加密镜像所属的命名空间。

    $ cat encrypted-alinux3.yaml
    apiVersion: v1
    kind: Pod
    metadata:
      name: encrypted-alinux3
    spec:
      runtimeClassName: kata-dragonball-tdx
      containers:
      - name: hello
        image: <acr_ee_registry>/<acr_namespace>/encrypted-alinux3:latest
        command:
         - sh
         - -c
         - 'echo hello && sleep infinity'
    
    $ kubectl apply -f encrypted-alinux3.yaml
  8. 等待几分钟后,执行以下命令查看应用是否已部署成功。

    $ kubectl get pod encrypted-alinux3

    预期输出:

    NAME                READY   STATUS    RESTARTS   AGE
    encrypted-alinux3   1/1     Running   0          1m