AI云原生实战15-容器镜像被篡改怎么办?镜像签名+RuntimeClass+PodSecurity构建AI容器的四层纵深防御

📅 2026/7/31 19:17:22 👁️ 阅读次数 📝 编程学习
AI云原生实战15-容器镜像被篡改怎么办?镜像签名+RuntimeClass+PodSecurity构建AI容器的四层纵深防御

AI容器安全不是配个NetworkPolicy就完事了——镜像被投毒、容器被逃逸、配置有缺陷,任何一个短板都能让整个集群沦陷。

目录

一、你的AI容器真的安全吗?

二、第一道防线:镜像签名与验证——让"假镜像"无处遁形

2.1 为什么需要镜像签名?

2.2 主流工具对比:Cosign vs Notation

2.3 实战:Cosign Keyless 签名 + 验签

2.4 实战:Notation + 企业CA签名

2.5 准入控制:在K8s层面强制验签

三、第二道防线:镜像扫描——在"出事之前"把漏洞揪出来

3.1 镜像扫描解决什么问题

3.2 主流工具:Trivy vs Grype

3.3 实战:Trivy全量扫描 + CI集成

3.4 准入控制:Trivy Operator 在K8s层自动扫描

四、第三道防线:RuntimeClass安全沙箱——用硬件隔离兜底

4.1 为什么还需要沙箱?

4.2 RuntimeClass + 安全沙箱方案

4.3 实战:配置Kata Containers RuntimeClass

4.4 gVisor配置参考

五、第四道防线:PodSecurity标准——从"凭感觉"到"按标准"

5.1 PodSecurity的进化史

5.2 实战:Enforce + Warn + Audit 三模式部署

5.3 AI容器的Restricted配置示例

六、分层防御总览:四道防线如何协同工作

每一层的职责

攻击路径与防御矩阵

七、生产级完整YAML清单

八、落地避坑指南

8.1 不要一上来就全量推行

8.2 关于性能损耗

8.3 别忘了运行时监控

九、总结


一、你的AI容器真的安全吗?

先问一个扎心的问题:你公司用的AI推理镜像,是谁打的?从哪个仓库拉的?打完有没有被人改过?

如果你回答不上来,那恭喜你——你已经踩进了容器安全最致命的坑。

2025年的AI工程化浪潮里,几乎每家公司都在抢着上Kubernetes跑AI负载。模型推理用Pod拉起,训练用Job分布,数据预处理用CronJob定时执行——看起来很美好对吧?

但现实是,AI容器比普通业务容器更容易成为攻击目标

⚠️镜像投毒:AI镜像动辄几个GB到十几GB,基础镜像里塞个挖矿脚本、改个Python依赖,很难被发现。2024年就爆出过PyPI上的torch包被投毒事件,那些镜像如果被CI/CD流水线拉下来直接推生产……

⚠️逃逸攻击:AI推理需要GPU直通、需要挂载大容量存储,权限难免放宽。一旦有攻击者通过模型文件注入触发容器逃逸,宿主机的GPU显存数据、模型权重文件全暴露。

⚠️配置缺陷:大部分AI团队focus在模型精度上,写出来的K8s YAML就俩字——奔放。privileged: true、hostNetwork、hostPath——比你家大门还敞亮。

我见过一个真实的案例:某AI公司的推理Pod直接用root跑,挂载了宿主机的docker.sock,结果一个模型输入层面的RCE就让攻击者拿到整个集群的控制权——代价是全公司的模型参数被勒索,损失七位数

所以容器安全,从来不是"配一个NetworkPolicy就完事"那么简单。

今天这篇,咱们就聊聊AI容器安全的四道纵深防线——从镜像供应链到运行时隔离,从Pod准入到策略管控,每一道都是一层过滤网,层层递进、环环相扣。


二、第一道防线:镜像签名与验证——让"假镜像"无处遁形

2.1 为什么需要镜像签名?

很多人觉得:“镜像我都是从官方仓库拉的,能有什么问题?”

问得好,那我再问一句:你能保证从拉取到部署的整个链条上,没人动过这个镜像吗?

