一文读懂k8s之Pod安全策略

导读

Pod容器想要获取集群的资源信息,须要配置角色和ServiceAccount进行受权。为了更精细地控制Pod对资源的使用方式,Kubernetes从1.4版本开始引入了PodSecurityPolicy资源对象对Pod的安全策略进行管理。linux

Pod特权模式

容器内的进程得到的特权几乎与容器外的进程相同。使用特权模式,能够更容易地将网络和卷插件编写为独立的pod,不须要编译到kubelet中。nginx

PodSecurityPolicy

官网定义程序员

Pod 安全策略(Pod Security Policy) 是集群级别的资源,它可以控制Pod规约 中与安全性相关的各个方面。PodSecurityPolicy 对象定义了一组Pod运行时必须遵循的条件及相关字段的默认值,只有 Pod 知足这些条件才会被系统接受。docker

Pod 安全策略容许管理员控制以下方面:api

 

Pod 安全策略 由设置和策略组成,它们可以控制 Pod 访问的安全特征。这些设置分为以下三类:安全

(1)基于布尔值控制 :这种类型的字段默认为最严格限制的值。bash

(2)基于被容许的值集合控制 :这种类型的字段会与这组值进行对比,以确认值被容许。网络

(3)基于策略控制 :设置项经过一种策略提供的机制来生成该值,这种机制可以确保指定的值落在被容许的这组值中。app

开启flex

若是须要开启PodSecurityPolicy,须要在kube-apiserver的启动参数中设置以下参数

--enable-admission-plugins=PodSecurityPolicy

  

在开启PodSecurityPolicy准入控制器后,k8s默认不容许建立任何Pod,须要建立PodSecurityPolicy和RBAC受权策略,Pod才能建立成功。

注:修改kube-apiserver配置文件/etc/kubernetes/manifests/kube-apiserver.yaml,因为是static pod,因此修改就会生效。

系统默认此参数为:

--enable-admission-plugins=NodeRestriction

  

开启以后建立Pod会出现以下错误:

 

建立PodSecurityPolicy

下列PodSecurityPolicy表示是不容许建立特权模式的Pod

apiVersion: policy/v1beta1 
kind: PodSecurityPolicy
metadata:
  name: psp-non-privileged
spec:
  privileged: false  #不容许特权模式的Pod
  seLinux:
    rule: RunAsAny
  supplementalGroups:
    rule: RunAsAny
  runAsUser:
    rule: RunAsAny
  fsGroup:
    rule: RunAsAny
  volumes:
  - '*'

  

建立以后查看:

kubectl get psp
或者
kubectl get podSecurityPolicy

  

 

以后再次建立Pod就能建立成功

 

上面的PodSecurytiPolicy是设置了不容许建立特权模式的Pod,例如,在下面的YAML配置文件pod-privileged.yaml中为Pod设置了特权模式:

apiVersion: v1
kind: Pod
metadata:
  name: nginx
spec:
  containers:
  - name: nginx
    image: nginx:latest
    imagePullPolicy: IfNotPresent
    ports:
    - containerPort: 80
    securityContext:
      privileged: true

  

建立的时候会报以下错误:

unable to validate against any pod security policy 

 

PodSecurityPolicy配置详解

在PodSecurityPolicy对象中能够设置下列字段来控制Pod运行时的各类安全策略

(1)特权模式相关配置

privileged:是否容许Pod以特权模式运行

(2)宿主机资源相关配置

一、hostPID:是否容许Pod共享宿主机的进程空间

二、hostIPC:是否容许Pod共享宿主机的IPC命名空间

三、hostNetwork:是否容许Pod共享宿主机网络的命名空间

四、hostPorts:是否容许Pod使用宿主机的端口号,能够经过hostPortRange字段设置容许使用的端口号范围,以[min, max]设置最小端口号和最大端口号

五、Volumes:容许Pod使用的存储卷Volume类型,设置为“*”表示容许使用任意Volume类型,建议至少容许Pod使用下列Volume类型。configMap,emptyDir、downwardAPI、persistentVolumeClaim、secret、projected

