Kubernetes:創建和分配Kubernetes Pod安全策略

目錄

Pod Security Policies(PSP)

Pod的安全策略配置

1.PodSecurityPolicy的工作機制

2.PodSecurityPolicy配置詳情

2.1.特權模式相關配置

2.2.宿主機資源相關配置

2.3.用戶和組相關配置

       2.4.提升權限相關配置

      2.5.Linux能力相關配置

     2.6.SELinux相關配置

     2.7.其他Linux相關配置

示例的PodSecurityPolicy安全策略配置

例1:基本沒有限制的安全策略,允許創建任意安全設置的Pod。

例2:要求Pod運行用戶爲非特權用戶;禁止提升權限;不允許使用宿主機網絡、端口號、IPC等資源;限制可以使用的Volume類型,等等。

分配Kubernetes Pod安全策略

Security Context

Container-level Security Context

Container級別可以設置的安全策略類型

Pod-level Security Context

Pod級別可以設置的安全策略類型


Pod Security Policies(PSP)

Pod Security Policies(PSP)是集羣級的Pod安全策略,自動爲集羣內的Pod和Volume設置Security Context。

使用PSP需要API Server開啓extensions/v1beta1/podsecuritypolicy,並且配置PodSecurityPolicyadmission控制器。

Pod的安全策略配置

Pod 安全策略 是集羣級別的資源,它能夠控制 Pod 運行的行爲,以及它具有訪問什麼的能力。 

爲了更精細地控制Pod對資源的使用方式,Kubernetes從1.4版本開始引入了PodSecurityPolicy資源對象對Pod的安全策略進行管理,並在1.10版本中升級爲Beta版,到1.14版本時趨於成熟。

1.PodSecurityPolicy的工作機制

若想啓用PodSecurityPolicy機制,則需要在kube-apiserver服務的啓動參數--enable-admission-plugins中進行設置:

如果是高可用,所有apiserver均需要修改

kubectl edit pod -n kube-system kube-apiserver-k8s-master
--enable-admission-plugins=PodSecurityPolicy

kube-apiserver-k8s-master,值得是你apiserver組件的pod名稱

在開啓PodSecurityPolicy准入控制器後,Kubernetes默認不允許創建任何Pod,需要創建PodSecurityPolicy策略和相應的RBAC授權策略(Authorizing Policies),Pod才能創建成功。

例如,嘗試創建如下Pod:

apiVersion: v1
kind: Pod
metadata:
  name: nginx
spec:
  containers:
  - name: nginx
    image: nginx

使用Kubectl命令創建時,系統將提示“禁止創建”的報錯信息

接下來創建一個PodSecurityPolicy,配置文件psp-non-privileged.yaml的內容如下:

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:
  - '*'

之後再次創建Pod既可成功。

上面的PodSecurityPolicy“psp-non-privileged”設置了privileged: false,表示不允許創建特權模式的Pod。

在下面的YAML配置文件pod-privileged.yaml中爲Pod設置了特權模式:

apiVersion: v1
kind: Pod
metadata:
  name: nginx
spec:
  containers:
  - name: nginx
    image: nginx
    securityContext:
      privileged: true

創建Pod時,系統將提示“禁止創建特權模式的Pod”的報錯信息.

2.PodSecurityPolicy配置詳情

在PodSecurityPolicy對象中可以設置下列字段來控制Pod運行時的各種安全策略。

Pod 安全策略 由設置和策略組成,它們能夠控制 Pod 訪問的安全特徵。這些設置分爲如下三類:

  • 基於布爾值控制 :這種類型的字段默認爲最嚴格限制的值。
  • 基於被允許的值集合控制 :這種類型的字段會與這組值進行對比,以確認值被允許。
  • 基於策略控制 :設置項通過一種策略提供的機制來生成該值,這種機制能夠確保指定的值落在被允許的這組值中。

2.1.特權模式相關配置

privileged:是否允許Pod以特權模式運行。

2.2.宿主機資源相關配置