Docker Hub上的镜像是没有天然防篡改能力的。你拉下来的镜像是"一个tar包推上去的",中间经过的镜像仓库是否可信?镜像Tag是否被覆盖过?CI/CD流水线的构建机如果被攻破,推送的镜像是否被篡改?

镜像签名的本质:用私钥对镜像的digest签名,任何人只要有公钥就能验证镜像的完整性和来源可靠性。谁签的名、镜像内容变没变、什么时间签的——三个问题一次性回答。

2.2 主流工具对比:Cosign vs Notation

目前镜像签名领域,两个主流工具二选一:

维度CosignNotation
缔造者Sigstore 社区CNCF Notary 项目
签名载体OCI 镜像仓库的 Tag 或 ReferrersOCI Artifact / Referrers
Key管理支持 Keyless(OIDC 免密钥)+ 传统 Key传统 Key + 证书链模式
认证集成原生支持 GitHub/GitLab OIDC支持 x509 证书
策略引擎Cosign Policy 内置Ratify 独立组件
企业友好度⭐⭐⭐ Keyless 模式降低门槛⭐⭐⭐⭐ 证书链适合企业CA体系
社区活跃度非常高,Sigstore 社区主力较高,CNCF 赛道

💡选型建议:如果你在GitHub/GitLab上的CI/CD用的是OIDC认证,强烈建议走Cosign的Keyless模式。这东西是真的省心——连密钥管理都省了,OIDC令牌本身就是你的身份凭证。

如果贵司有严格的PKI体系(比如基于企业CA签发的证书),Notation会更适合。

2.3 实战:Cosign Keyless 签名 + 验签

先说Keyless模式——这是Cosign最大的亮点:

# 安装 Cosign # Mac brew install cosign # Linux # 这里走 VERSION 变量指定版本 VERSION=$(curl -s https://api.github.com/repos/sigstore/cosign/releases/latest | jq -r .tag_name | sed 's/^v//') curl -LO "https://github.com/sigstore/cosign/releases/download/v${VERSION}/cosign_${VERSION}_amd64.deb" sudo dpkg -i cosign_${VERSION}_amd64.deb # 构建并推送镜像 docker build -t registry.example.com/ai-inference:v1 . docker push registry.example.com/ai-inference:v1 # 签名(Keyless模式,不用管理任何密钥!) cosign sign registry.example.com/ai-inference:v1 # 触发浏览器OIDC认证,或通过环境变量指配CI的OIDC token # COSIGN_EXPERIMENTAL=1 cosign sign ... # 完成后签名信息作为OCI Tag或Referrers存储在镜像仓库中

验证签名:

# 验证签名 cosign verify \ --certificate-identity-regexp 'https://github.com/myorg/.*' \ --certificate-oidc-issuer-regexp 'https://token.actions.githubusercontent.com' \ registry.example.com/ai-inference:v1

⚠️关键配置点--certificate-identity-regexp--certificate-oidc-issuer-regexp定义了"谁的签名我认"。这里必须精确匹配你组织的CI系统,否则任何人都能用Cosign签你的镜像——那就失去意义了。

2.4 实战:Notation + 企业CA签名

# 安装 Notation # Mac brew install notation # Linux curl -LO https://github.com/notaryproject/notation/releases/latest/download/notation_1.1.0_linux_amd64.tar.gz tar -xzf notation_*.tar.gz sudo mv notation /usr/local/bin/ # 导入企业CA签发的证书 notation cert add --type ca --file ca.pem --name my-enterprise-ca notation cert add --type signing --file signer-cert.pem --key signer-key.pem \ --name ai-team-key # 签名 notation sign registry.example.com/ai-inference:v1 \ --signature-format cose \ --key ai-team-key # 本地验证 notation verify registry.example.com/ai-inference:v1

2.5 准入控制:在K8s层面强制验签

光签名没有任何意义,只有在部署时强制验证才有用。

Ratify(Notation的策略执行引擎)或Kyverno做准入控制:

