一文讀懂k8s之Pod安全策略

Liusy01發表於2021-01-20

導讀

Pod容器想要獲取叢集的資源資訊,需要配置角色和ServiceAccount進行授權。為了更精細地控制Pod對資源的使用方式,Kubernetes從1.4版本開始引入了PodSecurityPolicy資源物件對Pod的安全策略進行管理。

Pod特權模式

容器內的程式獲得的特權幾乎與容器外的程式相同。使用特權模式,可以更容易地將網路和卷外掛編寫為獨立的pod,不需要編譯到kubelet中。

PodSecurityPolicy

官網定義

Pod 安全策略(Pod Security Policy) 是叢集級別的資源,它能夠控制Pod規約 中與安全性相關的各個方面。PodSecurityPolicy 物件定義了一組Pod執行時必須遵循的條件及相關欄位的預設值,只有 Pod 滿足這些條件才會被系統接受。

Pod 安全策略允許管理員控制如下方面:

一文讀懂k8s之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會出現如下錯誤:

一文讀懂k8s之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

  

一文讀懂k8s之Pod安全策略

 

之後再次建立Pod就能建立成功

一文讀懂k8s之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
一文讀懂k8s之Pod安全策略

 

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,一個喜歡健身的程式設計師。

獲取更多幹貨以及最新訊息,請關注公眾號:上古偽神

如果對您有幫助,點個關注就是對我最大的支援!!!

相關文章