前言
上一篇写 ServiceAccount 和 RBAC 时,我把它们理解成 API 层面的权限控制:这个 Pod 里的程序能不能访问 Kubernetes API,能读什么、改什么。
但这还不够。即使一个应用不访问 API Server,它在节点上运行时仍然有权限边界:
1 | 容器用哪个用户运行? |
这些问题主要通过 SecurityContext 表达。
我目前这样区分:
1 | RBAC |
这篇先从几个最容易理解、最常用的字段开始。
Pod 级和 Container 级
SecurityContext 可以写在 Pod 层,也可以写在容器层。
1 | Pod securityContext |
示例:
1 | apiVersion: v1 |
可以这样看:
1 | Pod 层: |
如果容器级和 Pod 级都设置了相关字段,容器级通常更具体。
runAsNonRoot:不要用 root 跑应用
runAsNonRoot: true 表示容器应该以非 root 用户运行。
1 | securityContext: |
如果镜像默认用户是 root,又没有指定非 root 用户,可能会启动失败。
这不是坏事。它是在提醒我:这个应用镜像没有把运行用户设计清楚。
更明确的写法:
1 | securityContext: |
可以理解成:
1 | 不要用 root |
这要求镜像里的文件权限也要配合。否则应用可能因为没有权限读写自己的目录而失败。
allowPrivilegeEscalation:避免提权
allowPrivilegeEscalation: false 表示容器内进程不能获得比父进程更多的权限。
1 | securityContext: |
我把它理解成:
1 | 进程进来时是什么权限 |
这对普通业务容器通常是合理默认值。
如果一个应用要求提权,应该反过来问:它为什么需要?是镜像设计问题,还是它确实是系统级组件?
多数 Web API、worker、前端服务,都不应该需要提权。
readOnlyRootFilesystem:根文件系统只读
readOnlyRootFilesystem: true 会把容器根文件系统设为只读。
1 | securityContext: |
这样应用不能随意往镜像层路径写文件。
1 | /app 只读 |
如果应用需要写临时文件,可以显式挂载 Volume:
1 | volumeMounts: |
这样边界更清楚:
1 | 镜像内容 |
这会逼着应用把“程序文件”和“运行时数据”分开。
capabilities:少给额外能力
Linux capabilities 可以把 root 的一些能力拆开授权。Kubernetes 里可以给容器添加或移除 capabilities。
常见安全写法是先丢掉所有额外能力:
1 | securityContext: |
如果确实需要,再明确加回来:
1 | securityContext: |
NET_BIND_SERVICE 常用于允许进程绑定低端口,例如 80。
我更倾向把 capabilities 当成精细工具,而不是默认全部保留。普通应用通常不需要很多额外能力。
privileged:尽量不要开
privileged: true 会给容器很高的权限。
1 | securityContext: |
这通常只适合少数基础设施组件,比如某些节点级 agent、网络或存储插件。
对普通业务应用来说,它太宽了。
1 | 普通 Web 服务 |
如果某个业务容器必须 privileged 才能跑,我会先怀疑镜像或应用设计,而不是直接放行。
seccomp、AppArmor 和 SELinux
SecurityContext 还能配置更底层的安全机制:
1 | seccomp |
这些能力依赖节点操作系统和集群环境支持。
一个常见 seccomp 写法:
1 | securityContext: |
可以理解成:使用容器运行时提供的默认 seccomp 配置,不让容器拥有完全不受限制的系统调用面。
这一层细节很多,入门阶段我先建立一个方向:普通业务应用尽量用默认受限策略,只有确实需要时再放开。
Pod Security Standards
Kubernetes 现在有 Pod Security Standards,分成三个层级:
1 | Privileged |
Pod Security Admission 可以在 Namespace 级别执行这些标准。
例如给 Namespace 打标签:
1 | metadata: |
这表示在这个 Namespace 里创建 Pod 时,要按 restricted 策略检查。
这里需要注意版本背景:PodSecurityPolicy 已经在 Kubernetes v1.25 移除,现在更应该看 Pod Security Admission 或第三方策略引擎。
一个相对收敛的业务容器示例
下面是我会考虑作为普通 Web 服务起点的配置:
1 | apiVersion: apps/v1 |
这不是所有应用的万能模板,但它表达了几个方向:
1 | 非 root |
如果应用因此跑不起来,我会优先改镜像和文件权限,而不是立刻删掉安全限制。
排查安全上下文问题
SecurityContext 配得更严格后,常见问题是权限不足。
例如:
1 | Permission denied |
排查时我会看:
1 | kubectl describe pod <pod-name> |
常见方向:
- 镜像默认用户是不是 root;
- 应用是否写了只读路径;
- 需要写的目录有没有挂载 Volume;
- 文件 UID/GID 是否和
runAsUser对得上; - 是否真的需要某个 capability。
这类问题表面上是 Pod 起不来,实际是在帮我发现镜像和运行时边界没有设计好。
小结
这一篇整理下来,我对 SecurityContext 的理解可以概括成几句话:
- RBAC 管 API 权限,SecurityContext 管容器运行权限;
- SecurityContext 可以写在 Pod 层或容器层;
- 普通业务容器尽量非 root 运行;
allowPrivilegeEscalation: false可以避免进程提权;readOnlyRootFilesystem: true能让镜像内容保持只读;- capabilities 应该按需添加,默认尽量少;
privileged: true只适合少数系统级组件;- Pod Security Standards 提供了 Privileged、Baseline、Restricted 三个安全层级;
- PodSecurityPolicy 已在 Kubernetes v1.25 移除,应关注 Pod Security Admission 或策略引擎。
下一篇准备整理 NetworkPolicy。SecurityContext 管单个容器权限,NetworkPolicy 要解决 Pod 之间网络访问能不能被限制的问题。
参考资料
- Configure a Security Context:https://kubernetes.io/docs/tasks/configure-pod-container/security-context/
- Pod Security Standards:https://kubernetes.io/docs/concepts/security/pod-security-standards/
- Pod Security Admission:https://kubernetes.io/docs/concepts/security/pod-security-admission/
- Pod Security Policies:https://kubernetes.io/docs/concepts/security/pod-security-policy/