💡核心逻辑:在K8s的Admission Webhook里拦截所有Pod创建请求,检查镜像是否有有效签名。没有签名 → 直接拒绝创建。

# Kyverno 策略:强制所有Pod必须包含已验证签名的镜像 apiVersion: kyverno.io/v1 kind: ClusterPolicy metadata: name: require-image-signature spec: validationFailureAction: Enforce background: false rules: - name: check-cosign-signature match: any: - resources: kinds: - Pod verifyImages: - imageReferences: - "registry.example.com/*" mutateDigest: true verifyDigest: true required: true attestors: - count: 1 entries: - keys: publicKeys: |- -----BEGIN PUBLIC KEY----- MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAE... -----END PUBLIC KEY-----

💡为什么不推荐用 Admission Controller 手动写Webhook?因为Kyverno/ Ratify/ OPA Gatekeeper 已经封装了镜像签名验证的完整逻辑,没必要再重复造轮子。而且它们支持热更新策略规则,不需要重启APIServer。


三、第二道防线:镜像扫描——在"出事之前"把漏洞揪出来

3.1 镜像扫描解决什么问题

镜像签名解决的是"这个镜像有没有被篡改",而镜像扫描解决的是"这个镜像本身有没有漏洞"。

⚠️这是两道完全不同的防线。签名保证完整性,扫描保证安全性。少了任何一个,你的供应链安全都有窟窿。

3.2 主流工具:Trivy vs Grype

维度TrivyGrype
开发商Aqua SecurityAnchore
漏洞库自家 + NVD + RedHat + Alpine 等14个源自家 + NVD + RedHat + Ubuntu 等
扫描速度⭐⭐⭐⭐ 非常快⭐⭐⭐ 较快
SBOM支持CycloneDX + SPDXCycloneDX + SPDX
策略引擎内置 Cosign + 配置策略需要 + Syft 配合
容器镜像层缓存❌(当前不支持)
K8s 集成Trivy Operator(CRD + 准入)社区方案

💡我的推荐:日常开发用Trivy就够了。理由很直接——Trivy Operator可以做成CRD扫描K8s集群中所有Pod的镜像,跟K8s生态绑定最紧密,不用额外运维一套扫描系统。

3.3 实战:Trivy全量扫描 + CI集成

# 安装 Trivy # Mac brew install trivy # Linux curl -sfL https://raw.githubusercontent.com/aquasecurity/trivy/main/contrib/install.sh | sh # 扫描单个镜像 trivy image registry.example.com/ai-inference:v1 # 扫描并输出JSON供后续处理 trivy image --format json --output scan-result.json \ registry.example.com/ai-inference:v1 # 只扫描 HIGH / CRITICAL 级别(建议CI用这种模式) trivy image --severity HIGH,CRITICAL \ --exit-code 1 \ --ignore-unfixed \ registry.example.com/ai-inference:v1

⚠️必配参数说明

  • --exit-code 1:发现漏洞时让CI失败,阻止有问题的镜像进入仓库
  • --ignore-unfixed:忽略没有修复方案的漏洞(很多OS包漏洞确实没有补丁,扫出来也没用,白白阻塞流水线)
  • --severity HIGH,CRITICAL:只关心中高风险,LOW/MEDIUM级别的漏洞阈值下可以放过

3.4 准入控制:Trivy Operator 在K8s层自动扫描

Trivy Operator是精品——它作为Operator运行在集群内,自动发现并扫描所有Pod的镜像,同时提供Admission Controller+准入Webhook,在Pod创建前自动扫描

# 安装 Trivy Operator helm repo add aqua https://aquasecurity.github.io/helm-charts helm repo update helm install trivy-operator aqua/trivy-operator \ --namespace trivy-system \ --create-namespace \ --set="trivy.ignoreUnfixed=true" \ --set="trivy.severity=CRITICAL,HIGH"

然后Trivy Operator会自动创建VulnerabilityReportCRD,每个Pod都会有一个对应的扫描报告:

# 查看所有漏洞报告 kubectl get vulnerabilityreports -A # 查看某个Pod的详细漏洞 kubectl get vulnerabilityreport pod-ai-inference-xxxxx -o yaml

