1. 程式人生 > >035.叢集安全-Pod安全

035.叢集安全-Pod安全

一 Pod安全

1.1 PodSecurityPolicy啟用

為了更精細地控制Pod對資源的使用方式,Kubernetes從1.4版本開始引入了PodSecurityPolicy資源物件對Pod的安全策略進行管理,並在1.1版本中升級為Beta版,到1.14版本時趨於成熟。 若想啟用PodSecurityPolicy機制,需要在kube-apiserver服務的啟動引數--enable-admission-plugins中進行設定: [root@k8smaster01 ~]# vi /etc/systemd/system/kube-apiserver.service
  1 ……
  2 --enable-admission-plugins=PodSecurityPolicy \
  3 ……
[root@k8smaster01 ~]# systemctl daemon-reload [root@k8smaster01 ~]# systemctl restart kube-apiserver.service 在開啟PodSecurityPolicy准入控制器後,Kubernetes預設不允許建立任何Pod,需要建立PodSecurityPolicy策略和相應的RBAC授權策略(Authorizing Policies),Pod才能建立成功。 [root@k8smaster01 study]# vi nginx-pod.yaml #測試建立Pod
  1 apiVersion: v1
  2 kind: Pod
  3 metadata:
  4   name: nginx
  5 spec:
  6   containers:
  7   - name: nginx
  8     image: nginx
  9     ports:
 10     - name: web
 11       containerPort: 80
[root@k8smaster01 study]# kubectl create -f nginx-pod.yaml

1.2 PodSecurityPolicy配置

[root@k8smaster01 study]# vi psp-non-privileged.yaml
  1 apiVersion: policy/v1beta1
  2 kind: PodSecurityPolicy
  3 metadata:
  4   name: psp-non-privileged
  5 spec:
  6   privileged: false		#不允許特權模式的Pod
  7   seLinux:
  8     rule: RunAsAny
  9   supplementalGroups:
 10     rule: RunAsAny
 11   runAsUser:
 12     rule: RunAsAny
 13   fsGroup:
 14     rule: RunAsAny
 15   volumes:
 16   - '*'
[root@k8smaster01 study]# kubectl create -f psp-non-privileged.yaml [root@k8smaster01 study]# kubectl get psp psp-non-privileged #檢視策略 [root@k8smaster01 study]# kubectl create -f nginx-pod.yaml #再次建立Pod 解釋:如上PodSecurityPolicy“psp-non-privileged”設定了privileged:false,表示不允許建立特權模式的Pod。 [root@k8smaster01 study]# vi nginx-pod2.yaml #開啟Pod的特權模式
  1 apiVersion: v1
  2 kind: Pod
  3 metadata:
  4   name: nginx2
  5 spec:
  6   containers:
  7   - name: nginx2
  8     image: nginx
  9     securityContext:
 10       privileged: true
 11     ports:
 12     - name: web
 13       containerPort: 80
[root@k8smaster01 study]# kubectl create -f nginx-pod2.yaml 解釋:如上開啟Pod的特權模式,在建立Pod時,系統將提示如上“禁止建立特權模式的Pod”的報錯資訊。

二 PodSecurityPolicy配置詳解

在PodSecurityPolicy物件中可以設定下列欄位來控制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型別。
    1. configMap
    2. downwardAPI
    3. emptyDir
    4. persistentVolumeClaim
    5. secret
    6. projected
  6. AllowedHostPaths:允許Pod使用宿主機的hostPath路徑名稱,可以通過pathPrefix欄位設定路徑的字首,並可以設定是否為只讀屬性。
示例1:
  1 apiVersion: policy/v1beta1
  2 kind: PodSecurityPolicy
  3 metadata:
  4   name: allow-hostpath-volumes
  5 spec:
  6   volumes:
  7     - hostPath
  8   allowedHostPaths:
  9     - pathPrefix: "/foo"
 10       readOnly: true
解釋:結果為允許Pod訪問宿主機上以“/foo”為字首的路徑,包括“/foo”“/foo/”“/foo/bar”等,但不能訪問“/fool”“/etc/foo”等路徑,也不允許通過“/foo/../”表示式訪問/foo的上層目錄。
  1. FSGroup:設定允許訪問某些Volume的Group ID範圍,可以將規則(rule欄位)設定為MustRunAs、MayRunAs或RunAsAny。
    1. MustRunAs:需要設定Group ID的範圍,例如1~65535,要求Pod的securityContext.fsGroup設定的值必須屬於該Group ID的範圍。
    2. MayRunAs:需要設定Group ID的範圍,例如1~65535,不強制要求Pod設定securityContext.fsGroup。
    3. RunAsAny:不限制Group ID的範圍,任何Group都可以訪問Volume。
  2. ReadOnlyRootFilesystem:要求容器執行的根檔案系統(rootfilesystem)必須是隻讀的。
  3. allowedFlexVolumes:對於型別為flexVolume的儲存卷,設定允許使用的驅動型別。
