Confidential Containers(CoCo)为容器工作负载提供了一层关键的安全隔离——即使在平台部分不可信的环境下,也能通过硬件可信执行环境(如 AMD SEV-SNP、Intel TDX)保护运行中的数据。但现实是:要让一个普通 Pod 跑在 CoCo 环境里,应用团队往往需要手动指定 runtimeClass、添加节点选择器、配置加密参数等一堆基础设施细节。这些细节既容易出错,又把安全策略的执行责任推给了不该承担它的人。Kyverno 的策略引擎恰好能解决这个问题——用声明式策略把 CoCo 的基础设施配置自动化,让应用团队只管写业务代码。
CoCo 的部署痛点在哪
一个标准的 Kubernetes Pod 要跑在 CoCo 环境中,至少需要以下改动:
- 指定
runtimeClass:必须设为kata-cc或对应运行时类,否则 Pod 仍跑在普通 runc 容器里。 - 节点调度约束:CoCo Pod 只能调度到启用了对应硬件特性的节点上,需要添加
nodeSelector或亲和性规则。 - 镜像加密配置:某些场景下容器镜像需要加密拉取,涉及额外的 annotation 或 secret 引用。
应用开发者本该只关心业务逻辑,但现在却被迫理解底层安全架构。更麻烦的是,如果某个团队忘了加 runtimeClass,CoCo 的保护就形同虚设——Pod 照常运行,但没有任何机密性保障,且这种"静默失败"很难被发现。
Kyverno 如何接管这些配置
Kyverno 是 Kubernetes 原生的策略引擎,支持三种核心动作:验证(validate)、变更(mutate)、生成(generate)。在 CoCo 场景中,变更策略是主力——它能在 Pod 创建时自动注入所需的基础设施字段,应用团队提交的原始 YAML 完全不需要改动。
核心思路:
- 应用团队提交一个普通 Pod 或 Deployment,不带任何 CoCo 相关字段。
- Kyverno 的变更策略根据标签或命名空间等条件,自动为 Pod 注入
runtimeClass、nodeSelector和必要的 annotation。 - 验证策略作为兜底,确保关键工作负载不会遗漏 CoCo 配置。
实战:用 Kyverno 策略自动注入 CoCo 配置
下面给出三个可以直接复制使用的 Kyverno 策略,覆盖最常见的 CoCo 自动化场景。
策略一:自动注入 runtimeClass
任何带 confidential-containers.io/enabled: "true" 标签的命名空间中的 Pod,自动设置 runtimeClassName 为 kata-cc:
apiVersion: kyverno.io/v1
kind: ClusterPolicy
metadata:
name: inject-coco-runtimeclass
spec:
rules:
- name: mutate-runtimeclass
match:
any:
- resources:
kinds:
- Pod
namespaceSelectors:
matchLabels:
confidential-containers.io/enabled: "true"
mutate:
patchStrategicMerge:
spec:
runtimeClassName: kata-cc
使用前确保集群中已安装 CoCo 运行时类:
# 检查 runtimeClass 是否存在
kubectl get runtimeclass kata-cc
# 如果不存在,先创建(CoCo 安装脚本通常会自动创建)
kubectl apply -f - <<EOF
apiVersion: node.k8s.io/v1
kind: RuntimeClass
metadata:
name: kata-cc
handler: kata-cc
overhead:
podFixed:
memory: "120Mi"
cpu: "250m"
scheduling:
nodeSelector:
confidential-containers.io/runtime: "kata-cc"
EOF
策略二:自动添加节点选择器
CoCo Pod 必须调度到支持机密计算的节点。以下策略自动注入 nodeSelector:
apiVersion: kyverno.io/v1
kind: ClusterPolicy
metadata:
name: inject-coco-node-selector
spec:
rules:
- name: mutate-node-selector
match:
any:
- resources:
kinds:
- Pod
namespaceSelectors:
matchLabels:
confidential-containers.io/enabled: "true"
preconditions:
all:
- key: "{{ request.object.spec.runtimeClassName }}"
operator: Equals
value: "kata-cc"
mutate:
patchStrategicMerge:
spec:
nodeSelector:
confidential-containers.io/runtime: "kata-cc"
注意 preconditions 确保只在 runtimeClass 已被设为 kata-cc 的 Pod 上追加节点选择器,避免对普通 Pod 误操作。如果两个策略同时生效,Kyverno 会按策略优先级顺序依次变更,最终 Pod 同时拥有 runtimeClassName 和 nodeSelector。
策略三:验证兜底——阻止未启用 CoCo 的工作负载进入敏感命名空间
变更策略处理了"自动加上配置",但还需要验证策略防止"静默绕过"——确保标记为敏感的命名空间中,所有 Pod 都必须使用 CoCo 运行时:
apiVersion: kyverno.io/v1
kind: ClusterPolicy
metadata:
name: enforce-coco-runtimeclass
spec:
validationFailureAction: Enforce
rules:
- name: require-coco-runtimeclass
match:
any:
- resources:
kinds:
- Pod
namespaceSelectors:
matchLabels:
confidential-containers.io/enabled: "true"
validate:
message: "此命名空间要求所有 Pod 必须使用 kata-cc runtimeClass 以启用 Confidential Containers。"
pattern:
spec:
runtimeClassName: "kata-cc"
validationFailureAction: Enforce 意味着不合规的 Pod 直接被拒绝创建,而不是仅记录告警。
完整部署流程
把以上策略组合起来,一个典型的部署流程如下:
# 1. 给目标命名空间打标签
kubectl label namespace sensitive-workloads confidential-containers.io/enabled=true
# 2. 安装 Kyverno(如果集群中还没有)
kubectl apply -f https://github.com/kyverno/kyverno/releases/download/v1.12.0/install.yaml
# 3. 应用三个策略
kubectl apply -f inject-coco-runtimeclass.yaml
kubectl apply -f inject-coco-node-selector.yaml
kubectl apply -f enforce-coco-runtimeclass.yaml
# 4. 应用团队提交一个普通 Deployment(无需任何 CoCo 字段)
kubectl apply -f - <<EOF
apiVersion: apps/v1
kind: Deployment
metadata:
name: my-sensitive-app
namespace: sensitive-workloads
spec:
replicas: 2
selector:
matchLabels:
app: my-sensitive-app
template:
metadata:
labels:
app: my-sensitive-app
spec:
containers:
- name: app
image: myregistry.io/my-sensitive-app:v1.0
ports:
- containerPort: 8080
EOF
# 5. 验证 Kyverno 已自动注入配置
kubectl get deployment my-sensitive-app -n sensitive-workloads -o jsonpath='{.spec.template.spec.runtimeClassName}'
# 期望输出: kata-cc
kubectl get deployment my-sensitive-app -n sensitive-workloads -o jsonpath='{.spec.template.spec.nodeSelector}'
# 期望输出包含: confidential-containers.io/runtime=kata-cc
应用团队提交的 Deployment 中完全没有 CoCo 相关字段,但最终运行的 Pod 已经具备全部机密计算配置。
需要注意的边界与风险
- 性能开销:CoCo 运行时(Kata Containers)有额外的内存和 CPU overhead,上述 RuntimeClass 定义中已声明了
120Mi / 250m的固定开销。调度和容量规划时必须把这个开销算进去。 - 策略冲突:如果集群中已有其他变更策略修改 Pod 的
nodeSelector,需要确认 Kyverno 的策略优先级和合并逻辑不会产生冲突。建议用patchStrategicMerge而非patchJson6902,前者对 map 类型的字段会合并而非覆盖。 - 镜像加密的局限:CoCo 的镜像加密拉取(image decryption)需要额外配置 key broker 和 secret 引用。Kyverno 可以通过生成策略(generate)自动创建关联的 Secret,但 key broker 的部署本身不在 Kyverno 的职责范围内,需要单独处理。
- 调试难度:CoCo Pod 运行在虚拟机隔离环境中,传统的
kubectl exec和kubectl logs行为会有差异。团队在迁移到 CoCo 前应先在测试环境验证调试流程。
落地建议
- 分阶段推进:先在非生产命名空间启用变更策略,观察注入结果和 Pod 运行状态;确认无误后再在敏感命名空间启用验证策略(Enforce 模式)。
- 命名空间驱动:用命名空间标签作为策略的触发条件,比逐个 Pod 打标签更易维护。新建敏感命名空间时只需打一个标签,所有工作负载自动获得 CoCo 保护。
- 监控策略执行:Kyverno 自带策略报告(PolicyReport)资源,定期检查可以发现变更失败或验证拦截的情况:
bash kubectl get policyreport -n sensitive-workloads - 与 GitOps 配合:Kyverno 策略本身是 Kubernetes 草案资源,可以纳入 Argo CD 或 Flux 的管理流程,确保策略变更也经过审批和版本控制。
把 CoCo 的基础设施配置从应用团队手中剥离出来,交给 Kyverno 自动执行,既减少了人为遗漏的风险,也让机密计算的采纳门槛大幅降低。应用开发者写的是普通 Deployment,跑出来的却是受硬件级隔离保护的 Pod——这才是安全基础设施该有的样子。