如果再配合准入Webhook,所有新创建的Pod如果不满足漏洞阈值,直接拒绝:

# 准入策略:拒绝包含CRITICAL漏洞的镜像 apiVersion: aquasecurity.github.io/v1alpha1 kind: ClusterConfigAuditReport ... # 这里实际上是通过Trivy Operator的ConfigMap配置策略 # 在 trivy-operator 命名空间修改配置即可 kubectl edit configmap trivy-operator -n trivy-system

四、第三道防线:RuntimeClass安全沙箱——用硬件隔离兜底

4.1 为什么还需要沙箱?

前两道防线解决的是供应链安全——镜像是否可信、是否有漏洞。但它们解决不了运行时逃逸的问题。

只要你的容器和宿主机共享Linux内核(这是Docker和runc的默认模式),就有逃逸的可能——CVE-2022-0185(Linux内核越界漏洞)、CVE-2024-21626(runc文件描述符泄露)……每年的逃逸漏洞轮着来。

⚠️AI容器的特殊性:AI推理Pod需要挂载GPU、请求巨量显存、可能挂载额外的模型存储。这些"特权"操作天然增加了逃逸攻击面。

4.2 RuntimeClass + 安全沙箱方案

K8s的RuntimeClass机制就是为解决这个问题的——让不同的Pod跑在不同的容器运行时上

核心思路:高风险的AI推理Pod跑在轻量级VM沙箱里,跟宿主机完全隔离。

维度Kata ContainersgVisor
隔离级别轻量级VM(硬件虚拟化)用户态内核(应用层拦截)
性能损耗~5-10%(接近原生)~15-40%(系统调用越多越慢)
GPU支持✅ 完整支持(GPU passthrough)❌ 不支持GPU直通
兼容性⭐⭐⭐⭐⭐ 所有系统调用都支持⭐⭐⭐ 部分系统调用不兼容
启动速度较慢(需启动VM)很快(进程级)
安全等级更高(硬件隔离)较高(软件隔离)
适用场景AI推理、GPU负载、高风险Pod通用Web服务、低风险Pod

💡AI场景的明确建议

  • AI推理Pod用Kata Containers——GPU passthrough是刚需,没有替代方案。损失5-10%的性能,换的是完整的硬件隔离。
  • Web服务 / 数据处理Pod用gVisor——不需要GPU,系统调用模式简单,gVisor足够。
  • 管理面Pod(kube-system下的组件)用默认runc——改运行时可能导致兼容性问题。

4.3 实战:配置Kata Containers RuntimeClass

# 1. 安装Kata Containers(选择一个节点做测试) # Ubuntu sudo apt-get update && sudo apt-get install -y kata-containers # 2. 配置 containerd 支持 Kata # 编辑 /etc/containerd/config.toml 添加: cat >> /etc/containerd/config.toml << EOF [plugins."io.containerd.grpc.v1.cri".containerd.runtimes.kata] runtime_type = "io.containerd.kata.v2" privileged_without_host_devices = true EOF # 重启 containerd sudo systemctl restart containerd # 3. 创建 RuntimeClass cat <<'EOF' | kubectl apply -f - apiVersion: node.k8s.io/v1 kind: RuntimeClass metadata: name: kata-qemu handler: kata scheduling: nodeSelector: katacontainers.io/kata-runtime: "true" EOF # 4. 标记kata节点 kubectl label node <ai-node-name> katacontainers.io/kata-runtime=true # 5. 在AI推理Pod中指定 runtimeClassName apiVersion: v1 kind: Pod metadata: name: ai-inference-safe spec: runtimeClassName: kata-qemu containers: - name: inference image: registry.example.com/ai-inference:v1 resources: requests: nvidia.com/gpu: 1 limits: nvidia.com/gpu: 1 volumeMounts: - name: model-storage mountPath: /models volumes: - name: model-storage persistentVolumeClaim: claimName: model-pvc