示例2:
  1 apiVersion: policy/v1beta1
  2 kind: PodSecurityPolicy
  3 metadata:
  4   name: allow-flex-volumes
  5 spec:
  6   volumes:
  7     - flexVolume
  8   allowedflexVolumes:
  9     - driver: example/lvm
 10     - driver: example/cifs

2.3 使用者和組相關配置

  1. RunAsUser:設定執行容器的使用者ID(User ID)範圍,規則欄位(rule)的值可以被設定為MustRunAs、MustRunAsNonRoot或RunAsAny。
    1. MustRunAs:需要設定User ID的範圍,要求Pod的securityContext.runAsUser設定的值必須屬於該User ID的範圍。
    2. MustRunAsNonRoot:必須以非root使用者執行容器,要求Pod的securityContext.runAsUser設定一個非0的使用者ID,或者映象中在USER欄位設定了使用者ID,建議同時設定allowPrivilegeEscalation=false以避免不必要的提升許可權操作。
  2. RunAsAny:不限制User ID的範圍,任何User都可以執行。
    1. RunAsGroup:設定執行容器的Group ID範圍,規則欄位的值可以被設定為MustRunAs、MustRunAsNonRoot或RunAsAny。
    2. MustRunAs:需要設定Group ID的範圍,要求Pod的securityContext.runAsGroup設定的值必須屬於該Group ID的範圍。
    3. MustRunAsNonRoot:必須以非root組執行容器,要求Pod的securityContext.runAsUser設定一個非0的使用者ID,或者映象中在USER欄位設定了使用者ID,建議同時設定allowPrivilegeEscalation=false以避免不必要的提升許可權操作。
    4. RunAsAny:不限制Group ID的範圍,任何Group的使用者都可以執行。
  3. SupplementalGroups:設定容器可以額外新增的Group ID範圍,可以將規則(rule欄位)設定為MustRunAs、MayRunAs或RunAsAny。
    1. MustRunAs:需要設定Group ID的範圍,要求Pod的securityContext.supplementalGroups設定的值必須屬於該Group ID範圍。
    2. MayRunAs:需要設定Group ID的範圍,不強制要求Pod設定securityContext.supplementalGroups。
    3. 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-linuxcapabilities。

2.6.SELinux相關配置

  1. seLinux:設定SELinux引數,可以將規則欄位(rule)的值設定為MustRunAs或RunAsAny。
    1. MustRunAs:要求設定seLinuxOptions,系統將對Pod的securityContext.seLinuxOptions設定的值進行校驗。
    2. RunAsAny:不限制seLinuxOptions的設定。

2.7 其他Linux相關配置

  1. AllowedProcMountTypes:設定允許的ProcMountTypes型別列表,可以設定allowedProcMountTypes或DefaultProcMount。
  2. AppArmor:設定對容器可執行程式的訪問控制權限,詳情請參考https://kubernetes.io/docs/tutorials/clusters/apparmor/#podsecuritypolicyannotations。
  3. Seccomp:設定允許容器使用的系統呼叫(SystemCalls)的profile。
  4. Sysctl:設定允許調整的核心引數,詳情請參考https://kubernetes.io/docs/concepts/cluster-administration/sysctlcluster/#podsecuritypolicy。

2.8 常見PodSecurityPolicy安全策略配置

示例1:基本沒有限制的安全策略,允許建立任意安全設定的Pod。
  1 apiVersion: policy/v1beta1
  2 kind: PodSecurityPolicy
  3 metadata:
  4   name: privileged
  5   annotations:
  6     seccomp.security.alpha.kubernetes.io/allowedProfileNames: '*'
  7 spec:
  8   privileged: true
  9   allowPrivilegeEscalation: true
 10   allowedCapabilities:
 11   - '*'
 12   volumes:
 13   - '*'
 14   hostNetwork: true
 15   hostPorts:
 16   - min: 0
 17     max: 65535
 18   hostIPC: true
 19   hostPID: true
 20   runAsUser:
 21     rule: 'RunAsAny'
 22   seLinux:
 23     rule: 'RunAsAny'
 24   supplementalGroups:
 25     rule: 'RunAsAny'
 26   fsGroup:
 27     rule: 'RunAsAny'
