一句话总结
镜像安全解决的是"构建时不带坏东西进来". Pod 安全解决的是"运行时容器能做什么".
即使应用被攻破, 通过 SecurityContext, Capabilities 收缩, Seccomp 和 AppArmor 限制, 攻击者能造成的伤害也被限制在最小范围内.
运行时威胁模型
假设攻击者已经获得了容器内的代码执行能力(通过应用漏洞如 RCE), 接下来想做什么?
| 攻击动作 | 需要的权限 | 防御手段 |
|---|---|---|
| 读取 /etc/shadow | root UID | runAsNonRoot |
| 安装后门程序 | 文件系统写入 | readOnlyRootFilesystem |
| 提权为 root | setuid/setgid | allowPrivilegeEscalation: false |
| 逃逸到宿主机 | SYS_ADMIN / privileged | 移除 Capabilities + privileged: false |
| 嗅探网络流量 | NET_RAW | 移除 NET_RAW Capability |
| 挂载宿主机设备 | SYS_ADMIN | 移除 SYS_ADMIN + Seccomp |
| 加载内核模块 | SYS_MODULE | 移除 SYS_MODULE + Seccomp |
SecurityContext = 监狱的安保层级.
普通犯人只有一间封闭牢房(最小权限容器), 不能出门, 不能打电话, 不能接触工具.
privileged 容器 = 给了犯人监狱的万能钥匙.
SecurityContext 详解
SecurityContext 可以在 Pod 级别和 Container 级别设置. Container 级别覆盖 Pod 级别.
最佳实践配置
|
关键字段解释
| 字段 | 效果 | 为什么重要 |
|---|---|---|
runAsNonRoot: true |
进程 UID ≠ 0 才允许启动 | 防止以 root 身份运行 |
readOnlyRootFilesystem |
容器根文件系统只读 | 攻击者无法写入后门程序 |
allowPrivilegeEscalation |
禁止 setuid/setgid 提权 | 阻止权限升级攻击 |
privileged: false |
非特权模式 | 特权容器 ≈ 宿主机 root |
capabilities.drop: ALL |
移除所有 Linux Capabilities | 最小权限原则 |
readOnlyRootFilesystem 需要配合可写 volume
很多应用需要写临时文件(日志, 缓存, PID 文件). 开启只读后要为 /tmp, /var/run 等目录挂载 emptyDir volume. 否则应用会因为写文件失败而崩溃.
Linux Capabilities
传统 Linux 权限模型是二元的: root(全能)vs 非 root(受限). Capabilities 将 root 的权限拆分为约 40 个细粒度能力:
| Capability | 权限 | 风险 |
|---|---|---|
NET_BIND_SERVICE |
绑定 < 1024 端口 | 低(通常安全) |
NET_RAW |
使用原始套接字(ping/tcpdump) | 中(可以嗅探网络) |
SYS_PTRACE |
追踪其他进程 | 高(可以注入代码到其他进程) |
SYS_ADMIN |
挂载, 修改 namespace 等 | 极高(几乎等于 root) |
SYS_MODULE |
加载内核模块 | 极高(可以修改内核行为) |
DAC_OVERRIDE |
绕过文件权限检查 | 高(可以读写任何文件) |
正确做法: Drop ALL + Add 需要的
默认容器有约 14 个 Capabilities(包括 NET_RAW 等高风险的). 正确做法是先 drop: ["ALL"] 移除全部, 再逐个添加应用真正需要的.
大多数 Go HTTP 服务不需要任何额外 Capability, 直接全部移除即可.
Seccomp
Seccomp(Secure Computing)限制容器可以使用的 Linux 系统调用(syscall). 容器只需要约 40-50 个 syscall, 但 Linux 有 300+ 个, 没用到的全部禁止.
Profile 类型
| 类型 | 含义 | 使用方式 |
|---|---|---|
RuntimeDefault |
容器运行时的默认 profile(containerd 约禁用 50 个危险 syscall) | seccompProfile: {type: RuntimeDefault} |
Localhost |
自定义 profile(JSON 文件) | seccompProfile: {type: Localhost, localhostProfile: "profiles/my.json"} |
Unconfined |
不限制(默认行为, 不推荐) | 不设置 seccompProfile 时的状态 |
|
RuntimeDefault 足够大多数场景
containerd 的默认 seccomp profile 禁用了 mount, reboot, kexec_load 等危险 syscall, 同时保留了正常应用所需的全部 syscall.
除非应用需要做非常特殊的操作(如直接操作设备文件), 否则 RuntimeDefault 就足够了.
AppArmor
AppArmor 是 Linux 的强制访问控制(MAC)框架, 限制进程可以访问的文件路径, 网络操作和 Capabilities. 与 Seccomp 互补: Seccomp 限制"能调哪些 syscall", AppArmor 限制"能访问哪些资源".
|
自定义 AppArmor profile 示例:
|
Pod Security Standards(PSS)
K8s 内置的 Pod 安全准入控制器, 按三个安全级别强制约束 Namespace 内的 Pod:
| 级别 | 约束 | 适用场景 |
|---|---|---|
| Privileged | 无限制(全部允许) | 系统组件(kube-system) |
| Baseline | 禁止已知的危险配置(hostNetwork, privileged, hostPID 等) | 通用业务工作负载 |
| Restricted | 最严格(必须非 root, drop ALL capabilities, 只读 FS 等) | 安全敏感的生产服务 |
启用方式
|
渐进式实施策略
不要一上来就在所有 Namespace 开 enforce=restricted, 会导致大量 Pod 无法创建. 推荐路径:
- 先 audit 模式收集违规数据
- 逐个修复不合规的 Deployment
- 切换到 warn 模式验证
- 最终切到 enforce
运行时威胁检测
上面的机制是预防. 但如果攻击者绕过了预防怎么办? 需要检测:
Falco: 运行时安全监控
Falco(CNCF 孵化项目)通过监听 Linux 内核事件, 实时检测容器中的可疑行为:
- 容器内启动了 shell(/bin/sh, /bin/bash)
- 读取了敏感文件(/etc/shadow, /etc/passwd)
- 进程尝试修改系统目录
- 容器建立了对外的网络连接
- 使用了不在白名单中的 syscall
|
Defense in Depth 落地
预防(SecurityContext + Capabilities + Seccomp)+ 检测(Falco)+ 响应(告警 → 自动隔离 Pod / 人工处理)= 完整的运行时安全闭环.
快速回顾
- SecurityContext: runAsNonRoot + readOnlyRootFilesystem + allowPrivilegeEscalation=false 是最基本的三件套
- Capabilities: drop ALL + 按需 add, 大多数 Go 服务不需要任何额外 Capability
- Seccomp: 至少启用 RuntimeDefault, 限制可用的系统调用
- AppArmor: 限制进程可访问的文件路径和网络操作
- Pod Security Standards: Namespace 级别的安全基线, 渐进式从 audit → warn → enforce
- Falco: 运行时行为监控, 检测+告警形成安全闭环
动手练习
- 完整 SecurityContext 配置: 给一个现有 Deployment 添加完整的安全 SecurityContext(非 root + 只读 FS + drop ALL + seccomp RuntimeDefault), 验证应用仍然正常运行
- 只读文件系统验证: 在配置了
readOnlyRootFilesystem: true的容器中执行touch /test, 观察报错 - PSS enforce 测试: 给 Namespace 添加
pod-security.kubernetes.io/enforce=restrictedlabel, 尝试部署一个 privileged Pod, 观察被拒绝 - Falco 告警触发: 安装 Falco(Helm chart), 触发一条告警规则(如在容器中执行
kubectl exec -- sh), 在 Falco 日志中找到对应告警