⚠️注意事项

  • 启用Kata的节点建议打上taint,只调度安全Pod,避免非安全Pod也跑到Kata节点上(浪费资源)
  • GPU passthrough需要节点支持SR-IOV或直通,不是所有硬件都支持
  • Kata对存储有额外的Overhead,建议用local SSD而非网络存储

4.4 gVisor配置参考

# 安装 gVisor runsc curl -LO https://storage.googleapis.com/gvisor/releases/release/latest/x86_64/runsc sudo mv runsc /usr/local/bin/ sudo chmod +x /usr/local/bin/runsc # 配置 containerd cat >> /etc/containerd/config.toml << EOF [plugins."io.containerd.grpc.v1.cri".containerd.runtimes.runsc] runtime_type = "io.containerd.runsc.v1" EOF sudo systemctl restart containerd # 创建 RuntimeClass cat <<'EOF' | kubectl apply -f - apiVersion: node.k8s.io/v1 kind: RuntimeClass metadata: name: gvisor handler: runsc EOF

五、第四道防线:PodSecurity标准——从"凭感觉"到"按标准"

5.1 PodSecurity的进化史

PodSecurity Policies(PSP)那会儿是真的反人类——一个PSP写200行YAML是常事,而且逻辑复杂到连K8s大佬都配不对。

好在K8s v1.21开始引入PodSecurity Admission,v1.25正式GA,把PSP替代了

PodSecurity标准只有三个等级,但覆盖了95%以上的容器安全配置:

等级说明典型限制
Privileged不受限——啥都能干没有额外限制
Baseline最小受限——防已知特权升级禁止privileged、禁止hostNetwork、禁止hostPID/IPC、限制Seccomp等
Restricted强受限——遵循Pod安全最佳实践Baseline基础上+强制non-root、限制capabilities、限制SELinux等

💡实际建议你的集群中90%的Pod都应该用Restricted,只有那些实在不兼容的特殊Pod(比如网络插件、监控agent)才放宽到Baseline或Privileged。

5.2 实战:Enforce + Warn + Audit 三模式部署

PodSecurity采用三种模式而非一刀切,让你可以渐进式落地:

# 命名空间级别配置 apiVersion: v1 kind: Namespace metadata: name: ai-inference-prod labels: # Enforce:直接拒绝不符合Restricted的Pod pod-security.kubernetes.io/enforce: restricted pod-security.kubernetes.io/enforce-version: latest # Warn:不符合的Pod创建时给警告,但不会拒绝 pod-security.kubernetes.io/warn: baseline pod-security.kubernetes.io/warn-version: latest # Audit:不符合的在审计日志记录,但没有任何用户可见影响 pod-security.kubernetes.io/audit: baseline pod-security.kubernetes.io/audit-version: latest --- # 集群级默认值 apiVersion: apiserver.config.k8s.io/v1 kind: AdmissionConfiguration plugins: - name: PodSecurity configuration: apiVersion: pod-security.admission.config.k8s.io/v1 kind: PodSecurityConfiguration defaults: enforce: "restricted" enforce-version: "latest" audit: "baseline" audit-version: "latest" warn: "baseline" warn-version: "latest" exemptions: # 豁免kube-system等系统命名空间 namespaces: ["kube-system", "gatekeeper-system", "trivy-system"] # 豁免特定运行时类 runtimeClasses: ["kata-qemu", "gvisor"]

5.3 AI容器的Restricted配置示例

apiVersion: apps/v1 kind: Deployment metadata: name: ai-inference-secure namespace: ai-inference-prod spec: replicas: 3 selector: matchLabels: app: ai-inference template: metadata: labels: app: ai-inference spec: # 使用Kata运行时——第三道防线 runtimeClassName: kata-qemu securityContext: # 关键:Pod级别的安全上下文 runAsNonRoot: true runAsUser: 1000 runAsGroup: 3000 fsGroup: 2000 seccompProfile: type: RuntimeDefault containers: - name: inference image: registry.example.com/ai-inference:v1 securityContext: allowPrivilegeEscalation: false capabilities: drop: - ALL # AI推理可能需要CAP_SYS_PTRACE,按需添加 # add: ["SYS_PTRACE"] readOnlyRootFilesystem: true runAsNonRoot: true runAsUser: 1000 seccompProfile: type: RuntimeDefault resources: requests: memory: "8Gi" cpu: "4" nvidia.com/gpu: 1 limits: memory: "16Gi" cpu: "8" nvidia.com/gpu: 1 volumeMounts: - name: tmp mountPath: /tmp - name: models mountPath: /models readOnly: true volumes: - name: tmp emptyDir: {} - name: models persistentVolumeClaim: claimName: ai-models-pvc readOnly: true