六、AllowedHostPaths:容许Pod使用宿主机的hostPath路径名称,可经过pathPrefix字段设置路径的前缀,并能够设置是否只读属性,例如:只容许Pod访问宿主机上以“/foo”为前缀的路径,包 括“/foo”“/foo/”“/foo/bar”等,

apiVersion: policy/v1beta1
kind: PodSecurityPolicy
metadata:
  name: all-hostpath-volumes
spec:
  volumes:
  - hostPath
  allowedHostPaths:
  - pathPrefix: "/foo"
    readOnly: true   

  

七、FSGroup:设置容许访问某些Volume的Group ID范围,能够将rule字段设置为ManyRunAs、MayRunAs、RunAsAny

MustRunAs:须要设置Group ID的范围,例如1~65535,要求Pod的securityContext.fsGroup设置的值必须属于该Group ID的范围。

MayRunAs:须要设置Group ID的范围,例如1~65535,不强制要求Pod设置securityContext.fsGroup。

RunAsAny:不限制Group ID的范围,任何Group均可以访问Volume。

八、ReadOnlyRootFilesystem:要求容器运行的根文件系统(root filesystem)必须是只读的

九、allowedFlexVolumes:对于类型为flexVolume的存储卷,设置容许使用的驱动类型,例如:

apiVersion: policy/v1beta1
kind: PodSecurityPolicy
metadata:
  name: allowedflexvolumes
spec:
  volumes:
  - flexVolume
  allowedFlexVolumes:
  - driver: example/lvm
  - driver: example/cifs

  

(3)用户和组相关配置

一、RunAsUser:设置运行容器的用户ID范围,rule能够被设置为MustRunAs、MustRunAsNonRoot或RunAsAny

MustRunAs:须要设置User ID的范围,要求Pod的securityContext.runAsUser设置的值必须属于该User ID的范围。

MustRunAsNonRoot:必须以非root用户运行容器,要求Pod的 securityContext.runAsUser设置一个非0的用户ID,或者镜像中在USER字段设置了用户ID,建议同时设置allowPrivilegeEscalation=false以免不 必要的提高权限操做。

RunAsAny:不限制User ID的范围,任何User均可以运行。

二、RunAsGroup:设置运行容器的Group ID范围,能够被设置为MustRunAs、MustRunAsNonRoot、RunAsAny

MustRunAs:须要设置Group ID的范围,要求Pod的securityContext.runAsGroup设置的值必须属于该Group ID的范围。

MustRunAsNonRoot:必须以非root组运行容器,要求Pod的securityContext.runAsUser设置一个非0的用户ID,或者镜像中在USER字段设置了用户ID,建议同时设置allowPrivilegeEscalation=false以免没必要要的提高权限操做。

RunAsAny:不限制Group ID的范围,任何Group的用户均可以运行。

三、SupplementalGroups:设置容器能够额外添加的Group ID范围,能够将规则(rule字段)设置为MustRunAs、MayRunAs或RunAsAny

MustRunAs:须要设置Group ID的范围,要求Pod的securityContext.supplementalGroups设置的值必须属于该Group ID范围。

MayRunAs:须要设置Group ID的范围,不强制要求Pod设置 securityContext.supplementalGroups。

RunAsAny:不限制Group ID的范围,任何supplementalGroups的用户均可以运行。

(4)提高权限相关配置

一、AllowPrivilegeEscalation:用于设置容器内的子进程是否能够提高权限,一般在设置非Root用户(MustRunAsNonRoot)时进行设置。

二、DefaultAllowPrivilegeEscalation:设置AllowPrivilegeEscalation的默认值,设置为disallow时,管理员还能够显式设置 AllowPrivilegeEscalation来指定是否容许提高权限。

(5)Linux能力相关配置

一、AllowedCapabilities:设置容器使用的linux能力列表,设置为“*”表示容许使用Linux的全部能力(如NET_ADMIN、SYS_TIME等)。

