容器共享宿主机内核,默认隔离并不等同于虚拟机边界。Kubernetes 工作负载加固的目标是:即使应用被入侵,也尽量限制攻击者能够调用的系统能力、访问的文件和影响的节点范围。
## 1. 从 SecurityContext 开始
Pod 和容器级 SecurityContext 可以控制运行用户、Linux capabilities、只读文件系统、seccomp 等属性。普通业务的建议基线如下:
```yaml
apiVersion: v1
kind: Pod
metadata:
name: secure-app
spec:
securityContext:
runAsNonRoot: true
runAsUser: 10001
runAsGroup: 10001
fsGroup: 10001
seccompProfile:
type: RuntimeDefault
containers:
- name: app
image: example/app@sha256:REPLACE_WITH_DIGEST
securityContext:
allowPrivilegeEscalation: false
readOnlyRootFilesystem: true
capabilities:
drop: ["ALL"]
volumeMounts:
- name: tmp
mountPath: /tmp
volumes:
- name: tmp
emptyDir: {}
```
只读根文件系统启用后,应用确实需要写入的目录应单独挂载 emptyDir 或持久卷。不要为了省事重新打开整个根目录写权限。
## 2. 删除 capabilities
Linux capabilities 把传统 root 权限拆成更小的能力集合。最稳妥的方式是先 drop ALL,再按实际需求添加。例如绑定 1024 以下端口可能需要 NET_BIND_SERVICE,但很多应用可以直接改用高端口,从而不再添加能力。
特别警惕 SYS_ADMIN、SYS_PTRACE、NET_ADMIN 等高风险能力。能力越多,容器逃逸或横向移动后的破坏面越大。
## 3. seccomp、AppArmor 与 SELinux
- seccomp 限制系统调用。RuntimeDefault 使用容器运行时提供的默认配置,通常比 Unconfined 更安全。
- AppArmor 通过配置文件约束进程对文件、网络和能力的访问。
- SELinux 使用标签和策略隔离资源,在启用它的发行版上应保持 enforcing,并正确配置卷标签。
三者并非互斥,可以与非 root、只读文件系统和 capabilities 一起构成多层防护。上线前要在测试环境验证,因为限制过严会导致应用启动失败或功能异常。
## 4. 避免突破隔离边界的配置
以下配置应被准入策略阻止或严格审批:
- privileged: true
- hostPID、hostIPC、hostNetwork
- 挂载 /、/proc、/sys 或容器运行时 socket
- 允许提权或以 UID 0 运行
- 使用不受控制的 hostPort
特权容器会绕过许多内核安全约束。即使镜像来自内部,也不应该默认信任。
## 5. RuntimeClass 与安全沙箱
RuntimeClass 允许 Pod 选择不同的容器运行配置。对处理不可信代码、多租户或高敏感数据的负载,可以选择提供更强隔离的运行时,例如基于用户态内核或硬件虚拟化的方案。安全性提高通常会带来启动时间、内存和兼容性开销。
```yaml
apiVersion: node.k8s.io/v1
kind: RuntimeClass
metadata:
name: sandboxed
handler: sandboxed-handler
---
apiVersion: v1
kind: Pod
metadata:
name: untrusted-job
spec:
runtimeClassName: sandboxed
containers:
- name: job
image: example/job:1.0.0
```
集群管理员必须先在 CRI 中配置对应 handler。若只有部分节点支持,应在 RuntimeClass 中配置 scheduling,或用节点标签、污点和容忍度确保 Pod 被调度到正确节点。
## 6. 什么时候使用 gVisor 或 Kata 一类沙箱
适合场景:
- 在线执行用户提交的脚本或插件。
- 多租户平台中租户之间需要更强隔离。
- 安全分析、CI 任务或来源不完全可信的镜像。
- 合规要求明确规定虚拟机级隔离。
普通可信微服务未必都需要安全沙箱。更合理的分层是:默认工作负载采用严格 SecurityContext,高风险工作负载再通过 RuntimeClass 提升隔离。
## 7. 验证方法
```bash
kubectl get pod secure-app -o yaml
kubectl describe pod secure-app
kubectl get runtimeclass
kubectl get events --sort-by=.lastTimestamp
```
还应在 CI 中检查 YAML,阻止 privileged、latest 标签、缺少资源限制和未设置 seccomp 的工作负载进入生产环境。
## 参考资料
- https://kubernetes.io/docs/concepts/security/linux-kernel-security-constraints/
- https://kubernetes.io/docs/tasks/configure-pod-container/security-context/
- https://kubernetes.io/docs/concepts/containers/runtime-class/