⚠️常见踩坑点

  • readOnlyRootFilesystem: true会导致应用在根目录写临时文件失败。必须声明emptyDir来挂载/tmp和/var/tmp等写目录
  • runAsNonRoot: true+runAsUser: 1000必须确保镜像内的进程是用1000uid跑的。如果Dockerfile里用root启动,这里直接创建失败。
  • AI推理框架(如Triton Server)有自己的进程管理逻辑,要注意这些框架的安全配置兼容性。

六、分层防御总览:四道防线如何协同工作

下面的图展示了AI容器从提交到运行的完整防御链路:

flowchart TD subgraph "开发者侧" A[代码提交] --> B[CI流水线] B --> C[Trivy镜像扫描] C --> D{漏洞达标?} D -->|否| E[阻断-返回修复] D -->|是| F[Cosign/Notation签名] F --> G[推送镜像到仓库] end subgraph "K8s集群侧" H[创建Pod请求] --> I[Admission Webhook] I --> J[Ratify/Kyverno验签] J --> K{签名有效?} K -->|否| L[拒绝Pod创建] K -->|是| M[PodSecurity校验] M --> N{符合Restricted?} N -->|否| O[Warn/Reject] N -->|是| P[Pod调度] P --> Q{Schedule调度策略} Q -->|AI推理Pod| R[RuntimeClass:kata-qemu] Q -->|Web服务Pod| S[RuntimeClass:gvisor] Q -->|系统组件| T[默认runc] end subgraph "运行时" R --> U[Kata轻量级VM隔离] S --> V[gVisor用户态内核] T --> W[标准容器] U --> X{运行时监控} V --> X W --> X X --> Y[Falco/告警] end

每一层的职责

防线防御对象生命周期阶段核心工具绕过成本
①镜像签名与验证镜像篡改、供应链攻击构建→部署Cosign/Notation + Ratify/Kyverno攻破私钥/CA或绕过Admission
②镜像扫描已知漏洞、恶意依赖构建时 + 运行时持续Trivy/Grype + Trivy Operator漏洞不上报或掩盖特征
③RuntimeClass沙箱容器逃逸、内核漏洞运行时Kata Containers / gVisor逃出VM或突破Seccomp
④PodSecurity标准配置缺陷、过度特权部署准入PodSecurity Admission找到豁免条件或利用不兼容点

攻击路径与防御矩阵

下面的Mermaid图直观展示了四类典型攻击分别会被哪道防线拦截——红色划线表示被拦截,绿色勾表示可绕过(需要更上游防线兜底):