二、RequiredDropCapabilities:设置不容许容器使用的linux能力列表

三、DefaultAddCapabilities:设置默认为容器添加的Linux能力列表,例如SYS_TIME等

(6)SELinux相关配置

seLinux:设置SELinux参数,能够将规则字段(rule)的值设置为MustRunAs或RunAsAny。

MustRunAs:要求设置seLinuxOptions,系统将对Pod的securityContext.seLinuxOptions设置的值进行校验。

RunAsAny:不限制seLinuxOptions的设置

(7)其它Linux相关配置

一、AllowedProcMountType:设置容许的PropMountTypes类型列表,能够设置allowedProcMountTypes或DefaultProcMount。

二、AppArmor:设置对容器可执行程序的访问控制权限,

三、Seccomp:设置容许容器使用的系统调用(System Calls)的profile

四、Sysctl:设置容许调整的内核参数,

(8)列举两种经常使用的PodSecurityPolicy安全策略配置

一、基本没有限制的安全策略,容许建立任意安全设置的Pod。

apiVersion: policy/v1beta1
kind: PodSecurityPolicy
metadata:
  name: privileged
  annotations:
    seccomp.security.alpha.kubernetes.io/allowedProfileNames: "*"
spec:
  privileged: true  #不容许建立特权模式的Pod
  allowPrivilegeEscalation: true  #设置子进程是否能够提高权限,配置MustRunAsNonRoot
  allowedCapabilities:
  - '*'
  volumes:
  - '*'
  hostNetwork: true
  hostPorts:
  - min: 0
    max: 65535
  hostIPC: true
  hostPID: true
  runAsUser:
    rule: 'RunAsAny'
  seLinux:
    rule: 'RunAsAny'
  supplementalGroups:
    rule: 'RunAsAny'
  fsGroup:
    rule: 'RunAsAny'

  

二、要求Pod运行用户为非特权用户;禁止提高权限;不容许使用宿主机网络、端口号、IPC等资源;限制可使用的Volume类型,等等

apiVersion: policy/v1beta1
kind: PodSecurityPolicy
metadata:
  name: retricted
  annotations:
    seccomp.security.alpha.kubernetes.io/allowedProfileNames: 'docker/default'
    seccomp.security.alpha.kubernetes.io/defaultProfileNames: 'docker/default'
    apparmor.security.beta.kubernetes.io/allowedProfileNames: 'runtime/default' 
    apparmor.security.beta.kubernetes.io/defaultProfileNames: 'runtime/default' 
spec:
  privileged: false
  allowPrivilegeEscalation: false
  requiredDropCapabilities:
  - ALL
  volumes:
  - 'configMap'
  - 'emptyDir'
  - 'projected'
  - 'secret'
  - 'downwardAPI'
  - 'persistentVolumeClaim'
  hostNetwork: false
  hostIPC: false
  hostPID: false
  runAsUser:
    rule: 'MustRunAsNonRoot'
  seLinux:
    rule: 'RunAsAny'
  supplementalGroups:
    rule: 'MustRunAsRoot'
    ranges:
    - min: 1
      max: 65535
  fsGroup:
    rule: 'MustRunAsRoot'
    ranges:
    - min: 1
      max: 65535
  readOnlyRootFilesystem: false

  

Kubernetes建议使用RBAC受权机制来设置针对Pod安全策略的受权,一般应该对Pod的ServiceAccount进行受权。

例如,能够建立以下ClusterRole(也能够建立Role)并将其设置为容许使用PodSecurityPolicy:

apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
  name: role-name
rules:
- apiGroups: ['policy']
  resources: ['podsecuritypolicies']
  verbs: ['use']
  resourceNames:
  - #容许使用的PodSecurityPolicy列表

  

而后建立一个ClusterRoleBinding与用户和ServiceAccount进行绑定

apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
  name: bind-name
