導讀
Pod容器想要獲取叢集的資源資訊,需要配置角色和ServiceAccount進行授權。為了更精細地控制Pod對資源的使用方式,Kubernetes從1.4版本開始引入了PodSecurityPolicy資源物件對Pod的安全策略進行管理。
Pod特權模式
容器內的程式獲得的特權幾乎與容器外的程式相同。使用特權模式,可以更容易地將網路和卷外掛編寫為獨立的pod,不需要編譯到kubelet中。
PodSecurityPolicy
官網定義
Pod 安全策略(Pod Security Policy) 是叢集級別的資源,它能夠控制Pod規約 中與安全性相關的各個方面。PodSecurityPolicy 物件定義了一組Pod執行時必須遵循的條件及相關欄位的預設值,只有 Pod 滿足這些條件才會被系統接受。
Pod 安全策略允許管理員控制如下方面:
Pod 安全策略 由設定和策略組成,它們能夠控制 Pod 訪問的安全特徵。這些設定分為如下三類:
(1)基於布林值控制 :這種型別的欄位預設為最嚴格限制的值。
(2)基於被允許的值集合控制 :這種型別的欄位會與這組值進行對比,以確認值被允許。
(3)基於策略控制 :設定項通過一種策略提供的機制來生成該值,這種機制能夠確保指定的值落在被允許的這組值中。
開啟
如果需要開啟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)宿主機資源相關配置
1、hostPID:是否允許Pod共享宿主機的程式空間
2、hostIPC:是否允許Pod共享宿主機的IPC名稱空間
3、hostNetwork:是否允許Pod共享宿主機網路的名稱空間
4、hostPorts:是否允許Pod使用宿主機的埠號,可以通過hostPortRange欄位設定允許使用的埠號範圍,以[min, max]設定最小埠號和最大埠號
5、Volumes:允許Pod使用的儲存卷Volume型別,設定為“*”表示允許使用任意Volume型別,建議至少允許Pod使用下列Volume型別。configMap,emptyDir、downwardAPI、persistentVolumeClaim、secret、projected
6、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
7、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。
8、ReadOnlyRootFilesystem:要求容器執行的根檔案系統(root filesystem)必須是隻讀的
9、allowedFlexVolumes:對於型別為flexVolume的儲存卷,設定允許使用的驅動型別,例如:
apiVersion: policy/v1beta1 kind: PodSecurityPolicy metadata: name: allowedflexvolumes spec: volumes: - flexVolume allowedFlexVolumes: - driver: example/lvm - driver: example/cifs
(3)使用者和組相關配置
1、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都可以執行。
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的使用者都可以執行。
(4)提升許可權相關配置
1、AllowPrivilegeEscalation:用於設定容器內的子程式是否可以提升許可權,通常在設定非Root使用者(MustRunAsNonRoot)時進行設定。
2、DefaultAllowPrivilegeEscalation:設定AllowPrivilegeEscalation的預設值,設定為disallow時,管理員還可以顯式設定 AllowPrivilegeEscalation來指定是否允許提升許可權。
(5)Linux能力相關配置
1、AllowedCapabilities:設定容器使用的linux能力列表,設定為“*”表示允許使用Linux的所有能力(如NET_ADMIN、SYS_TIME等)。
2、RequiredDropCapabilities:設定不允許容器使用的linux能力列表
3、DefaultAddCapabilities:設定預設為容器新增的Linux能力列表,例如SYS_TIME等
(6)SELinux相關配置
seLinux:設定SELinux引數,可以將規則欄位(rule)的值設定為MustRunAs或RunAsAny。
MustRunAs:要求設定seLinuxOptions,系統將對Pod的securityContext.seLinuxOptions設定的值進行校驗。
RunAsAny:不限制seLinuxOptions的設定
(7)其它Linux相關配置
1、AllowedProcMountType:設定允許的PropMountTypes型別列表,可以設定allowedProcMountTypes或DefaultProcMount。
2、AppArmor:設定對容器可執行程式的訪問控制許可權,
3、Seccomp:設定允許容器使用的系統呼叫(System Calls)的profile
4、Sysctl:設定允許調整的核心引數,
(8)列舉兩種常用的PodSecurityPolicy安全策略配置
1、基本沒有限制的安全策略,允許建立任意安全設定的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'
2、要求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,一個喜歡健身的程式設計師。
獲取更多幹貨以及最新訊息,請關注公眾號:上古偽神
如果對您有幫助,點個關注就是對我最大的支援!!!