Kubernetes

K8s 安全上下文(SecurityContext)全解

·15 分钟阅读·5910 字
📋 目录

K8s 安全上下文(SecurityContext)全解

1. 基础概念

1.1. 什么是安全上下文

securityContext 用于定义 Pod / 容器的安全运行策略,控制:

  • 容器运行的 Linux 用户/用户组
  • 文件挂载权限
  • Linux 内核能力(Capabilities)
  • 是否允许权限提升、是否启用特权容器
  • 根文件系统只读、内核参数、seccomp、AppArmor 等安全模块

1.2. 两个配置层级 & 优先级

K8s 支持两级安全上下文,作用范围 + 优先级明确:

  1. Pod 级别 securityContext:定义在 spec.securityContext,对 Pod 内所有容器生效
  2. 容器级别 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,否则容器启动失败

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. 关键说明

  1. runAsNonRoot: true 是安全合规强校验,适合镜像不可控场景
  2. fsGroup 只对 Volume 生效,不影响容器内部原有文件权限
  3. 若镜像内没有 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. 两个关键字段

  1. capabilities.add:在容器默认能力基础上追加指定能力
  2. 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. 高危配置红线(生产绝对禁止)

  1. 业务容器开启 privileged: true
  2. 业务容器 allowPrivilegeEscalation: true
  3. 不做 capabilities.drop: ALL,保留大量默认能力
  4. 容器以 UID=0(root) 运行

10. 不同场景配置建议

10.1. 普通无状态业务(Web/API/微服务)

  • runAsNonRoot: true
  • runAsUser/runAsGroup:非 0 普通用户
  • allowPrivilegeEscalation: false
  • readOnlyRootFilesystem: 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. 高频面试题

  1. securityContext 分为哪两个级别?优先级? 答:Pod 级别、容器级别;容器级别优先级更高

  2. runAsUser、runAsGroup、fsGroup 区别?

    • runAsUser/runAsGroup:容器进程运行身份
    • fsGroup:挂载卷文件的属组,解决目录权限问题
  3. allowPrivilegeEscalation 作用?生产建议值? 答:控制容器内是否可以提权;生产全部设为 false

  4. privileged 特权容器风险?哪些场景可以使用? 答:获取宿主机完全权限,逃逸风险极高;仅网络插件、存储插件、节点运维组件使用。

  5. readOnlyRootFilesystem 作用?开启后应用无法写文件如何解决? 答:根目录只读,防篡改;通过 emptyDir 挂载临时可写目录。

  6. Linux Capabilities 生产最佳实践? 答:先 drop: ALL 删除所有能力,再按需 add 必需能力(最小权限)。

  7. runAsNonRoot=true 作用? 答:强制容器不能以 root 用户启动,镜像使用 root 则直接启动失败。


关联文档