(1)hostPID:是否允許Pod共享宿主機的進程空間。
(2)hostIPC:是否允許Pod共享宿主機的IPC命名空間。
(3)hostNetwork:是否允許Pod使用宿主機網絡的命名空間。
(4)hostPorts:是否允許Pod使用宿主機的端口號,可以通過hostPortRange字段設置允許使用的端口號範圍,以【min,max】設置最小端口號和最大端口號。
(5)Volumes:允許Pod使用的存儲卷Volume類型,設置爲“*”表示允許使用任意Volume類型,建議至少允許Pod使用下列Volume類型。

  • configMap
  • downwardAPI
  • emptyDir
  • persistentVolumeClaim
  • secret
  • projected

(6)AllowedHostPaths:允許Pod使用宿主機的hostPath路徑名稱,可以通過pathPrefix字段設置路徑的前綴,並可以設置是否爲只讀屬性,例子如下。

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

結果爲允許Pod訪問宿主機上以“/foo”爲前綴的路徑,包括“/foo”“/foo/”“/foo/bar”等,但不能訪問“/fool”“/etc/foo”等路徑,也不允許通過“/foo/../”表達式訪問/foo的上層目錄。

(7)FSGroup:設置允許訪問某些Volume的Group ID範圍,可以將規則(rule字段)設置爲MustRunAs、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。

(8)ReadOnlyRootFilesystem:要求容器運行的根文件系統(root filesystem)必須是隻讀的。
(9)allowedFlexVolumes:對於類型爲flexVolume的存儲卷,設置允許使用的驅動類型,例子如下。

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

2.3.用戶和組相關配置

