一 Pod安全 1.1 PodSecurityPolicy啟用 為了更精細地控制Pod對資源的使用方式,Kubernetes從1.4版本開始引入了PodSecurityPolicy資源對象對Pod的安全策略進行管理,併在1.1版本中升級為Beta版,到1.14版本時趨於成熟。 若想啟用PodSecu ...
一 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.service1 …… 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.yaml1 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 宿主機資源相關配置
- hostPID:是否允許Pod共用宿主機的進程空間。
- hostIPC:是否允許Pod共用宿主機的IPC命名空間。
- hostNetwork:是否允許Pod使用宿主機網路的命名空間。
- hostPorts:是否允許Pod使用宿主機的埠號,可以通過hostPortRange欄位設置允許使用的埠號範圍,以[min,max]設置最小埠號和最大埠號。
- Volumes:允許Pod使用的存儲捲Volume類型,設置為“*”表示允許使用任意Volume類型,建議至少允許Pod使用下列Volume類型。
- configMap
- downwardAPI
- emptyDir
- persistentVolumeClaim
- secret
- projected
- AllowedHostPaths:允許Pod使用宿主機的hostPath路徑名稱,可以通過pathPrefix欄位設置路徑的首碼,並可以設置是否為只讀屬性。
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的上層目錄。
- 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。
- ReadOnlyRootFilesystem:要求容器運行的根文件系統(rootfilesystem)必須是只讀的。
- allowedFlexVolumes:對於類型為flexVolume的存儲捲,設置允許使用的驅動類型。
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 用戶和組相關配置
- 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都可以運行。
- 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的用戶都可以運行。
2.4 提升許可權相關配置
- AllowPrivilegeEscalation:設置容器內的子進程是否可以提升許可權,通常在設置非root用戶(MustRunAsNonRoot)時進行設置。
- DefaultAllowPrivilegeEscalation:設置AllowPrivilegeEscalation的預設值,設置為disallow時,管理員還可以顯式設置AllowPrivilegeEscalation來指定是否允許提升許可權。
2.5 Linux能力相關配置
- AllowedCapabilities:設置容器可以使用的Linux能力列表,設置為“*”表示允許使用Linux的所有能力(如NET_ADMIN、SYS_TIME等)。
- RequiredDropCapabilities:設置不允許容器使用的Linux能力列表。
- DefaultAddCapabilities:設置預設為容器添加的Linux能力列表,例如SYS_TIME等,Docker建議預設設置的Linux能力請查看https://docs.docker.com/engine/reference/run/#runtime-privilege-and-linuxcapabilities。
2.6.SELinux相關配置
- seLinux:設置SELinux參數,可以將規則欄位(rule)的值設置為MustRunAs或RunAsAny。
- MustRunAs:要求設置seLinuxOptions,系統將對Pod的securityContext.seLinuxOptions設置的值進行校驗。
- RunAsAny:不限制seLinuxOptions的設置。
2.7 其他Linux相關配置
- AllowedProcMountTypes:設置允許的ProcMountTypes類型列表,可以設置allowedProcMountTypes或DefaultProcMount。
- AppArmor:設置對容器可執行程式的訪問控制許可權,詳情請參考https://kubernetes.io/docs/tutorials/clusters/apparmor/#podsecuritypolicyannotations。
- Seccomp:設置允許容器使用的系統調用(SystemCalls)的profile。
- 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 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相關設置。
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