机密计算工程实战:从机密容器到机密 Kubernetes 的可信编排
云原生把算力变成了"租来的内存"。当模型权重、私有语料、推理请求流经同一个 hyperscaler 的物理机,传统加密只保护"静止"与"传输中"的数据,却对"使用中"的内存束手无策。机密计算(Confidential Computing)用 CPU 的硬件可信执行环境(TEE)把这段最后的盲区填上。本文聚焦既有资料较少涉及的容器与编排层——如何让 K8s 真正调度并验证一台"看不见内存"的机密节点。
读完你将掌握:TEE 威胁模型与三大家族差异、基于 Kata Containers 的机密容器装配、远程证明(Remote Attestation)的验签闭环,以及把 vLLM 推理服务跑在一台经过证明的机密节点上的完整部署清单。
一、为什么需要"机密容器":威胁模型先行
在共享租户的物理机上,云厂商的特权软件栈(hypervisor、host OS、固件、运维人员)对租户内存拥有天然可见性。传统威胁模型只防"外部攻击者",却默认信任云厂商。机密计算要回答的是更苛刻的问题:即便云厂商的 root 权限、物理内存抓取、甚至是被攻陷的 hypervisor,也无法读出你的运行时数据。
- 内存嗅探:通过 PCIe 抓包、内存条冷启动、或 hypervisor dump 读取明文内存。
- 特权敌手:被攻陷的 host kernel / hypervisor 仍可映射客户机物理页。
- 侧信道:缓存时序、页表访问模式等推断密钥或模型结构。
- 合规诉求:数据出境、金融/医疗敏感数据要求"使用中加密"的审计证据。
机密容器(Confidential Container)的思路是:把容器不直接跑在 host 上,而是跑在一台加密内存 + 测量启动(measured boot)的机密虚拟机里,再把这台 VM 当成普通的 K8s 节点暴露给调度器。租户的 workload 与 host 之间被一层硬件加密内存和证明边界彻底隔开。
二、技术基座:TEE 三大家族对比
| 技术 | 厂商 | 隔离边界 | 内存加密 | 证明粒度 |
|---|---|---|---|---|
| AMD SEV-SNP | AMD EPYC | VM 级,防 hypervisor | AES-128 全内存加密 + 页完整性 | VMPL + ATTESTATION report |
| Intel TDX | Intel Xeon | Trust Domain(TD)级 | AES-256 全内存加密(MKTME) | TDQUOTE(远程证明) |
| ARM CCA | ARMv9(Graviton4+) | Realm 级 | RME 粒度的物理内存保护 | Realm attestation token |
三者的工程目标一致——给"使用中"的数据上锁,但接口与证明流程各异。下面的实战以 SEV-SNP / TDX 为主轴,因为当前公有云的机密节点几乎都基于这两者。
三、机密容器架构:Kata Containers + 机密 VM
标准容器运行时(runc)直接复用 host 内核,天然不满足机密隔离。机密容器采用 Kata Containers:每个 Pod 背后是一台轻量虚拟机,guest kernel 与 host 完全隔离。当这台 VM 以 SEV-SNP/TDX 模式启动时,它的内存对 host 不可见,于是"容器"就运行在 TEE 之中。
| 组件 | 职责 |
|---|---|
| kata-runtime / shim | 拦截 CRI 请求,创建机密 VM 与 guest 内 agent 通信 |
| guest kernel + rootfs | 运行在加密内存中的迷你 OS,承载容器进程 |
| attestation agent | 生成并上报证明报告,获取解密密钥(sealing) |
| hardware TEE | CPU 侧内存加密引擎与密钥派生(如 AMD ASP / Intel TDX module) |
四、落地一:检测与验证 TEE 环境
在把 workload 放进去之前,先确认硬件与内核确实支持机密 VM。下面三组命令分别检测 SEV-SNP、TDX,以及机密字符设备是否就绪。
# 检测 AMD SEV-SNP 能力标志 grep -m1 -o 'sev_snp' /proc/cpuinfo # 检测 Intel TDX guest 标志 grep -m1 -o 'tdx_guest' /proc/cpuinfo # 查看机密计算相关字符设备 ls -l /dev/sev* 2>/dev/null ls -l /dev/tdx_guest 2>/dev/null
如果内核加载了机密驱动,可以用 Python 直接读取 SEV-SNP 的 attestation report 请求接口(注意 struct 格式串里的 < 表示小端):
import struct
# SEV-SNP 通过 misc 字符设备 /dev/sev-guest 获取 attestation report
DEV = "/dev/sev-guest"
# REPORT_REQ 布局(简化):用户数据(64B) + VMPL(4B) + 保留(4B)
USER_DATA = b"ybb-cc-attest-2026".ljust(64, b"\x00")
req = struct.pack("<64sI4s", USER_DATA, 0, b"\x00" * 4)
with open(DEV, "rb") as f:
f.write(req)
report = f.read(0x400) # 读取 report 响应
print("attestation report length:", len(report))
在 Rust 侧,可以通过 sysfs 粗略判断是否身处机密 VM:
// 检测当前进程是否运行在机密 VM 中
fn is_confidential_vm() -> bool {
std::fs::read_to_string("/sys/devices/system/cpu/cpu0/topology/tdx_guest")
.map(|s| s.trim() == "1")
.unwrap_or(false)
}
fn main() {
println!("running in confidential VM: {}", is_confidential_vm());
}
五、落地二:配置 Kata 机密运行时
让 containerd 多注册一个 kata-cc 运行时,专门启动机密 VM。先调整 Kata 的 hypervisor 配置,开启机密 guest 与对应固件:
[hypervisor.qemu] kernel = "/opt/kata/share/kata-kernel.confidential" image = "/opt/kata/share/kata-containers.img" machine_type = "q35" # 启用 SEV-SNP / TDX 机密虚拟机 confidential_guest = true firmware = "/opt/kata/share/kata-sev.fd" # 关闭主机可观测的串口,避免信息泄漏 default_vcpus = 8 default_memory = 16384
随后在 containerd 中挂接该运行时,并通过 RuntimeClass 暴露给 K8s:
# /etc/containerd/config.toml 片段 [plugins."io.containerd.grpc.v1.cri".containerd.runtimes.kata-cc] runtime_type = "io.containerd.kata.v2" [plugins."io.containerd.grpc.v1.cri".containerd.runtimes.kata-cc.options] ConfigPath = "/opt/kata/share/defaults/kata-confidential.toml"
apiVersion: node.k8s.io/v1 kind: RuntimeClass metadata: name: kata-cc handler: kata-cc
六、落地三:远程证明与密钥密封
光有加密内存还不够——租户需要密码学证据证明对端确实是预期的机密环境,而非伪造的 VM。远程证明(Remote Attestation)由硬件生成含 PCR 度量值的 quote,并由厂商 CA 签名;验证方用 CA 公钥校验签名并比对 PCR,确认运行时未被篡改。
import hashlib
def verify_quote(quote, expected_pcr, ca_pubkey):
# 1. 解析 quote:report_body + signature + cert_chain
report_body = quote["report_body"]
# 2. 校验厂商 CA 对 report 的签名
if not ca_pubkey.verify(report_body, quote["signature"]):
raise ValueError("attestation signature invalid")
# 3. 比对 PCR 度量值,防止加载了被篡改的运行时
if report_body["pcr"].hex() != expected_pcr:
raise ValueError("PCR mismatch: runtime tampered")
return True
# 验证通过后才可释放模型权重解密密钥(sealing / unwrap)
key = unwrap_sealed_key(quote) if verify_quote(quote, GOLDEN_PCR, CA) else None
关键工程点:密钥密封(Sealing)把密钥与特定 PCR 值绑定——只有度量值完全匹配的机密环境才能解封。这样即使攻击者复制了磁盘镜像,没有对应的 TEE 也无法恢复明文密钥。
七、落地四:机密 Kubernetes 上运行 vLLM 推理
把上述能力串起来:给机密节点打 label 与 taint,让推理 Pod 通过 runtimeClassName: kata-cc 调度进去,并在容器启动后、加载模型权重前完成证明。
apiVersion: v1
kind: Pod
metadata:
name: vllm-confidential
spec:
runtimeClassName: kata-cc
nodeSelector:
node.kubernetes.io/instance-type: confidential-vm
tolerations:
- key: "cc.node"
operator: "Equal"
value: "true"
effect: "NoSchedule"
containers:
- name: vllm
image: vllm/vllm-openai:latest
args: ["--model", "meta-llama/Llama-3-8B", "--enforce-eager"]
env:
- name: ATTESTATION_ENDPOINT
value: "https://attestation.local/verify"
- name: SEALED_WEIGHT_KEY
valueFrom:
secretKeyRef:
name: vllm-weight-key
key: sealed
推理服务启动脚本应先向 attestation 服务验明正身,拿到解封密钥后再从加密卷加载权重——这样权重在机密内存之外始终以密文存在。
八、性能与权衡
| 维度 | 普通容器 | 机密容器 |
|---|---|---|
| 冷启动延迟 | 亚秒级 | +2~5s(开机 + 证明) |
| 内存带宽 | 基准 | 下降 3%~8%(加密引擎) |
| I/O 吞吐 | 基准 | 近似基准(加密在内存控制器) |
| 数据机密性 | 依赖 host 信任 | 硬件保证,host 不可见 |
对 LLM 推理这类"内存里装着金子"的场景,个位数百分比的带宽损耗换来"即便云厂商也无法读取权重与 prompt",通常是划算的。
九、生产落地 Checklist
- 硬件准入:确认实例规格支持 SEV-SNP/TDX,内核加载对应驱动(
sev-guest/tdx-guest)。 - 嵌套与版本:机密 VM 通常不支持再嵌套虚拟化;Kata guest kernel 需匹配 host TEE 模块版本。
- 证明服务高可用:attestation 服务是密钥释放的单点,需独立部署并做冗余。
- PCR 基线固化:将验证明文 PCR 写入 CI,镜像变更必须重新生成 golden PCR。
- 密钥生命周期:sealed key 与实例强绑定,销毁实例即销毁解封能力,需配套 KMS 备份策略。
十、总结
机密计算把"信任"从人(云厂商 SLA)迁移到了硬件(CPU 加密引擎 + 厂商 CA)。容器与编排层的可信化——Kata 机密运行时 + RuntimeClass + 远程证明门控——是让这项能力真正落地到 AI 推理生产系统的关键一环:模型权重与用户 prompt 在机密内存之外始终以密文存在,operator 即便拥有 root 也无可奈何。
对金融、医疗、跨境外包推理等强合规场景,机密容器已是不可或缺的基础设施。下一步值得探索的是把证明门控进一步下沉到服务网格(mTLS + 证明双向校验),让整个推理链路在"零信任"的前提下仍可观测、可调度。

发表评论 取消回复