flowchart LR subgraph 攻击向量 A1[恶意镜像投毒] A2[供应链依赖篡改] A3[内核漏洞逃逸] A4[容器过度特权] end subgraph 防线拦截 L1[①镜像签名验证] L2[②漏洞扫描] L3[③RuntimeClass沙箱] L4[④PodSecurity标准] end subgraph 拦截结果 R1[❌ 拦截 - 签名不匹配] R2[❌ 拦截 - CVE超阈值] R3[❌ 拦截 - VM隔离] R4[❌ 拦截 - Restricted策略] R5[⚠️ 需要⑤运行时监控兜底] end A1 -->|镜像digest不一致| L1 L1 -->|验签失败| R1 A2 -->|依赖含已知漏洞| L2 L2 -->|CRITICAL漏洞| R2 A3 -->|利用内核syscall| L3 L3 -->|Kata硬件虚拟机| R3 A3 -.->|突破沙箱| R5 A4 -->|特权操作被限制| L4 L4 -->|非root+只读FS| R4
攻击类型绕过第一道绕过第二道绕过第三道绕过第四道
恶意镜像投毒❌ 签名验证❌ 漏洞扫描✅ 无法阻止✅ 无法阻止
供应链依赖篡改❌ 签名验证❌ 漏洞扫描✅ 无法阻止✅ 无法阻止
内核漏洞逃逸✅ 签名有效即可✅ 能过扫描❌ Kata VM隔离✅ 非内核级问题
容器过度特权✅ 签名有效即可✅ 能过扫描❌ 缩小攻击面❌ Restricted策略
宿主文件访问✅ 签名有效即可✅ 能过扫描❌ Kata文件系统隔离❌ 只读根文件系统
网络横向移动✅ 签名有效即可✅ 能过扫描✅ 沙箱内仍可网络通信✅ 无直接防御

七、生产级完整YAML清单

下面是一份可以直接用于生产环境的完整配置组合:

# 文件1:RuntimeClass 定义 --- apiVersion: node.k8s.io/v1 kind: RuntimeClass metadata: name: kata-qemu handler: kata scheduling: nodeSelector: katacontainers.io/kata-runtime: "true" tolerations: - effect: NoSchedule key: kata operator: Exists --- apiVersion: node.k8s.io/v1 kind: RuntimeClass metadata: name: gvisor handler: runsc --- # 文件2:命名空间级PodSecurity配置 apiVersion: v1 kind: Namespace metadata: name: ai-inference-prod labels: pod-security.kubernetes.io/enforce: restricted pod-security.kubernetes.io/enforce-version: latest pod-security.kubernetes.io/warn: baseline pod-security.kubernetes.io/warn-version: latest --- apiVersion: v1 kind: Namespace metadata: name: ai-training labels: # Training可能用GPU集合通信,放宽到baseline pod-security.kubernetes.io/enforce: baseline pod-security.kubernetes.io/enforce-version: latest --- # 文件3:Kyverno镜像签名验证策略 apiVersion: kyverno.io/v1 kind: ClusterPolicy metadata: name: require-image-signature spec: validationFailureAction: Enforce background: false rules: - name: check-signature match: any: - resources: kinds: - Pod verifyImages: - imageReferences: - "registry.example.com/*" mutateDigest: true verifyDigest: true required: true attestors: - count: 1 entries: - keys: publicKeys: |- -----BEGIN PUBLIC KEY----- MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEX... -----END PUBLIC KEY----- --- # 文件4:生产级AI推理Deployment(完整安全配置) apiVersion: apps/v1 kind: Deployment metadata: name: ai-inference-secure namespace: ai-inference-prod labels: app.kubernetes.io/name: ai-inference app.kubernetes.io/component: inference-server security-tier: restricted spec: replicas: 3 selector: matchLabels: app: ai-inference template: metadata: labels: app: ai-inference annotations: # 显式声明容器运行时 container.apparmor.security.beta.kubernetes.io/inference: runtime/default seccomp.security.alpha.kubernetes.io/pod: runtime/default spec: runtimeClassName: kata-qemu serviceAccountName: inference-sa securityContext: runAsNonRoot: true runAsUser: 1000 runAsGroup: 3000 fsGroup: 2000 seccompProfile: type: RuntimeDefault containers: - name: inference image: registry.example.com/ai-inference:v1 imagePullPolicy: Always ports: - containerPort: 8000 protocol: TCP env: - name: MODEL_PATH value: /models/current - name: LOG_LEVEL value: info securityContext: allowPrivilegeEscalation: false capabilities: drop: - ALL readOnlyRootFilesystem: true runAsNonRoot: true runAsUser: 1000 seccompProfile: type: RuntimeDefault resources: requests: cpu: "4" memory: "8Gi" nvidia.com/gpu: 1 limits: cpu: "8" memory: "16Gi" nvidia.com/gpu: 1 volumeMounts: - name: tmp mountPath: /tmp - name: model-storage mountPath: /models readOnly: true livenessProbe: httpGet: path: /health port: 8000 initialDelaySeconds: 30 periodSeconds: 10 readinessProbe: httpGet: path: /ready port: 8000 initialDelaySeconds: 5 periodSeconds: 5 volumes: - name: tmp emptyDir: medium: Memory sizeLimit: 1Gi - name: model-storage persistentVolumeClaim: claimName: ai-models-pvc readOnly: true --- # 文件5:最小RBAC apiVersion: v1 kind: ServiceAccount metadata: name: inference-sa namespace: ai-inference-prod automountServiceAccountToken: false --- # 文件6:NetworkPolicy apiVersion: networking.k8s.io/v1 kind: NetworkPolicy metadata: name: inference-network-policy namespace: ai-inference-prod spec: podSelector: matchLabels: app: ai-inference policyTypes: - Ingress - Egress ingress: - from: - namespaceSelector: matchLabels: kubernetes.io/metadata.name: ai-gateway ports: - port: 8000 protocol: TCP egress: - to: - namespaceSelector: matchLabels: kubernetes.io/metadata.name: kube-system ports: - port: 53 protocol: UDP - port: 53 protocol: TCP - to: - podSelector: matchLabels: app: model-registry ports: - port: 50051 protocol: TCP

