kubernetes 安全上下文

kubernetes为安全运行pod及容器运行设计了安全上下文机制,该机制允许用户和管理员定义pod或容器的特权与访问控制,已配置容器与主机以及主机之上的其它容器间的隔离级别。安全上下文就是一组用来决定容器时如何创建和运行的约束条件,这些条件代表创建和运行容器时使用的运行时参数。需要提升容器权限时,用户通常只应授予容器执行其工作所需的访问权限,以最小权限法则来抑制容器对基础架构及其它容器产生的负面影响。

kubernetes支持用户在pod及容器级别配置安全上下文,并允许管理员通过pod安全策略在集群全局级别限制用户在创建和运行pod时可设定安全上下文。安全上下文(Security Context)定义 Pod 或 Container 的特权与访问控制设置。 安全上下文包括但不限于:

自主访问控制(DAC):传统UNIX的访问控制机制,它允许对象的所有者基于UUID和GID设定对象的访问权限。

Linux功能:Linux为突破系统上传统的两级用户(root和普通用户)授权模型,而将内核管理权限打散成多个不同维度或级别的权限子集,每个子集称为一种功能或能力,例如CAP_NET_ADMIN、CAP_SYS_TIME、CAP_SYS_PTRACE和CAP_SYS_ADMIN等,从而允许进程仅具有一部分内核管理功能就能完成必要的管理任务。

seccomp:全称为secure computing mode,是linux内核的安全模型,用于为默认可发起的任何系统调用进程施加控制机制,人为地禁止它能够发起的系统调用,有效降低了程序被劫持的危害级别。

AppArmor:全称为Application Armor,意为应用盔甲,是linux内核的一个安全模块,通过加载带内核的配置文件来定义对程序的约束与控制。

SELinux:全称为Security-Enhanced Linux,意为安全加强的Linux,是linux内核的一个安全模块,提供了包括强制访问控制在内的访问控制安全策略机制。

Privileged模式:即特权模式容器,该模式下容器中的root用户拥有所有的内核功能,即具有真正的管理员权限,它能看到主机上的所有设备,能够挂载文件系统,甚至可以在容器中运行容器;容器默认运行于非特权模式。 AllowPrivilegeEscalation:控制是否允许特权升级,及进程是否能够获取比父进程更多的特权;运行于特权模式或具有CAP_SYS_ADMIN能力的容器默认允许特权升级。

这些安全上下文相关的特性多数嵌套定义在pod或容器的securityContext字段中,而且有些特性对应的嵌套字段还不止一个。而seccomp和AppArmor的安全上下文则需要以资源注解的方式进行定义,而且技能由管理员在集群级别进行pod安全策略配置。

配置格式

apiVersion: v1
kind: Pod
metadata:
  name: securitycontext-capabilities-demo
  namespace: default
spec:
  securityContext:            #pod级别的安全上下文,对内部多有容器均有效
    runAsUer <integer>        #以指定的用户身份运行容器进程,默认由镜像中的USER指定
    runAsGroup <integer>      #以指定的用户组运行容器进程,默认使用的组随容器运行时设定
    supplementalGroups <[] integer>  #为容器中1号进程的用户添加的附加组
    fsGroup <integer>         #为容器中的1号进程附加一个专用组,其功能类似于sgid
    runAsNonRoot <boolean>    #是否以非root身份运行
    seLinuxOptions <object>   #SELINUX的相关配置
    sysctl <[] object>        #应用到当前pod名称空间级别的sysctl参数设置列表
    windowsOptions <object>   #windows容器专用配置
  containers:
  - name: ...
    image: ...
    securityContext:      #容器级别的安全上下文,仅在当前容器生效
      runAsUer <integer>        #以指定的用户身份运行容器进程,默认由镜像中的USER指定
      runAsGroup <integer>      #以指定的用户组运行容器进程,默认使用的组随容器运行时设定
      runAsNonRoot <boolean>    #是否以非root身份运行
      allowPrivilegeEscalation <boolean> #是否允许特权升级
      capabilities <object>     #为当前容器添加或删除内核能力
        add <[] string>         #添加由列表定义的各项内核能力
        drop <[] string>        #移除由列表定义的各项内核能力
      privileged <boolean>      #是否允许为特权容器
      procMount <string>        #设置容器procMount类型,默认为DefaultProcMount
      readOnlyRootFilesystem <boolean>  #是否将根文件系统设置为只读模式
      seLinuxOptions <object>   #selinux相关配置
      windowsOptions <object>   #windows相关配置