示例2:要求Pod執行使用者為非特權使用者;禁止提升許可權;不允許使用宿主機網路、埠號、IPC等資源;限制可以使用的Volume型別等。
  1 apiVersion: policy/v1beta1
  2 kind: PodSecurityPolicy
  3 metadata:
  4   name: restricted
  5   annotations:
  6     seccomp.security.alpha.kubernetes.io/allowedProfileNames: 'docker/default'
  7     apparmor.security.beta.kubernetes.io/allowedProfileNames: 'runtime/default'
  8     seccomp.security.alpha.kubernetes.io/defaultProfileName: 'docker/default'
  9     apparmor.security.beta.kubernetes.io/dafaultProfileName: 'runtime/default'
 10 spec:
 11   privileged: false
 12   allowPrivilegeEscalation: false
 13   requiredDropCapabilities:
 14   - ALL
 15   volumes:
 16   - 'configMap'
 17   - 'emptyDir'
 18   - 'projected'
 19   - 'secret'
 20   - 'downwardAPI'
 21   - 'persistentVolumeClaim'
 22   hostNetwork: false
 23   hostIPC: false
 24   hostPID: false
 25   runAsUser:
 26     rule: 'MustRunAsNonRoot'
 27   seLinux:
 28     rule: 'MustRunAs'
 29     ranges:
 30     - min: 1
 31       max: 65535
 32   fsGroup:
 33     rule: 'MustRunAs'
 34     ranges:
 35     - min: 1
 36       max: 65535
 37   readOnlyRootFilesystem: false
示例3:建立如下ClusterRole(也可以建立Role)並將其設定為:允許使用PodSecurityPolicy。
  1 kind: ClusterRole
  2 apiVersion: rbac.authorization.k8s.io/v1
  3 metadata:
  4   name: <role name>
  5 rules:
  6 - apiGroup: ['policy']
  7   resources: ['podsecuritypolicies']
  8   verbs: ['use']
  9   resourceNames:
 10   - <list of policies to authorize>  # 允許使用的PodSecurityPolicy列表
然後建立一個ClusterRoleBinding與使用者和ServiceAccount進行繫結。
  1 kind: ClusterRoleBinding
  2 apiVersion: rbac.authorization.k8s.io/v1
  3 metadata:
  4   name: <binding name>
  5 roleRef:
  6   kind: ClusterRole
  7   name: <roke name>  # 之前建立的ClusterRole名稱
  8   apiGroup: rbac.authorization.k8s.io
  9 subjects:
 10 # 對特定Namespace中的ServiceAccount進行授權
 11 - kind: ServiceAccount
 12   name: <authorized servie account name> # ServiceAccount 的名稱
 13   namespace: <authorized pod namespace> # Namespace的名稱
 14 # 對特定使用者進行授權(不推薦)
 15 - kind: User
 16   apiGroup: rbac.authorization.k8s.io
 17   name: <authorized user name>  # 使用者名稱

三 Pod的安全設定詳解

3.1 Pod安全策略型別

當Kubernetes叢集中設定了PodSecurityPolicy策略之後,系統將對Pod和Container級別的安全設定進行校驗,對於不滿足PodSecurityPolicy安全策略的Pod,系統將拒絕建立。 Pod和容器的安全策略可以在Pod或Container的securityContext欄位中進行設定,如果在Pod和Container級別都設定了相同的安全型別欄位,容器將使用Container級別的設定。 在Pod級別可以設定的安全策略型別如下:
  • 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相關設定。
示例1: [root@k8smaster01 study]# vi security-context-pod01.yaml
  1 apiVersion: v1
  2 kind: Pod
  3 metadata:
  4   name: security-context-demo
  5 spec:
  6   securityContext:
  7     runAsUser: 1000
  8     runAsGroup: 3000
  9     fsGroup: 2000
 10   volumes:
 11   - name: sec-ctx-vol
 12     emptyDir: {}
 13   containers:
 14   - name: sec-ctx-demo
 15     image: tomcat
 16     volumeMounts:
 17     - name: sec-ctx-vol
 18       mountPath: /data/demo
 19     securityContext:
 20       allowPrivilegeEscalation: false
[root@k8smaster01 study]# kubectl create -f security-context-pod01.yaml [root@k8smaster01 study]# kubectl exec -ti security-context-demo /bin/bash $ ps aux #執行程序的使用者ID為1000 $ ls -l /data/ #掛載的目錄Group ID為2000 total 0 drwxrwsrwx 2 root 2000 6 Nov 28 13:56 demo 解釋:在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。

3.3 Container安全策略型別

  • runAsUser: 容器內執行程式的使用者ID。
  • runAsGroup: 容器內執行程式的使用者組ID。
  • runAsNonRoot: 是否必須以非root使用者執行程式。
  • privileged: 是否以特權模式執行。
  • allowPrivilegeEscalation: 是否允許提升許可權。
  • readOnlyRootFilesystem: 根檔案系統是否為只讀屬性。
  • capabilities: Linux能力列表。
  • seLinuxOptions: SELinux相關設定。
示例2: [root@k8smaster01 study]# vi security-context-pod02.yaml
  1 apiVersion: v1
  2 kind: Pod
  3 metadata:
  4   name: security-context-demo-2
  5 spec:
  6   securityContext:
  7     runAsUser: 1000
  8   containers:
  9   - name: sec-ctx-demo-2
 10     image: tomcat
 11     securityContext:
 12       runAsUser: 2000
 13       allowPrivilegeEscalation: false
[root@k8smaster01 study]# kubectl create -f security-context-pod02.yaml [root@k8smaster01 study]# kubectl exec security-context-demo-2 /bin/bash $ ps aux #執行程序的使用者ID為1000