在 Kubernetes(K8s)中部署容器时,默认情况下容器拥有较高的权限,比如以 root 用户运行、能访问主机路径等。如果不加控制,很容易引发安全隐患,比如容器逃逸、数据泄露、越权访问等问题。
这时候,K8s 提供的 SecurityContext(安全上下文) 就成为我们控制容器权限行为的重要工具。
本文将全面解析 SecurityContext 的作用、配置方法、使用场景与最佳实践,帮助你打造更安全的容器运行环境。
一、什么是 SecurityContext?
SecurityContext 是 Kubernetes Pod 或容器级别的安全配置,用于控制容器的用户身份、权限、文件系统访问能力等行为。
它支持两级配置:
PodSecurityContext
:作用于整个 Pod 的安全上下文;securityContext
:作用于某个特定容器。
👉 总体目标就是一句话: "最小权限运行容器,保护宿主系统安全。"
二、SecurityContext 能做什么?
SecurityContext 主要用于以下方面的安全控制:
控制项 | 作用说明 |
---|---|
runAsUser |
指定容器内进程的运行用户 UID |
runAsGroup |
指定容器进程所属的 GID |
fsGroup |
设置挂载卷中文件的 GID,影响读写权限 |
readOnlyRootFilesystem |
是否将容器的根文件系统设为只读 |
allowPrivilegeEscalation |
是否允许权限提升(如 sudo) |
privileged |
是否以特权模式运行容器(几乎拥有主机权限) |
capabilities |
Linux 能力控制(添加/移除特定系统权限) |
seLinuxOptions |
SELinux 配置(需要宿主支持) |
seccompProfile |
控制系统调用(需 1.19+ 支持) |
runAsNonRoot |
强制容器以非 root 用户运行 |
三、Pod 和容器级别的区别
- PodSecurityContext(Pod 级别) :配置应用于 Pod 内所有容器。
- securityContext(容器级别) :配置仅对该容器生效,优先生效。
⚠️ 容器级别会覆盖 Pod 级别的设置。
例如:
yaml
spec:
securityContext:
runAsUser: 1000 # Pod级别,默认用户
containers:
- name: app
image: myapp
securityContext:
runAsUser: 2000 # 覆盖Pod级别设置
四、典型配置示例详解
下面是一个实际使用 SecurityContext 的例子:
yaml
apiVersion: v1
kind: Pod
metadata:
name: secure-pod
spec:
securityContext:
runAsUser: 1000
runAsGroup: 3000
fsGroup: 2000
containers:
- name: secure-app
image: busybox
command: ["sleep", "3600"]
securityContext:
readOnlyRootFilesystem: true
allowPrivilegeEscalation: false
capabilities:
drop: ["ALL"]
add: ["NET_BIND_SERVICE"]
配置含义:
- 容器运行用户为 UID=1000,GID=3000;
- 所有挂载卷文件归属 GID=2000;
- 容器根文件系统为只读;
- 禁止提权操作;
- 移除所有默认 Linux Capabilities,仅保留
NET_BIND_SERVICE
(允许监听低端口);
五、每个字段的详细解释
✅ runAsUser
/ runAsGroup
指定容器进程的用户和组 ID,避免以 root 用户运行。
yaml
runAsUser: 1001
runAsGroup: 1001
配合 runAsNonRoot: true
可以强制要求容器不得以 root 启动。
✅ fsGroup
指定容器挂载卷文件的组 ID,使非 root 用户有权限访问挂载目录。
yaml
fsGroup: 2000
该字段只影响 Volume,不影响镜像内已有文件。
✅ readOnlyRootFilesystem
设为 true 后,容器根目录 /
将无法写入,提高安全性。
yaml
readOnlyRootFilesystem: true
适合运行纯计算型或无状态服务,例如:
- Nginx
- Java 应用
- 只读 API 服务
✅ allowPrivilegeEscalation
默认容器可能通过某些方式(如 sudo)获得 root 权限,设置为 false 可防止此类行为。
yaml
allowPrivilegeEscalation: false
搭配 runAsNonRoot
更加严谨。
✅ privileged
设置为 true 表示容器拥有宿主机几乎所有权限(慎用!)。
yaml
privileged: true
用于需要访问内核模块、设备管理等极高权限的特殊场景,如:
- 容器运行 Docker-in-Docker
- 网络探针、内核分析工具等
⚠️强烈不建议业务容器启用该模式。
✅ capabilities
控制容器拥有的 Linux 特权能力。K8s 默认赋予一部分 capabilities,如 CHOWN
、NET_RAW
。
你可以主动移除这些权限:
yaml
capabilities:
drop: ["ALL"]
add: ["NET_BIND_SERVICE"]
仅保留服务监听端口所需权限。
✅ seccompProfile
(K8s 1.19+)
Seccomp 可限制容器能调用的系统调用(Syscall),提供更强的内核安全隔离。
yaml
securityContext:
seccompProfile:
type: RuntimeDefault
支持类型:
RuntimeDefault
: 默认系统策略;Localhost
: 挂载自定义策略文件;Unconfined
: 不启用 Seccomp(不安全)。
六、安全实践建议
实践项 | 推荐配置 | 说明 |
---|---|---|
禁止容器以 root 用户运行 | runAsNonRoot: true |
强制非 root 启动 |
限制提权能力 | allowPrivilegeEscalation: false |
防止 sudo 等方式提权 |
删除默认 capabilities | capabilities.drop: ["ALL"] |
降低系统级访问能力 |
禁用写入根文件系统 | readOnlyRootFilesystem: true |
提升只读安全性 |
启用 Seccomp | seccompProfile: RuntimeDefault |
限制系统调用攻击面 |
使用非特权容器 | privileged: false (默认) |
避免滥用权限 |
七、与 Pod 安全策略(PSP/OPA/Kyverno)配合使用
SecurityContext 是声明性配置,真正执行限制时常需要搭配集群安全控制策略,如:
- ✅ PodSecurityAdmission(K8s 1.25+)
- ✅ OPA/Gatekeeper:策略治理
- ✅ Kyverno:基于 YAML 的策略控制器
- ❌ PodSecurityPolicy(PSP)已弃用
例如,使用 OPA 限制容器必须 drop 所有 Capabilities 或禁止 Privileged 容器启动。
八、常见误区与排查建议
问题 | 原因 | 解决方法 |
---|---|---|
容器运行失败,权限不足 | 文件系统权限不匹配 UID | 调整 fsGroup 或挂载路径权限 |
配置 runAsUser 但仍为 root | 容器级别未配置,或镜像设置了 USER root |
优先配置容器级别 securityContext |
修改 securityContext 无效 | 缓存或 YAML 缺字段 | 确保字段在正确层级、更新生效 |
使用 runAsNonRoot 后容器无法启动 | 镜像未设置 USER,默认 root | 在 Dockerfile 中指定非 root 用户 |
九、总结:打造最小权限容器的关键手段
SecurityContext 是 Kubernetes 容器安全的第一道防线。通过合理配置它,可以最大限度减少攻击面、避免容器逃逸风险,并提高容器之间的权限隔离。
✅ 最佳实践清单:
- 强制非 root 启动(
runAsNonRoot: true
) - 设置
runAsUser
、runAsGroup
明确身份 - 限制特权能力(drop capabilities)
- 启用只读文件系统
- 禁止提权、避免 privileged 模式
- 配合 seccomp 加强内核安全控制