八、落地避坑指南

8.1 不要一上来就全量推行

我见过太多团队:“我们在所有命名空间强制enforce: restricted!” 然后……所有人都被阻塞了,然后……策略被回滚了。

💡建议的落地节奏

  1. 第1周:所有命名空间用audit模式,观察哪些Pod不满足
  2. 第2周:对不满足的Pod逐个评估,要么改代码适应Restricted,要么确认豁免
  3. 第3周:核心业务命名空间切到enforce: restricted
  4. 第4周:全量切enforce: restricted,保留warn: baseline作为新风向标

8.2 关于性能损耗

⚠️不要无脑对所有Pod启用Kata Containers

Kata的VM启动开销在5-20秒之间,对于水平扩展频繁匹配Pod的应用,这个延迟是不可接受的。而且不是所有CPU都支持Kata需要的虚拟化扩展(Intel VT-x/AMD-V)。

合理策略

  • 高风险AI推理Pod → Kata(安全 > 性能)
  • 批处理/离线任务 → Kata(可接受额外启动时间)
  • 在线Web服务 → gVisor(启动快,隔离够用)
  • kube-system组件 → runc(不改运行时)

8.3 别忘了运行时监控

四道防线都配好了,但你以为就完事了?

💡运行时监控是第五道防线(可选增强)

# Falco 运行时安全(作为补充监控) helm repo add falcosecurity https://falcosecurity.github.io/charts helm install falco falcosecurity/falco \ --namespace falco \ --create-namespace \ --set falco.driver.kind=ebpf

Falco可以检测:容器内执行shell、读取敏感文件、创建网络连接等等——即使攻击者突破了Kata沙箱,Falco还能在宿主机层给你报警


九、总结

AI容器安全不是选一个工具就能解决的。四道防线,缺一不可

  1. 镜像签名(Cosign/Notation)→ 解决"镜像被篡改"的问题
  2. 镜像扫描(Trivy/Grype)→ 解决"镜像有漏洞"的问题
  3. RuntimeClass沙箱(Kata/gVisor)→ 解决"逃逸攻击"的问题
  4. PodSecurity标准(Restricted/Baseline)→ 解决"配置缺陷"的问题

配置从来不是为了阻止"绝对不会出事"——而是为了提高攻击成本,让攻击者觉得"不值得攻破你"

今天花半天配好这四道防线,明天省下的可能是一个七位数的安全事件。


📌 推荐阅读

  • Cosign 官方文档
  • Trivy Operator 项目
  • Kata Containers 架构说明
  • K8s PodSecurity 标准

如果你也在做AI容器安全,欢迎留言交流👇 你觉得哪道防线最难落地?


标签容器安全镜像签名RuntimeClassPodSecurityKata ContainersCosignTrivy