(1)RunAsUser:設置運行容器的用戶ID(User 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都可以運行。

(2)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的用戶都可以運行

(3)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的用戶都可以運行。

2.4.提升權限相關配置

(1)AllowPrivilegeEscalation:設置容器內的子進程是否可以提升權限,通常在設置非root用戶(MustRunAsNonRoot)時進行設置。
(2)DefaultAllowPrivilegeEscalation:設置AllowPrivilegeEscalation的默認值,設置爲disallow時,管理員還可以顯式設置AllowPrivilegeEscalation來指定是否允許提升權限。

2.5.Linux能力相關配置

(1)AllowedCapabilities:設置容器可以使用的Linux能力列表,設置爲“*”表示允許使用Linux的所有能力(如NET_ADMIN、SYS_TIME等)。
(2)RequiredDropCapabilities:設置不允許容器使用的Linux能力列表。
(3)DefaultAddCapabilities:設置默認爲容器添加的Linux能力列表,例如SYS_TIME等,Docker建議默認設置的Linux能力請查看https://docs.docker.com/engine/reference/run/#runtime-privilege-and-linux-capabilities。

2.6.SELinux相關配置

seLinux:設置SELinux參數,可以將規則字段(rule)的值設置爲MustRunAs或RunAsAny。

  • MustRunAs:要求設置seLinuxOptions,系統將對Pod的securityContext.seLinuxOptions設置的值進行校驗。
  • RunAsAny:不限制seLinuxOptions的設置。

2.7.其他Linux相關配置

(1)AllowedProcMountTypes:設置允許的ProcMountTypes類型列表,可以設置allowedProcMountTypes或DefaultProcMount。
(2)AppArmor:設置對容器可執行程序的訪問控制權限,詳情請參考https://kubernetes.io/docs/tutorials/clusters/apparmor/#podsecuritypolicy-annotations
(3)Seccomp:設置允許容器使用的系統調用(System Calls)的profile。
(4)Sysctl:設置允許調整的內核參數,詳情請參考https://kubernetes.io/docs/concepts/cluster-administration/sysctl-cluster/#podsecuritypolicy

示例的PodSecurityPolicy安全策略配置

例1:基本沒有限制的安全策略,允許創建任意安全設置的Pod。

apiVersion: policy/v1beta1
kind: PodSecurityPolicy
metadata:
  name: privileged
  annotations:
    seccomp.security.alpha.kubernetes.io/allowedProfileNames: '*'
spec:
  privileged: true
  allowPrivilegeEscalation: true
  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'

例2:要求Pod運行用戶爲非特權用戶;禁止提升權限;不允許使用宿主機網絡、端口號、IPC等資源;限制可以使用的Volume類型,等等。

apiVersion: policy/v1beta1
kind: PodSecurityPolicy
metadata:
  name: restricted
  annotations:
    seccomp.security.alpha.kubernetes.io/allowedProfileNames: 'docker/default'
    apparmor.security.beta.kubernetes.io/allowedProfileNames: 'runtime/default'
    seccomp.security.alpha.kubernetes.io/defaultProfileName: 'docker/default'
    apparmor.security.beta.kubernetes.io/dafaultProfileName: '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: 'MustRunAs'
    ranges:
    - min: 1
      max: 65535
  fsGroup:
    rule: 'MustRunAs'
    ranges:
    - min: 1
      max: 65535
  readOnlyRootFilesystem: false

分配Kubernetes Pod安全策略

Kubernetes建議使用RBAC授權機制來設置針對Pod安全策略的授權,通常應該對Pod的ServiceAccount進行授權。

角色的訪問控制(RBAC)是kubernetes標準的授權模式,並且很容應用於Pod安全策略。藉助RBAC,你可以將Pod安全策略分配給應用。

爲此,我們將創建一個新的YAML文件,該文件不僅會創建集羣範圍的角色(使用ClusterRole定義),還將創建集羣綁定(使用ClusterRoleBinding定義),以向每個經過身份驗證的用戶授予訪問權限。

例如,可以創建如下ClusterRole(也可以創建Role)並將其設置爲允許使用PodSecurityPolicy:

kind: ClusterRole
apiVersion: rbac.authorization.k8s.io/v1
metadata:
  name: <role name>
rules:
- apiGroup: ['policy']
  resources: ['podsecuritypolicies']
  verbs: ['use']
  resourceNames:
  - <list of policies to authorize>  # 允許使用的PodSecurityPolicy列表

然後創建一個ClusterRoleBinding與用戶和ServiceAccount進行綁定:

kind: ClusterRoleBinding
apiVersion: rbac.authorization.k8s.io/v1
metadata:
  name: <binding name>
roleRef:
  kind: ClusterRole
  name: <roke name>  # 之前創建的ClusterRole名稱
  apiGroup: rbac.authorization.k8s.io
subjects:
# 對特定Namespace中的ServiceAccount進行授權
- kind: ServiceAccount
  name: <authorized servie account name> # ServiceAccount 的名稱
  namespace: <authorized pod namespace> # Namespace的名稱
# 對特定用戶進行授權(不推薦)
- kind: User
  apiGroup: rbac.authorization.k8s.io
  name: <authorized user name>  # 用戶名

也可以創建RoleBinding對與該RoleBinding相同的Namespace中的Pod進行授權,通常可以與某個系統級別的Group關聯配置,例如:

kind: RoleBinding
apiVersion: rbac.authorization.k8s.io/v1
metadata:
  name: <binding name>
  namespace: <binding namespace>  # 該RoleBinding 所屬的Namespace
roleRef:
  kind: Role
  name: <role name>
  apiGroup: rbac.authorization.k8s.io
subjects:
# 授權該Namespace中的全部ServiceAccount
- kind: Group
  apiGroup: rbac.authorization.k8s.io
  name: system:serviceaccounts
# 授權該Namespace中的全部哦用戶
- kind: Group
  apiGroup: rbac.authorization.k8s.io
  name: system:authenticated

Security Context

通過上文,我們瞭解了PodSecurityPolicy策略,知道了

  • 在系統管理員對Kubernetes集羣中設置了PodSecurityPolicy策略之後,系統將對Pod和Container級別的安全設置進行校驗,對於不滿足PodSecurityPolicy安全策略的Pod,系統將拒絕創建。

但除此之外還有個,securityContext

  • Pod和容器的安全策略可以在Pod或Container的securityContext字段中進行設置,如果在Pod和Container級別都設置了相同的安全類型字段,容器將使用Container級別的設置。

Security Context的目的是限制不可信容器的行爲,保護系統和其他容器不受其影響。

要爲Pod指定安全設置,請securityContext在Pod規範中包括該字段。該securityContext字段是 PodSecurityContext對象。

Kubernetes提供了三種配置Security Context的方法:

  • Container-level Security Context:僅應用到指定的容器
  • Pod-level Security Context:應用到Pod內所有容器以及Volume
  • Pod Security Policies(PSP):應用到集羣內部所有Pod以及Volume

Container-level Security Context

Container-level Security Context僅應用到指定的容器上,並且不會影響Volume。

Container級別可以設置的安全策略類型

  • runAsUser:容器內運行程序的用戶ID。
  • runAsGroup:容器內運行程序的用戶組ID。
  • runAsNonRoot:是否必須以非root用戶運行程序。
  • privileged:是否以特權模式運行。
  • allowPrivilegeEscalation:是否允許提升權限。
  • readOnlyRootFilesystem:根文件系統是否爲只讀屬性。
  • capabilities:Linux能力列表。
  • seLinuxOptions:SELinux相關設置。

比如

例1:Container級別的安全設置,作用於特定的容器。

apiVersion: v1
kind: Pod
metadata:
  name: security-context-demo-2
spec:
  securityContext:
    runAsUser: 1000
  containers:
  - name: sec-ctx-demo-2
    image: tomcat
    securityContext:
      runAsUser: 2000
      allowPrivilegeEscalation: false

創建該Pod之後進入容器環境,查看到運行進程的用戶ID爲2000:

例2:爲Container設置可用的Linux能力,爲容器設置允許使用的Linux能力包括NET_ADMIN和SYS_TIME。

apiVersion: v1
kind: Pod
metadata:
  name: security-context-demo-3
spec:
  containers:
  - name: sec-ctx-3
    image: tomcat
    securityContext:
      capabilities:
        add: ["NET_ADMIN","SYS_TIME"]

 

創建該Pod之後進入容器環境,查看1號進程的Linux能力設置:

Pod-level Security Context

Pod-level Security Context應用到Pod內所有容器,並且還會影響Volume(包括fsGroup和selinuxOptions)。

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: tomcat
    volumeMounts:
    - name: sec-ctx-vol
      mountPath: /data/demo
    securityContext:
      allowPrivilegeEscalation: false

 在spec.securityContext中設置瞭如下參數。

  • runAsUser=1000:所有容器都將以User ID 1000運行程序,所有新生成文件的User ID也被設置爲1000。
  • runAsGroup=3000:所有容器都將以Group ID 3000運行程序,所有新生成文件的Group ID也被設置爲3000。
  • fsGroup=2000:掛載的卷“/data/demo”及其中創建的文件都將屬於Group ID 2000。
  • 創建該Pod之後進入容器環境,查看到運行進程的用戶ID爲1000:
  • 查看從Volume掛載到容器的/data/demo目錄,其Group ID爲2000
  • 在該目錄下創建一個新文件,可見其用戶ID爲1000,組ID爲2000:

Pod級別可以設置的安全策略類型

  • runAsUser:容器內運行程序的用戶ID。
  • runAsGroup:容器內運行程序的用戶組ID。
  • runAsNonRoot:是否必須以非root用戶運行程序。
  • fsGroup:SELinux相關設置。
  • seLinuxOptions:SELinux相關設置。
  • supplementalGroups:允許容器使用的其他用戶組ID。
  • sysctls:設置允許調整的內核參數。

參考鏈接:

https://kubernetes.io/docs/tasks/configure-pod-container/security-context/

https://kubernetes.io/zh/docs/concepts/policy/pod-security-policy/

https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.18/#securitycontext-v1-core

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章