容器不是隔离,是限制
一句话总结
容器共享主机内核。因此,系统强化与其说是“加强隔离”,不如说是“减少容器可以向共享内核请求的操作”。
为什么需要它
虚拟机有独立内核。即使在 guest 中利用内核漏洞,也很难跨越 hypervisor 边界。容器则不同:节点上的所有 Pod 使用同一内核,而内核提供数百个系统调用。容器逃逸 CVE 大多攻击这个表面的某个位置。
因此防御逻辑也会改变。与其只阻止入侵,不如预先减少已入侵进程可向内核请求的操作。Linux 为此提供三层机制,Kubernetes 将三者都暴露为 Pod spec 字段。
| 机制 | 限制目标 | Pod spec 字段 |
|---|---|---|
| seccomp | 可调用的系统调用列表 | securityContext.seccompProfile |
| AppArmor / SELinux | 可访问的文件、网络与功能(MAC) | securityContext.appArmorProfile |
| capabilities | root 权限的细分片段 | securityContext.capabilities |
工作原理
seccomp 在实践中主要使用 RuntimeDefault 与 Localhost 两种类型。RuntimeDefault 使用容器运行时自带的默认阻止列表;Localhost 则指定节点 <seccomp-root>/profiles 下的 JSON 配置,并在 localhostProfile 中写入路径。节点上没有配置文件时,Pod 无法启动。写进 spec 与文件确实存在于节点,是两回事。
AppArmor 在 Kubernetes 1.30 中从 annotation 升级为正式字段。旧形式是 container.apparmor.security.beta.kubernetes.io/<컨테이너이름> annotation;新形式是 securityContext.appArmorProfile.type 与 localhostProfile。考试可能根据集群版本考查任一形式,因此两种都要了解。配置也必须预先加载到节点,并使用 aa-status 确认。
capabilities 最容易理解,效果也最大。容器 root 并非真正的 root,而是持有一组 capability 的 UID 0。使用 drop: ["ALL"] 全部丢弃后,只 add 真正需要的项目。例如,需要监听 80 端口的 Web 服务器只需 NET_BIND_SERVICE。privileged: true 会使这些控制全部失效:授予所有 capability、开放全部设备访问,并禁用 AppArmor、SELinux、seccomp 配置。因此,查找 privileged 容器是 CKS 的常见题型。
共享主机命名空间也属于同一层。hostPID: true 会让容器看到节点的全部进程,并能通过 /proc/<PID>/environ 读取其他进程的环境变量。如果旁边有把秘密放入环境变量的工作负载,防线就会失守。hostNetwork 会使网络策略实际上失去意义,hostIPC 则消除共享内存边界。
最后是 readOnlyRootFilesystem: true。它会消除攻击者投放二进制文件或替换现有文件的路径。需要写入的位置应单独挂载 emptyDir。
实际现场中的情况
查看容器镜像扫描结果,就能理解这一层的必要性。一个 node:22 镜像安装了 432 个软件包,漏洞报告有 1,247 项(CRITICAL 9、HIGH 137)。但用 ldd 统计应用实际链接的共享库,只有 8 个。其余都是基础镜像带来的内容,大多是 shell、软件包管理器和工具,对攻击者而言就是工具箱。最好的办法是从镜像删除;无法删除时,次优方案是用 capability 和 seccomp 限制这些工具能向内核请求的操作。
CRI 层也重复同一逻辑。containerd 会把 Pod spec 的 SecurityContext 翻译为 OCI spec。readOnlyRootFilesystem: true 变成 root.readonly = true,capabilities 变成 process.capabilities,seccompProfile 下沉为 linux.seccomp。而 privileged: true 会在翻译过程中展开为授予全部 capability、允许全部设备、禁用 AppArmor、SELinux、seccomp。一个字段便会同时摧毁三层控制。是否真正应用,应在节点上通过 crictl inspect 读取最终 spec 确认。
下一项实验要做什么
本环境没有真实容器运行时,因此无法确认配置是否真的被强制执行。实验将练习 CKS 实际评分的内容,即准确编写 Pod spec 字段:两种 seccomp 类型、AppArmor 配置、capability drop/add、禁止主机命名空间,以及亲手编写查找 privileged 容器的检测脚本。