K8s 安全上下文(SecurityContext)全解
1. 基础概念
1.1. 什么是安全上下文
securityContext 用于定义 Pod / 容器的安全运行策略,控制:
- 容器运行的 Linux 用户/用户组
- 文件挂载权限
- Linux 内核能力(Capabilities)
- 是否允许权限提升、是否启用特权容器
- 根文件系统只读、内核参数、seccomp、AppArmor 等安全模块
1.2. 两个配置层级 & 优先级
K8s 支持两级安全上下文,作用范围 + 优先级明确:
- Pod 级别 securityContext:定义在
spec.securityContext,对 Pod 内所有容器生效 - 容器级别 securityContext:定义在
spec.containers[].securityContext,仅对当前容器生效
优先级规则:容器级别 > Pod 级别,同名配置会被容器配置覆盖。
1.3. 核心设计目标
- 最小权限原则:容器不以 root 运行,降低入侵风险
- 限制系统能力:禁用高危 Linux 内核能力
- 禁止权限提升:防止容器内提权逃逸
- 文件系统防护:根目录只读,防止恶意篡改
- 统一安全基线:集群所有容器遵循同一安全规范
2. 运行用户与用户组(身份控制)
控制容器进程以哪个 Linux UID/GID 运行,生产强制禁止 root 运行容器。
2.1. runAsUser
- 含义:指定容器内进程运行的 用户 ID(UID)
- 规则:
- Linux 系统中
UID=0为 root 用户 - 生产必须使用 非 0 普通用户
- 镜像内必须提前存在该 UID,否则容器启动失败
- Linux 系统中
2.2. runAsGroup
- 含义:指定容器内进程运行的 组 ID(GID)
2.3. fsGroup
- 含义:挂载卷(PVC/hostPath/emptyDir)的文件属组
- 核心解决问题:容器运行用户(
runAsUser) 和 宿主机挂载目录权限不一致,导致权限不足无法读写。K8s 会自动将挂载卷所有文件/目录的属组修改为fsGroup。
2.4. runAsNonRoot
- 含义:布尔值,强制禁止 root 运行
true:如果镜像默认使用 UID=0,容器直接启动失败false(默认):允许 root 运行
2.5. 示例:用户身份组合配置
apiVersion: v1
kind: Pod
metadata:
name: sc-user-demo
spec:
securityContext:
runAsUser: 1000
runAsGroup: 1000
fsGroup: 1000
runAsNonRoot: true
containers:
- name: app
image: nginx
2.6. 关键说明
runAsNonRoot: true是安全合规强校验,适合镜像不可控场景fsGroup只对 Volume 生效,不影响容器内部原有文件权限- 若镜像内没有
UID=1000用户,容器会报错:permission denied
3. 特权模式 & 权限提升(高危配置)
3.1. privileged(特权容器)
- 类型:布尔值,默认
false - 作用:开启后容器获得宿主机所有权限,彻底打破容器隔离
- 查看/修改宿主机所有进程、网络、磁盘
- 加载内核模块、修改系统配置
- 挂载宿主机任意目录、访问所有设备
- 风险:极高,容器逃逸、提权风险巨大
- 使用场景:仅 CNI、CSI、节点监控、系统运维组件使用,业务容器严禁开启
containers:
- name: node-agent
image: agent
securityContext:
privileged: true
3.2. allowPrivilegeEscalation(禁止提权)
- 类型:布尔值,默认
true - 作用:控制容器内进程能否提权(如 su、sudo、setuid 程序提权)
true:允许子进程获取比父进程更高权限false:禁止权限提升,即使镜像内有 sudo/setuid 也无法提权
- 生产强制要求:所有业务容器设置为
false,是容器防逃逸核心配置
securityContext:
allowPrivilegeEscalation: false
4. Linux Capabilities(内核能力精细化管控)
4.1. 基础概念
Linux 传统 root 权限被拆分为一组细粒度内核能力(Capabilities),实现「最小权限」:
- 不直接给完整 root 权限,只开放程序必需的内核能力
- 分为
add(添加能力)、drop(移除能力)
4.2. 两个关键字段
capabilities.add:在容器默认能力基础上追加指定能力capabilities.drop:从容器默认能力中移除指定能力
4.3. 生产标准做法
先 drop: ALL 删除所有能力,再按需 add 必需能力,实现最小权限原则:
securityContext:
capabilities:
drop:
- ALL
add:
- NET_BIND_SERVICE # 仅允许绑定低端口
4.4. 常见需要额外 add 的能力
| 能力 | 用途 | 场景 |
|---|---|---|
NET_BIND_SERVICE | 绑定低于 1024 端口 | Web 服务使用 80/443 |
CHOWN | 修改文件属主 | 挂载卷权限修复 |
SYS_PTRACE | 跟踪进程系统调用 | 调试容器(非生产) |
SYS_RESOURCE | 突破资源限制 | 特殊计算任务 |
5. 只读根文件系统(文件系统防护)
5.1. readOnlyRootFilesystem
- 类型:布尔值,默认
false - 作用:容器根文件系统设置为只读,防止恶意篡改、木马写入
- 生产建议:无状态业务容器建议开启
5.2. 配套解决方案
开启 readOnlyRootFilesystem: true 后,应用无法向 /、/tmp、/var/run 写数据。需要挂载 emptyDir 作为临时可写目录:
volumeMounts:
- name: tmp-volume
mountPath: /tmp
- name: log-volume
mountPath: /app/logs
volumes:
- name: tmp-volume
emptyDir: {}
- name: log-volume
emptyDir: {}
5.3. 完整生产示例
securityContext:
allowPrivilegeEscalation: false
readOnlyRootFilesystem: true
capabilities:
drop:
- ALL
add:
- NET_BIND_SERVICE
6. 内核参数 sysctls
通过 securityContext.sysctls 修改容器内内核参数(需节点开启支持):
spec:
securityContext:
sysctls:
- name: net.core.somaxconn
value: "4096"
常用场景:调优网络连接队列、共享内存限制等。
7. 高级安全模块
7.1. Seccomp(安全计算模式)
Linux 内核系统调用过滤机制,限制容器可使用的系统调用,降低攻击面。
securityContext:
seccompProfile:
type: RuntimeDefault
7.2. AppArmor
Linux 强制访问控制模块,限制程序文件读写、网络、执行权限,多用于安全加固集群。
8. 生产标准安全上下文模板
整合用户、提权、能力、只读根、seccomp,企业生产通用基线:
apiVersion: v1
kind: Pod
metadata:
name: production-sc-pod
spec:
securityContext:
runAsUser: 1000
runAsGroup: 1000
fsGroup: 1000
runAsNonRoot: true
containers:
- name: business-app
image: my-app:v1
securityContext:
allowPrivilegeEscalation: false
readOnlyRootFilesystem: true
capabilities:
drop:
- ALL
add:
- NET_BIND_SERVICE
seccompProfile:
type: RuntimeDefault
volumeMounts:
- name: tmp-volume
mountPath: /tmp
- name: log-volume
mountPath: /app/logs
volumes:
- name: tmp-volume
emptyDir: {}
- name: log-volume
emptyDir: {}
9. 关键规则、风险与踩坑点
9.1. 优先级总结
容器 securityContext > Pod securityContext
9.2. 常见启动失败问题
问题1:runAsNonRoot=true 但镜像使用 root
- 现象:容器启动失败
container run as root is not allowed - 解决:镜像内创建普通用户,切换 UID;合理设置
runAsUser
问题2:readOnlyRootFilesystem=true 应用无法写文件
- 现象:
read-only file system - 原因:应用向根目录
/、/tmp、/var/run写数据 - 解决:挂载
emptyDir作为临时可写目录
问题3:挂载卷权限不足
- 现象:挂载 PVC/hostPath 后读写报错
permission denied - 解决:配置
fsGroup,自动修正卷文件属组
问题4:无法绑定 80/443 端口
- 现象:
permission denied - 解决:添加
capabilities.add: ["NET_BIND_SERVICE"]
9.3. 高危配置红线(生产绝对禁止)
- 业务容器开启
privileged: true - 业务容器
allowPrivilegeEscalation: true - 不做
capabilities.drop: ALL,保留大量默认能力 - 容器以 UID=0(root) 运行
10. 不同场景配置建议
10.1. 普通无状态业务(Web/API/微服务)
runAsNonRoot: truerunAsUser/runAsGroup:非 0 普通用户allowPrivilegeEscalation: falsereadOnlyRootFilesystem: true- capabilities:drop ALL,按需加
NET_BIND_SERVICE seccompProfile: RuntimeDefault
10.2. 有状态应用(MySQL/Redis/MQ)
- 不建议开启
readOnlyRootFilesystem(需要持久化写数据) - 其余规则同普通业务:非 root、禁止提权、精简 Capabilities
- 必须配置
fsGroup保证数据卷权限
10.3. 系统组件(CNI、CSI、节点代理)
- 可按需开启
privileged: true - 不强制非 root,遵循组件官方要求
10.4. 测试/临时 Pod
也建议遵循基础安全规则,养成规范。
11. Deployment / StatefulSet 全局生效
安全上下文配置在 Pod 模板中,即可对所有副本生效:
apiVersion: apps/v1
kind: Deployment
metadata:
name: web-deploy
spec:
replicas: 2
template:
spec:
securityContext:
runAsUser: 1000
runAsNonRoot: true
containers:
- name: web
image: nginx
securityContext:
allowPrivilegeEscalation: false
readOnlyRootFilesystem: true
12. 高频面试题
-
securityContext 分为哪两个级别?优先级? 答:Pod 级别、容器级别;容器级别优先级更高。
-
runAsUser、runAsGroup、fsGroup 区别?
- runAsUser/runAsGroup:容器进程运行身份
- fsGroup:挂载卷文件的属组,解决目录权限问题
-
allowPrivilegeEscalation 作用?生产建议值? 答:控制容器内是否可以提权;生产全部设为
false。 -
privileged 特权容器风险?哪些场景可以使用? 答:获取宿主机完全权限,逃逸风险极高;仅网络插件、存储插件、节点运维组件使用。
-
readOnlyRootFilesystem 作用?开启后应用无法写文件如何解决? 答:根目录只读,防篡改;通过 emptyDir 挂载临时可写目录。
-
Linux Capabilities 生产最佳实践? 答:先
drop: ALL删除所有能力,再按需add必需能力(最小权限)。 -
runAsNonRoot=true 作用? 答:强制容器不能以 root 用户启动,镜像使用 root 则直接启动失败。
关联文档
- K8s 环境变量 全维度详解 — 容器配置注入
- Pod 生命周期钩子(Hook)完整详解 — Pod 生命周期管理
- K8s 高阶配置全解 — 高阶配置总览