内核功能

传统linux仅实现了特权和非特权两类进程,前者是指以0号UID身份运行的进程,而后者则是从属非0号UID用户的进程。linux内核从2.2版本开始将附加在超级用户的权限分割为多个独立单元,这些单元是线程级别的,它们可配置在每个线程之上为其赋予特定的管理能力。linux内核常用的功能包括但不限于如下这些:

CAP_CHOWN:改变文件的UID和GID。

CAP_MKNOD:借助系统调用mknod()创建设备文件。

CAP_NET_ADMIN:网络管理相关的操作,可用于管理网络接口、netfilter上的iptables规则、路由表、透明代理、TOS、清空驱动统计数据、设计混杂模式和启动多播功能等。

CAP_NET_BIND_SERVICE:绑定小于1024的特权端口,但该功能在重新映射用户后可能会失效。 CAP_NET_RAW:使用RAW或PACKET类型的套接字,并可绑定任何地址进行透明代理。

CAP_SYS_ADMIN:支持内核上的很大一部分管理功能。

CAP_SYS_BOOT:重启系统

CAP_SYS_CHROOT:使用chroot()进行根文件系统切换,并能够调用setns()修改Mount名称空间

CAP_SYS_MODULE:转载内核模块

CAP_SYS_TIME:设定系统时钟和硬件时钟

CAP_SYSLOG:调用syslog()执行日志相关的特权操作。

内核功能示例

apiVersion: v1
kind: Pod
metadata:
  name: securitycontext-capabilities-demo
  namespace: default
spec:
  containers:
  - name: demo
    image: myapp:v1.0
    imagePullPolicy: IfNotPresent
    securityContext:
      capabilities:
        add: ['NET_ADMIN']
        drop: ['CHOWN']

特权容器

kubernetes集群中,kube-proxy中的容器就运行在特权模式

例如:

#查看kube-proxy yaml
kubectl get pods -n kube-system kube-proxy-ggdx8 -o yaml

apiVersion: v1
kind: Pod
metadata:
  ...
  namespace: kube-system
  ...
  containers:
  - command:
    - /usr/local/bin/kube-proxy
    - --config=/var/lib/kube-proxy/config.conf
    - --hostname-override=$(NODE_NAME)
    env:
    - name: NODE_NAME
      valueFrom:
        fieldRef:
          apiVersion: v1
          fieldPath: spec.nodeName
    image: registry.aliyuncs.com/google_containers/kube-proxy:v1.28.5
    imagePullPolicy: IfNotPresent
    name: kube-proxy
    resources: {}
    securityContext:
      privileged: true
    ...

在pod中使用sysctl

kubernetes允许在pod中独立安全地设置支持名称空间级别的内核参数,它们默认处于启动状态,而节点级别内核参数则被认为是不安全地,它们默认处于禁用状态。kernel.shm_rmid_force、net.ipv4.ip_local_range和net.ipv4.tcp_sysncookies这3个内核参数被kubernetes视为安全参数,它们在pod安全上下文的sysctl参数内嵌套使用,而余下的绝大多数的内核参数都是非安全参数,需要管理员手动在每个节点上通过kubelet选项逐个启用后才能配置到pod上。例如在各工作节点上编辑/etc/default/kubelet文件加入KUBELET_EXTRA_ARGS='--allowed-unsafe-sysctls=net.core.somaxconn,net.ipv4.ip_unprivileged_port_start',添加以下内容允许在pod上使用指定的两个非安全地内核参数,并重启kubelet服务使之生效。

例如:

apiVersion: v1
kind: Pod
metadata:
  name: securitycontext-sysctls-demo
  namespace: default
spec:
  securityContext:
    sysctls:
    - name: kernel.shm_rmid_forced
      value: "0"
    - name: net.ipv4.ip_unprivileged_port_start
      value: "0"
  containers:
  - name: demo
    image: myapp:v1.0
    imagePullPolicy: IfNotPresent
    securityContext:
      runAsUser: 1001
      runAsGroup: 1001

官方文档

Configure a Security Context for a Pod or Container | Kubernetes