ruleRef:
  kind: ClusterRole
  name: role-name
  apiGroup: rabc.authorization.k8s.io
subjects:
- kind: ServiceAccount
  name: serviceaccount
  namespace:
- kind: User
  name: username
  apiGroup: rbac.authorization.k8s.io

  

也能够建立RoleBinding对与该RoleBinding相同的Namespace中的Pod进行受权,一般能够与某个系统级别的Group关联配置,例如:

apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
  name: bind-name
  namespace: namespace #该RoleBinding所属的namespace
roleRef:
  kind: Role
  name: 
  apiGroup: rabc.authorization.k8s.io
subjects:
#受权该Namespace中的所有ServiceAccount
- kind: Group
  apiGroup: rabc.authorization.k8s.io
  name: system:serviceaccounts
#受权该Namespace的所有用户
- kind: User
  apiGroup: rabc.authorization.k8s.io
  name: system:authenticated

  

Pod的安全设置详解

Pod和容器的安全策略能够在Pod或Container的securityContext字段中设置,若是在Pod和Container级别都设置了相同的安全类型字段,容器将使用Container级别的设置。

在Pod级别能够设置的安全措施以下:

◎ runAsUser:容器内运行程序的用户ID。

◎ runAsGroup:容器内运行程序的用户组ID。

◎ runAsNonRoot:是否必须以非root用户运行程序。◎ fsGroup:SELinux相关设置。

◎ seLinuxOptions:SELinux相关设置。

◎ supplementalGroups:容许容器使用的其余用户组ID。

◎ sysctls:设置容许调整的内核参数。

在Container级别能够设置的安全策略类型以下:

◎ runAsUser:容器内运行程序的用户ID。

◎ runAsGroup:容器内运行程序的用户组ID。

◎ runAsNonRoot:是否必须以非root用户运行程序。

◎ privileged:是否以特权模式运行。

◎ allowPrivilegeEscalation:是否容许提高权限。

◎ readOnlyRootFilesystem:根文件系统是否为只读属性。

◎ capabilities:Linux能力列表。

◎ seLinuxOptions:SELinux相关设置。

例如:Pod级别的安全设置,做用于该Pod内的所有容器

apiVersion: v1
kind: Pod
metadata:
  name: security-context-demo
spec:
  securityContext:
    runAsUser: 1000
    runAsGroup: 3000
    fsGroup: 2000
  volumes:
  - name: sec-ctx-vol
    emptyDir: {}
  containers:
  - name: sec-ctx-demo
    image: nginx
    volumeMounts:
    - name: sec-ctx-demo
      mountPath: /data/demo
    securityContext:
      allowPrivilegeEscalation: false

  

◎ runAsUser=1000:全部容器都将以User ID 1000运行程序,全部新生成文件的User ID也被设置为1000。

◎ runAsGroup=3000:全部容器都将以Group ID 3000运行程序,全部新生成文件的Group ID也被设置为3000。

◎ fsGroup=2000:挂载的卷“/data/demo”及其中建立的文件都将属于Group ID 2000。

Container级别的安全设置,做用于特定的容器。

apiVersion: v1
kind: Pod
metadata:
  name: scd-2
spec:
  securityContext:
    runAsUser: 1000
  containers:
  - name: scd-2
    image: nginx:latest
    imagePullPolicy: IfNotPresent
    securityContext:
      runAsUser: 2000
      allowPrivilegeEscalation: false

  

为Container设置可用的Linux能力,为容器设置容许使用的Linux能力包括NET_ADMIN和SYS_TIME。

apiVersion: v1
kind: Pod
metadata:
  name: scd-3
spec:
  containers:
  - name: scd-3
    image: nginx
    securityContext:
      capabilities:
        add: ["NET_ADMIN","SYS_TIME"]

  

 

===============================

我是Liusy,一个喜欢健身的程序员。

获取更多干货以及最新消息,请关注公众号:上古伪神

若是对您有帮助,点个关注就是对我最大的支持!!!

相关文章
相关标签/搜索