前文咱們聊到了k8s的訪問控制第二關RBAC受權插件的相關話題,回顧請參考:http://www.javashuo.com/article/p-vbbxttgw-ny.html;今天咱們來聊一下k8s上的訪問控制第三關准入控制相關話題;html
在說准入控制以前,咱們先來回顧下以前的用戶認證和受權,在k8s上用戶認證和受權機制都是經過一個個插件進行功能的擴展,咱們要要想使用某種用戶認證和受權機制,相應的咱們應該去啓用對應的插件;對於用戶認證和受權這兩個機制來講,它們的工做邏輯都是同樣的,都是一票經過的機制,一票經過是指啓有多個插件,只要對應用戶來認證或作受權驗證,只要有其中的一個插件知足要求,對應的用戶就能經過認證,一樣的道理驗證受權也是,在k8s上受權插件是顯式受權的,即只要知足對應定義的受權規則,則對應的驗證受權就會被經過,反之沒有顯式受權的,即使認真經過權限驗證也是不能放行的;對於准入控制來講,在k8s上准入控制是經過准入控制器實現的,一個准入控制器就對應了一個插件,咱們要使用對應的准入控制器,相應咱們也要啓用對應的插件才行;在k8s上准入控制、用戶認證、受權默認都內置並啓用一些插件,咱們能夠直接編寫對應的規則便可;准入控制和用戶認證、受權機制不一樣的是,准入控制的工做邏輯是一票否決機制,所謂一票否決是指在多個准入控制規則當中,只要不知足其中一個規則,對應的請求就是拒絕操做的;對於准入控制來講,它有兩種類型,一種是變異型,一種是校驗型;所謂變異型是指咱們在提交給apiserver進行資源建立時,默認沒有指定的對應字段的信息;它會給咱們補上,或者咱們定義資源的某些屬性的值不太規範,它會幫助咱們修改對應的屬性的值爲一個規範的值,而後提交給apiserver;這種准入控制器一般是幫助咱們把對應提交的資源建立信息,規範後提交給apiserver,使得咱們提交資源的信息是可以知足對應api規範;校驗型准入控制器是用來限制咱們對應建立資源是否合理,是否知足咱們定義的規則,若是不知足就直接拒絕咱們建立;這種控制器主要用來限制咱們對k8s上的資源的使用;node
在k8s上准入控制器的模塊有不少,其中比較經常使用的有LimitRanger、ResourceQuota、ServiceAccount、PodSecurityPolicy等等,對於前面三種准入控制器系統默認是啓用的,咱們只須要定義對應的規則便可;對於PodSecurityPolicy這種准入控制器,系統默認沒有啓用,若是咱們要使用,就必需啓用之後,對應規則纔會正常生效;這裏須要注意一點,對應psp准入控制器,必定要先寫好對應的規則,把規則和權限綁定好之後,在啓用對應的准入控制器,不然先啓用准入控制器,沒有對應的規則,默認狀況它是拒絕操做,在k8s上沒有顯式定義規則都是拒絕,這可能致使現有的k8s系統跑的系統級pod沒法正常工做;因此對於psp准入控制器要慎用,若是規則和權限作的足夠精細,它會給咱們的k8s系統安全帶來大幅度的提高,反之,可能致使整個k8s系統不可用;nginx
查看apiserver啓用的准入控制器git
提示:apiserver啓用准入控制插件須要使用--enable-admission-plugins選項來指定,該選項可使用多個值,用逗號隔開表示啓用指定的准入控制插件;這裏配置文件中顯式啓用了NodeRestrication這個插件;默認沒有寫在這上面的內置准入控制器,它也是啓用了的,好比LimitRanger、ResourceQuota、ServiceAccount等等;對於不一樣的k8s版本,內置的准入控制器和啓用與否請查看相關版本的官方文檔;對於那些沒有啓動的准入控制器,咱們能夠在上面選項中直接啓用,分別用逗號隔開便可;docker
LimitRanger控制器api
LimitRanger准入控制器是k8s上一個內置的准入控制器,LimitRange是k8s上的一個標準資源,它主要用來定義在某個名稱空間下限制pod或pod裏的容器對k8s上的cpu和內存資源使用;它可以定義咱們在某個名稱空間下建立pod時使用的cpu和內存的上限和下限以及默認cpu、內存的上下限;若是咱們建立pod時定義了資源上下限,但不知足LimitRange規則中定義的資源上下限,此時LimitRanger就會拒絕咱們建立此pod;若是咱們在LimitRange規則中定義了默認的資源上下限制,咱們建立資源沒有指定其資源限制,它默認會使用LimitRange規則中的默認資源限制;一樣的邏輯LimitRanger能夠限制一個pod使用資源的上下限,它還能夠限制pod中的容器的資源上下限,比限制pod更加精準;不論是針對pod仍是pod裏的容器,它始終只是限制單個pod資源使用;安全
LimitRange規則定義bash
[root@master01 ~]# cat LimitRang-demo.yaml apiVersion: v1 kind: Namespace metadata: name: myns --- apiVersion: v1 kind: LimitRange metadata: name: cpu-memory-limit-range namespace: myns spec: limits: - default: cpu: 1000m memory: 1000Mi defaultRequest: cpu: 500m memory: 500Mi min: cpu: 500m memory: 500Mi max: cpu: 2000m memory: 2000Mi maxLimitRequestRatio: cpu: 4 memory: 4 type: Container [root@master01 ~]#
提示:以上清單主要定義了兩個資源,一個建立myns名稱空間,一個是在對應myns名稱空間下定義了LimitRange資源;其中LimitRange資源的名稱爲cpu-memory-limit-range,default字段用來指定默認容器資源上限值;defaultRequest用來指定默認容器資源下限值;min字段用來指定限制用戶指定的資源下限不能小於對應資源的值;max是用來限制用戶指定資源上限值不能大於該值;maxLimitRequestRatio字段用來指定資源的上限和下限的比值;即上限是下限的多少倍;type是用來描述對應資源限制的級別,該字段有兩個值pod和container;上述資源清單表示在該名稱空間下建立pod時,默認不指定其容器的資源限制,就限制對應容器最少要有0.5個核心的cpu和500M的內存;最大爲1個核心cpu,1g內存;若是咱們手動定義了容器的資源限制,那麼對應資源限制最小不能小於cpu爲0.5個核心,內存爲500M,最大不能超過cpu爲2個核心,內存爲2000M;若是咱們在建立pod時,只指定了容器的資源上限或下限,那麼上限最大是下限的的4倍,若是指定cpu上限爲2000m那麼下限必定不會小於500m,若是隻指定了cpu下限爲500m那麼上限最大不會超過2000m,對於內存也是一樣的邏輯;網絡
應用資源清單app
[root@master01 ~]# kubectl apply -f LimitRang-demo.yaml namespace/myns created limitrange/cpu-memory-limit-range created [root@master01 ~]# kubectl get limitrange -n myns NAME CREATED AT cpu-memory-limit-range 2021-01-01T08:01:24Z [root@master01 ~]# kubectl describe limitrange cpu-memory-limit-range -n myns Name: cpu-memory-limit-range Namespace: myns Type Resource Min Max Default Request Default Limit Max Limit/Request Ratio ---- -------- --- --- --------------- ------------- ----------------------- Container cpu 500m 2 500m 1 4 Container memory 500Mi 2000Mi 500Mi 1000Mi 4 [root@master01 ~]#
提示:資源清單中若是指定了maxLimitRequestRatio,須要注意min中和max中的對應資源的單位,若是指定的倍數和max與min中指定的值比例不一樣,它這裏會不會讓咱們建立;以下提示
[root@master01 ~]# kubectl apply -f LimitRang-demo.yaml namespace/myns unchanged The LimitRange "cpu-limit-range" is invalid: spec.limits[0].maxLimitRequestRatio[memory]: Invalid value: resource.Quantity{i:resource.int64Amount{value:4, scale:0}, d:resource.infDecAmount{Dec:(*inf.Dec)(nil)}, s:"4", Format:"DecimalSI"}: ratio 4 is greater than max/min = 3.814697 [root@master01 ~]#
提示:咱們在資源中指定maxLimitRequestRatio,它內部就是使用max/min,因此對應的值必須符合max/min的值;
驗證:在myns名稱空間下建立一個pod,默認不指定其資源限制,看看它是否會被limitrange規則自動附加其資源限制?
[root@master01 manifests]# cat pod-demo.yaml apiVersion: v1 kind: Pod metadata: name: nginx-pod-demo namespace: myns spec: containers: - image: nginx:1.14-alpine imagePullPolicy: IfNotPresent name: nginx [root@master01 manifests]# kubectl apply -f pod-demo.yaml pod/nginx-pod-demo created [root@master01 manifests]# kubectl get pods -n myns NAME READY STATUS RESTARTS AGE nginx-pod-demo 1/1 Running 0 15s [root@master01 manifests]# kubectl describe pod nginx-pod-demo -n myns Name: nginx-pod-demo Namespace: myns Priority: 0 Node: node01.k8s.org/192.168.0.44 Start Time: Fri, 01 Jan 2021 16:12:53 +0800 Labels: <none> Annotations: kubernetes.io/limit-ranger: LimitRanger plugin set: cpu, memory request for container nginx; cpu, memory limit for container nginx Status: Running IP: 10.244.1.108 IPs: IP: 10.244.1.108 Containers: nginx: Container ID: docker://4d566a239fe3f80e823352ff2eb0f4bc9e5ca1c107c62d87a5035e2d70e7d8f2 Image: nginx:1.14-alpine Image ID: docker-pullable://nginx@sha256:485b610fefec7ff6c463ced9623314a04ed67e3945b9c08d7e53a47f6d108dc7 Port: <none> Host Port: <none> State: Running Started: Fri, 01 Jan 2021 16:12:54 +0800 Ready: True Restart Count: 0 Limits: cpu: 1 memory: 1000Mi Requests: cpu: 500m memory: 500Mi Environment: <none> Mounts: /var/run/secrets/kubernetes.io/serviceaccount from default-token-n6tg5 (ro) Conditions: Type Status Initialized True Ready True ContainersReady True PodScheduled True Volumes: default-token-n6tg5: Type: Secret (a volume populated by a Secret) SecretName: default-token-n6tg5 Optional: false QoS Class: Burstable Node-Selectors: <none> Tolerations: node.kubernetes.io/not-ready:NoExecute op=Exists for 300s node.kubernetes.io/unreachable:NoExecute op=Exists for 300s Events: Type Reason Age From Message ---- ------ ---- ---- ------- Normal Scheduled 33s default-scheduler Successfully assigned myns/nginx-pod-demo to node01.k8s.org Normal Pulled 32s kubelet Container image "nginx:1.14-alpine" already present on machine Normal Created 32s kubelet Created container nginx Normal Started 32s kubelet Started container nginx [root@master01 manifests]#
提示:能夠看到咱們在myns名稱空間下建立的pod沒有指定其容器資源限制,建立pod後,其內部容器自動就有了默認的資源限制;其大小就是咱們在定義LimitRange規則中的default和defaultRequite字段中指定的資源限制;
驗證:建立一個pod指定其cpu下限爲200m,看看對應pod是否容許咱們建立?
[root@master01 manifests]# cat pod-demo.yaml apiVersion: v1 kind: Pod metadata: name: nginx-pod-demo2 namespace: myns spec: containers: - image: nginx:1.14-alpine imagePullPolicy: IfNotPresent name: nginx resources: requests: cpu: 200m [root@master01 manifests]# kubectl apply -f pod-demo.yaml Error from server (Forbidden): error when creating "pod-demo.yaml": pods "nginx-pod-demo2" is forbidden: [minimum cpu usage per Container is 500m, but request is 200m, cpu max limit to request ratio per Container is 4, but provided ratio is 5.000000] [root@master01 manifests]#
提示:咱們在建立資源清單中限制了容器使用cpu爲200m,在應用資源清單時,它這裏就不容許咱們建立,其緣由是咱們指定的資源限制規則不知足LimitRange這條准入控制規則,因此對應建立pod的請求被拒絕;這也意味着咱們在建立pod時,指定容器資源限制不能低於LimitRange准入控制規則中的最低限制,不然對應pod不被容許建立;
驗證:建立pod時指定其cpu最大限制爲2500m,看看對應pod是否容許被建立?
[root@master01 manifests]# cat pod-demo.yaml apiVersion: v1 kind: Pod metadata: name: nginx-pod-demo2 namespace: myns spec: containers: - image: nginx:1.14-alpine imagePullPolicy: IfNotPresent name: nginx resources: limits: cpu: 2500m [root@master01 manifests]# kubectl apply -f pod-demo.yaml Error from server (Forbidden): error when creating "pod-demo.yaml": pods "nginx-pod-demo2" is forbidden: maximum cpu usage per Container is 2, but limit is 2500m [root@master01 manifests]#
提示:能夠看到在pod容器裏指定對應的資源限制上限大於LimitRange准入控制規則中的max字段的值時,對應pod是不被容許建立;
驗證:給定pod容器的cpu上限或下限爲對應範圍內的值看看對應pod是否容許被建立?
[root@master01 manifests]# cat pod-demo.yaml apiVersion: v1 kind: Pod metadata: name: nginx-pod-demo2 namespace: myns spec: containers: - image: nginx:1.14-alpine imagePullPolicy: IfNotPresent name: nginx resources: requests: cpu: 700m [root@master01 manifests]# kubectl apply -f pod-demo.yaml pod/nginx-pod-demo2 created [root@master01 manifests]# kubectl describe pod nginx-pod-demo2 -n myns Name: nginx-pod-demo2 Namespace: myns Priority: 0 Node: node03.k8s.org/192.168.0.46 Start Time: Fri, 01 Jan 2021 16:33:39 +0800 Labels: <none> Annotations: kubernetes.io/limit-ranger: LimitRanger plugin set: memory request for container nginx; cpu, memory limit for container nginx Status: Running IP: 10.244.3.119 IPs: IP: 10.244.3.119 Containers: nginx: Container ID: docker://4a576eda79e0f2a377ca9d058ee6e64decf45223b720b93c3291eed9c2a920d1 Image: nginx:1.14-alpine Image ID: docker-pullable://nginx@sha256:485b610fefec7ff6c463ced9623314a04ed67e3945b9c08d7e53a47f6d108dc7 Port: <none> Host Port: <none> State: Running Started: Fri, 01 Jan 2021 16:33:40 +0800 Ready: True Restart Count: 0 Limits: cpu: 1 memory: 1000Mi Requests: cpu: 700m memory: 500Mi Environment: <none> Mounts: /var/run/secrets/kubernetes.io/serviceaccount from default-token-n6tg5 (ro) Conditions: Type Status Initialized True Ready True ContainersReady True PodScheduled True Volumes: default-token-n6tg5: Type: Secret (a volume populated by a Secret) SecretName: default-token-n6tg5 Optional: false QoS Class: Burstable Node-Selectors: <none> Tolerations: node.kubernetes.io/not-ready:NoExecute op=Exists for 300s node.kubernetes.io/unreachable:NoExecute op=Exists for 300s Events: Type Reason Age From Message ---- ------ ---- ---- ------- Normal Scheduled 23s default-scheduler Successfully assigned myns/nginx-pod-demo2 to node03.k8s.org Normal Pulled 23s kubelet Container image "nginx:1.14-alpine" already present on machine Normal Created 22s kubelet Created container nginx Normal Started 22s kubelet Started container nginx [root@master01 manifests]#
提示:從上面的示例能夠看到,咱們給定資源下限,對應資源上限它會用默認值給填充;
ResourceQuota准入控制器
ResourceQuota准入控制器也是k8s上內置的准入控制器,默認該控制器是啓用的狀態,它主要做用是用來限制一個名稱空間下的資源的使用;相對於LimitRanger准入控制器相比,它能防止在一個名稱空間下的pod被過多建立時,致使過多佔用k8s上的資源;簡單講它是用來在名稱空間級別限制用戶的資源使用;不一樣於LimitRanger准入控制器,Resourcequota准入控制器限制的是某個名稱空間下的資源,而LimitRanger准入控制器限制的是單個pod或pod中的容器的資源使用;
ResourceQuota資源的建立
[root@master01 ~]# cat resourcequota-demo.yaml apiVersion: v1 kind: ResourceQuota metadata: name: quota-demo namespace: myns spec: hard: pods: "5" requests.cpu: "5" requests.memory: 5Gi limits.cpu: "4" limits.memory: 10Gi count/deployments.apps: "5" count/deployments.extensions: "5" persistentvolumeclaims: "5" [root@master01 ~]#
提示:ResourceQuota的定義其kind類型爲ResourceQuota,羣組爲核心羣組v1;其中spec.hard字段是用來定義對應名稱空間下的資源限制規則;pods用來限制在對應名稱空間下的pod數量,requests.cpu字段用來限制對應名稱空間下全部pod的cpu資源的下限總和;requests.memory用來限制對應名稱空間下pod的內存資源的下限總和;limits.cpu用來限制對應名稱空間下的podcpu資源的上限總和,limits.memory用來限制對應名稱空間下pod內存資源上限總和;count/deployments.apps用來限制對應名稱空間下apps羣組下的deployments的個數,count/deployments.extensions用來限制對應名稱空間下extensions羣組下的deployments的數量;以上配置清單表示,在myns名稱空間下運行的pod數量不能超過5個,或者全部pod的cpu資源下限總和不能大於5個核心,內存資源下限總和不能大於5G,或者cpu上限資源總和不能大於4個核心,內存上限總和不能超過10G,或者apps羣組下的deployments控制器不能超過5個,exetensions羣組下的deploy控制器不能超過5個,pv個數不能超過5個;以上條件中任意一個條目不知足,都將沒法在對應名稱空間建立對應的資源;
應用資源清單
[root@master01 ~]# kubectl apply -f resourcequota-demo.yaml resourcequota/quota-demo created [root@master01 ~]# kubectl get resourcequota -n myns NAME AGE REQUEST LIMIT quota-demo 33s count/deployments.apps: 0/5, count/deployments.extensions: 0/5, persistentvolumeclaims: 0/5, pods: 2/5, requests.cpu: 1200m/5, requests.memory: 1000Mi/5Gi limits.cpu: 2/4, limits.memory: 2000Mi/10Gi [root@master01 ~]# kubectl describe resourcequota quota-demo -n myns Name: quota-demo Namespace: myns Resource Used Hard -------- ---- ---- count/deployments.apps 0 5 count/deployments.extensions 0 5 limits.cpu 2 4 limits.memory 2000Mi 10Gi persistentvolumeclaims 0 5 pods 2 5 requests.cpu 1200m 5 requests.memory 1000Mi 5Gi [root@master01 ~]#
提示:能夠看到應用資源清單之後,對應名稱空間下的資源使用狀況能夠經過查看resourcequota資源的詳細信息就能瞭解到;從上述resourcequota資源的詳細信息中能夠看到,當前myns中pod的cpu資源上限已經使用了2顆核心,對應內存的上限是了2000M;
驗證:在myns下建立2個cpu資源上限爲2000m的pod,看看對應pod是否被容許建立?
[root@master01 manifests]# cat pod-demo.yaml apiVersion: v1 kind: Pod metadata: name: nginx-pod-demo3 namespace: myns spec: containers: - image: nginx:1.14-alpine imagePullPolicy: IfNotPresent name: nginx resources: limits: cpu: 2000m [root@master01 manifests]# kubectl apply -f pod-demo.yaml pod/nginx-pod-demo3 created [root@master01 manifests]# kubectl describe resourcequota quota-demo -n myns Name: quota-demo Namespace: myns Resource Used Hard -------- ---- ---- count/deployments.apps 0 5 count/deployments.extensions 0 5 limits.cpu 4 4 limits.memory 3000Mi 10Gi persistentvolumeclaims 0 5 pods 3 5 requests.cpu 3200m 5 requests.memory 1500Mi 5Gi [root@master01 manifests]# cat pod-demo2.yaml apiVersion: v1 kind: Pod metadata: name: nginx-pod-demo4 namespace: myns spec: containers: - image: nginx:1.14-alpine imagePullPolicy: IfNotPresent name: nginx resources: limits: cpu: 2000m [root@master01 manifests]# kubectl apply -f pod-demo2.yaml Error from server (Forbidden): error when creating "pod-demo2.yaml": pods "nginx-pod-demo4" is forbidden: exceeded quota: quota-demo, requested: limits.cpu=2,requests.cpu=2, used: limits.cpu=4,requests.cpu=3200m, limited: limits.cpu=4,requests.cpu=5 [root@master01 manifests]#
提示:能夠看到在建立第一個pod時,對應pod成功建立,在建立第二個pod時,對應pod就能正常建立,其緣由是對應myns名稱空間下正常處於運行狀態的pod的cpu資源上限總和已經和resourcequota准入控制規則中的limit.cpus字段的值同樣了,再次建立pod時,myns名稱空間下的pod的cpu資源上限總和大於limit.cpus的值,因此不知足resourcequota准入控制規則,因此第二個pod就不容許被建立;
示例:使用resourcequota資源限制名稱空間下的storage資源
[root@master01 ~]# cat resourcequota-storage-demo.yaml apiVersion: v1 kind: ResourceQuota metadata: name: quota-storage-demo namespace: default spec: hard: requests.storage: "5Gi" persistentvolumeclaims: "5" requests.ephemeral-storage: "1Gi" limits.ephemeral-storage: "2Gi" [root@master01 ~]#
提示:requests.storage用來限制對應名稱空間下的存儲下限總和,persistenvolumeclaims用來限制pvc總數量,requests.ephemeral-storage用來如今使用本地臨時存儲的下限總容量;limits.ephemeral-storage用來限制使用本地臨時存儲上限總容量;以上配置表示在default名稱空間下非中止狀態的容器存儲下限總容量不能超過5G,pvc的數量不能超過5個,本地臨時存儲下限容量不能超過1G,上限不能超過2G;
應用配置清單
[root@master01 ~]# kubectl apply -f resourcequota-storage-demo.yaml resourcequota/quota-storage-demo created [root@master01 ~]# kubectl get resourcequota NAME AGE REQUEST LIMIT quota-storage-demo 7s persistentvolumeclaims: 3/5, requests.ephemeral-storage: 0/1Gi, requests.storage: 3Gi/5Gi limits.ephemeral-storage: 0/2Gi [root@master01 ~]# kubectl describe resourcequota quota-storage-demo Name: quota-storage-demo Namespace: default Resource Used Hard -------- ---- ---- limits.ephemeral-storage 0 2Gi persistentvolumeclaims 3 5 requests.ephemeral-storage 0 1Gi requests.storage 3Gi 5Gi [root@master01 ~]#
驗證:在default名稱空間下,再建立3個pvc看看對應資源是否被容許建立?
[root@master01 ~]# cat pvc-v1-demo.yaml apiVersion: v1 kind: PersistentVolumeClaim metadata: name: pvc-nfs-pv-v4 namespace: default spec: accessModes: - ReadWriteMany volumeMode: Filesystem resources: requests: storage: 500Mi --- apiVersion: v1 kind: PersistentVolumeClaim metadata: name: pvc-nfs-pv-v5 namespace: default spec: accessModes: - ReadWriteMany volumeMode: Filesystem resources: requests: storage: 500Mi --- apiVersion: v1 kind: PersistentVolumeClaim metadata: name: pvc-nfs-pv-v6 namespace: default spec: accessModes: - ReadWriteMany volumeMode: Filesystem resources: requests: storage: 500Mi [root@master01 ~]# kubectl apply -f pvc-v1-demo.yaml persistentvolumeclaim/pvc-nfs-pv-v4 created persistentvolumeclaim/pvc-nfs-pv-v5 created Error from server (Forbidden): error when creating "pvc-v1-demo.yaml": persistentvolumeclaims "pvc-nfs-pv-v6" is forbidden: exceeded quota: quota-storage-demo, requested: persistentvolumeclaims=1, used: persistentvolumeclaims=5, limited: persistentvolumeclaims=5 [root@master01 ~]#
提示:能夠看到如今在default名稱空間下建立3個pvc時,對應前兩個被成功建立,第三個被拒絕了;緣由是defualt名稱空間下的pvc資源數量已經達到resourcequota准入控制規則中定義的數量,因此不予建立;
示例:建立resourcequota准入控制規則,並限定其生效範圍
[root@master01 ~]# cat resourcequota-scopes-demo.yaml apiVersion: v1 kind: ResourceQuota metadata: name: quota-scopes-demo namespace: myns spec: hard: pods: "5" scopes: ["BestEffort"] [root@master01 ~]#
提示:限制resourcequota准入控制規則生效範圍,可使用scopes字段來指定對應的範圍;該字段爲一個列表,默認不指定是指全部狀態的pod;其中BsetEffort表示匹配對應pod的QOS(服務質量類別)值爲BestEffort的pod ;NotBestEffort表示匹配對應pod的QOS值不是BestEffort的pod;Terminating表示匹配對應Pod狀態爲Terminating狀態的pod;NotTerminating表示匹配狀態不是Terminating狀態的pod;上述清單規則表示只對pod的服務質量類別爲BestEffort的pod生效;其餘類型的pod不記錄到對應規則中;即只能在對應名稱空間下建立5個服務質量類別爲BestEffort類別的pod;
應用配置清單
[root@master01 ~]# kubectl apply -f resourcequota-scopes-demo.yaml resourcequota/quota-scopes-demo created [root@master01 ~]# kubectl get quota -n myns NAME AGE REQUEST LIMIT quota-scopes-demo 12s pods: 0/5 [root@master01 ~]#
提示:限制pod的服務質量類別爲BestEffort,只能對pod資源施加,其它資源都不支持;
PodSecurityPolicy准入控制器
PodSecurityPolicy准入控制器主要用來設置pod安全相關的策略,好比是否容許對應pod共享宿主機網絡名稱空間,是否容許pod容許爲特權模式等等;
示例:定義psp准入控制器規則
[root@master01 psp]# cat psp-privileged.yaml 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' [root@master01 psp]#
提示:PodSecurityPolicy是k8s的標準資源,其類型爲PodSecurityPolicy,羣組版本爲policy/v1beta1;其中spec字段用來定義對pod的相關安全屬性的定義;privileged用來定義對應pod是否容許運行爲特權模式;allowPrivilegeEscalation用來指定是否運行對應容器子進程特權;allowedCapabilities用來指定容許使用內核中的Capabilities功能,「*」表示全部;volumes用來指定可使用的卷類型列表,*表示可使用支持的任意類型的的卷;hostNetwork表示是否容許共享宿主機網絡名稱空間;hostPorts用來指定可使用宿主機端口範圍,min限制端口下限,max限制端口上限;hostIPC表示是否容許共享宿主機的IPC,hostPID表示是否共享宿主機的PID;runAsUser用來指定對應pod容許以那個用戶身份運行,RunAsAny表示能夠以任意用戶身份運行;以上清單主要定義了一個特權psp准入控制規則,一般這類psp應該有應用在對全部系統級pod使用;通常的普通用戶建立的pod不該該擁有上述權限;
psp准入控制規則相關屬性說明
示例:定義一個非特權psp准入控制法則
[root@master01 psp]# cat psp-restricted.yaml apiVersion: policy/v1beta1 kind: PodSecurityPolicy metadata: name: restricted annotations: seccomp.security.alpha.kubernetes.io/allowedProfileNames: 'docker/default' seccomp.security.alpha.kubernetes.io/defaultProfileName: 'docker/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: 'MustRunAs' ranges: - min: 1 max: 65535 fsGroup: rule: 'MustRunAs' ranges: - min: 1 max: 65535 readOnlyRootFilesystem: false [root@master01 psp]#
提示:定義好上述psp准入控制資源之後,咱們還應該把對那個對應准入控制資源綁定到不一樣的角色上,以實現不一樣角色擁有不一樣的psp准入控制法則的使用權限;
示例:定義clusterrole分別關聯不一樣的psp准入控制資源
[root@master01 psp]# cat clusterrole-with-psp.yaml kind: ClusterRole apiVersion: rbac.authorization.k8s.io/v1 metadata: name: psp:restricted rules: - apiGroups: ['policy'] resources: ['podsecuritypolicies'] verbs: ['use'] resourceNames: - restricted --- kind: ClusterRole apiVersion: rbac.authorization.k8s.io/v1 metadata: name: psp:privileged rules: - apiGroups: ['policy'] resources: ['podsecuritypolicies'] verbs: ['use'] resourceNames: - privileged [root@master01 psp]#
提示:以上定義了兩個clusterrole,一個名爲psp:restricted,該角色主要關聯非特權psp資源,其資源名爲restricted;第二個clusterrole名爲psp:privileged,該角色主要關聯特權psp資源;其對應psp資源名稱爲privileged;
示例:建立clusterrolebinding關聯相關用戶和組
[root@master01 psp]# cat clusterrolebinding-with-psp.yaml kind: ClusterRoleBinding apiVersion: rbac.authorization.k8s.io/v1 metadata: name: restricted-psp-user roleRef: kind: ClusterRole name: psp:restricted apiGroup: rbac.authorization.k8s.io subjects: - kind: Group apiGroup: rbac.authorization.k8s.io name: system:authenticated --- apiVersion: rbac.authorization.k8s.io/v1 kind: ClusterRoleBinding metadata: name: privileged-psp-user roleRef: apiGroup: rbac.authorization.k8s.io kind: ClusterRole name: psp:privileged subjects: - apiGroup: rbac.authorization.k8s.io kind: Group name: system:masters - apiGroup: rbac.authorization.k8s.io kind: Group name: system:node - apiGroup: rbac.authorization.k8s.io kind: Group name: system:serviceaccounts:kube-system [root@master01 psp]#
提示:以上配置主要建立了兩個clusterrolebinding,第一個cluserrolebinding主要把在k8s上認證經過的用戶的權限綁定到psp:restricted這個角色上,讓其擁有對應的權限,即經過認證的用戶擁有非特權psp准入控制法則權限;第二個clusterrolebinding主要綁定了三類用戶,第一類是system:masters組上的用戶,第二類是system:node組上的用戶,第三類是system:serviceaccounts:kube-system組上的用戶;這三個組都是系統級別用戶,主要是系統及pod和組件使用的組;因此這些用戶應該擁有特權psp准入控制法則,對應經過clusterrolebinding綁定到psp:privileged這個角色;
應用上述資源清單
[root@master01 psp]# kubectl apply -f psp-privileged.yaml podsecuritypolicy.policy/privileged created [root@master01 psp]# kubectl apply -f psp-restricted.yaml podsecuritypolicy.policy/restricted created [root@master01 psp]# kubectl apply -f clusterrole-with-psp.yaml clusterrole.rbac.authorization.k8s.io/psp:restricted created clusterrole.rbac.authorization.k8s.io/psp:privileged created [root@master01 psp]# kubectl apply -f clusterrolebinding-with-psp.yaml clusterrolebinding.rbac.authorization.k8s.io/restricted-psp-user created clusterrolebinding.rbac.authorization.k8s.io/privileged-psp-user created [root@master01 psp]#
提示:應用順序先應用psp准入控制資源,而後在應用clusterrole資源,最後應用clusterrolebinding資源;
啓用psp准入控制器
提示:編輯/etc/kubernetes/manifests/kube-apiserver.yaml文件,找到--enable-admission-plugins選項,在最後加上PodSecurityPolicy用逗號隔開;而後保存退出;對應psp准入控制器就啓用了;
驗證:把tom用戶設置爲myns名稱空間下的管理員,而後使用tom用戶的配置文件在myns下建立一個pod,該pod使用hostNetwork:true選項來共享宿主機網絡名稱空間,看看是否可以正常將pod建立出來?
設置tom用戶爲myns名稱空間下的管理員
[root@master01 ~]# cat tom-rolebinding-myns-admin.yaml apiVersion: rbac.authorization.k8s.io/v1 kind: RoleBinding metadata: name: tom-myns-admin namespace: myns roleRef: kind: ClusterRole name: admin apiGroup: rbac.authorization.k8s.io subjects: - kind: User apiGroup: rbac.authorization.k8s.io name: tom [root@master01 ~]# kubectl apply -f tom-rolebinding-myns-admin.yaml rolebinding.rbac.authorization.k8s.io/tom-myns-admin created [root@master01 ~]# kubectl get rolebinding -n myns NAME ROLE AGE tom-myns-admin ClusterRole/admin 10s [root@master01 ~]#
驗證tom用戶證書信息不是在system:master組內
[root@master01 ~]# cat /tmp/myk8s.config |grep client-certificate-data|awk {'print $2'}|base64 -d|openssl x509 -text -noout Certificate: Data: Version: 1 (0x0) Serial Number: f4:39:a9:5d:2f:01:09:2b Signature Algorithm: sha256WithRSAEncryption Issuer: CN=kubernetes Validity Not Before: Dec 29 16:29:59 2020 GMT Not After : Dec 29 16:29:59 2021 GMT Subject: CN=tom, O=myuser Subject Public Key Info: Public Key Algorithm: rsaEncryption Public-Key: (2048 bit) Modulus: 00:b7:02:e8:0d:ca:d5:3f:36:42:20:5c:16:6c:dd: 2a:be:53:f3:b7:14:8e:ca:9f:f4:45:4a:61:97:df: 3c:e8:c2:cd:2f:d8:80:85:29:3d:87:b1:9b:5e:9b: dd:60:0b:5f:60:46:8f:71:8b:49:1a:a6:48:94:f8: 15:0c:f2:98:3c:ab:3a:7c:28:c4:64:76:bf:03:90: 53:f7:2b:6d:18:b5:9b:53:d2:7b:e1:9e:56:bd:c6: 41:a7:99:0a:20:d9:d3:1b:f2:3d:f8:84:bb:8a:22: c7:66:1f:8e:7a:ee:e7:06:27:90:06:ce:23:69:eb: c7:42:69:13:d3:bd:2a:c2:5f:bd:1d:2c:0a:19:ca: f4:d6:a2:d4:47:73:bb:4e:5a:01:75:37:ba:2f:2b: 78:5f:70:3b:ce:5b:46:25:fb:c8:3f:8a:7b:15:ea: 85:aa:b0:b9:28:85:1a:fd:4a:7e:f2:92:40:bd:00: 2a:6c:08:84:eb:7b:dc:5b:e0:13:71:d3:af:75:e3: 6a:23:e1:a5:78:a2:03:ba:bf:e6:1b:bb:37:cc:11: aa:aa:d2:66:10:22:8f:31:a3:4d:f8:79:d2:05:d7: c9:9a:8c:ce:59:7c:30:7e:f1:2d:9a:4a:53:94:cc: 83:47:91:ea:6d:4f:01:9c:c9:3d:c6:9d:85:e0:41: 5c:ff Exponent: 65537 (0x10001) Signature Algorithm: sha256WithRSAEncryption 41:47:71:e6:60:70:5b:b0:5f:9c:47:2d:05:07:fd:93:6d:1b: 16:c3:fd:c8:d4:2e:45:b3:fd:d0:4c:e7:19:b4:80:86:ae:8f: 01:5b:26:f7:01:00:3a:e0:0f:b7:ce:6e:0a:a2:e2:84:2c:86: cd:d8:cb:42:3a:c6:bd:b0:50:72:2e:35:fb:02:5e:78:0c:ce: fa:3d:28:bc:96:63:d0:83:30:93:6f:59:4d:94:27:8d:ea:5c: 1e:19:1b:35:29:87:cf:76:3b:60:4d:8d:f2:b7:37:9a:5a:b6: 7c:58:ae:dd:f0:7a:fd:de:b9:9f:77:bb:fb:9c:42:d8:50:bc: 2f:50:5c:9b:56:4b:90:89:14:c9:52:6d:64:59:dd:3f:53:b1: e4:32:91:d5:98:fb:83:fa:78:23:45:0f:53:92:f0:1a:58:81: 03:f3:a3:b4:0a:83:d3:7c:ef:04:e8:ee:27:df:e8:4f:68:dc: df:46:ef:6b:45:7b:c0:bb:55:fd:82:c6:d9:3b:66:26:14:4a: fe:79:7d:a1:24:43:ba:20:19:6b:b3:d8:0f:2f:30:2b:d3:22: e6:f9:a9:88:38:98:7b:d6:c4:41:17:62:8d:05:6e:1f:c3:e2: 44:dc:35:a2:7f:ed:70:2f:68:75:50:61:74:41:d2:86:dd:75: 18:21:a1:c9 [root@master01 ~]#
提示:能夠看到tom用戶的證書中O=myuser,並不是system:master;
使用tom用戶的配置文件在myns名稱空間下建立pod
[root@master01 manifests]# cat pod-demo3.yaml apiVersion: v1 kind: Pod metadata: name: nginx-pod-demo3 namespace: myns spec: containers: - image: nginx:1.14-alpine imagePullPolicy: IfNotPresent name: nginx hostNetwork: true [root@master01 manifests]# kubectl apply -f pod-demo3.yaml --kubeconfig=/tmp/myk8s.config Error from server (Forbidden): error when creating "pod-demo3.yaml": pods "nginx-pod-demo3" is forbidden: PodSecurityPolicy: unable to admit pod: [spec.securityContext.hostNetwork: Invalid value: true: Host network is not allowed to be used] [root@master01 manifests]#
提示:能夠看到tom用戶在myns名稱空間下建立pod並共享宿主機網絡名稱空間,被apiserver拒絕了;這是由於咱們剛纔啓用了psp准入控制器,對應規則明確規定不在system:master組或system:serviceaccounts:system-kube組或system:node組的全部用戶都不能建立pod共享宿主機名稱空間;
使用system:master組上的用戶建立pod共享宿主機網絡名稱空間,看看是否能夠?
驗證:kubectl的證書,看看對應的組是不是system:master
[root@master01 ~]# cat /etc/kubernetes/admin.conf |grep client-certificate-data|awk {'print $2'}|base64 -d |openssl x509 -text -noout Certificate: Data: Version: 3 (0x2) Serial Number: 886870692518705366 (0xc4ecc322d4838d6) Signature Algorithm: sha256WithRSAEncryption Issuer: CN=kubernetes Validity Not Before: Dec 8 06:38:54 2020 GMT Not After : Dec 8 06:38:56 2021 GMT Subject: O=system:masters, CN=kubernetes-admin Subject Public Key Info: Public Key Algorithm: rsaEncryption Public-Key: (2048 bit) Modulus: 00:c0:4f:cc:45:9b:4a:19:00:a4:af:68:13:f4:39: b0:4c:a8:67:85:af:b3:f7:04:7e:de:16:4b:62:2c: d4:e8:c8:b3:26:39:d2:9a:8e:00:71:ef:82:ff:d3: ad:1a:89:f2:9b:2a:7b:84:c5:5c:85:5a:d0:c5:6e: 89:9d:96:e7:ec:db:92:50:f7:4f:a1:d8:14:2e:48: 33:de:05:48:f1:aa:36:d1:d3:9c:bf:6d:b9:6b:75: ce:66:a5:72:52:6c:bb:6c:2b:96:98:da:e1:99:1b: d4:51:3d:5d:d4:fa:76:d9:18:c7:d2:37:95:ad:3c: e7:af:87:21:75:1b:96:bb:64:51:f5:ae:44:ba:43: e1:d5:5d:39:57:a1:f0:04:e5:39:6c:af:8c:a6:7e: eb:4f:98:5d:07:ce:da:89:91:08:34:db:67:0b:09: 0c:59:3b:16:b0:13:f7:13:b8:fb:6f:54:d1:c9:e5: ce:27:a6:09:af:cc:9d:b5:1e:0a:9c:b4:d2:64:76: cd:35:67:9e:b5:a6:ba:d8:44:e9:c9:e8:0d:fb:c7: 00:06:4a:ce:72:67:a7:0e:56:57:8c:75:2a:c7:0f: bb:4a:d9:0c:ec:a1:27:3a:ce:92:13:e4:bf:d1:31: c8:be:20:58:a0:d6:43:f7:21:8a:cb:e3:fe:5e:1d: d9:2d Exponent: 65537 (0x10001) X509v3 extensions: X509v3 Key Usage: critical Digital Signature, Key Encipherment X509v3 Extended Key Usage: TLS Web Client Authentication X509v3 Authority Key Identifier: keyid:BE:53:44:7A:0F:3D:B0:99:37:F3:D3:52:BE:C1:75:E6:EF:81:DD:13 Signature Algorithm: sha256WithRSAEncryption 35:ea:55:af:57:62:46:26:e9:60:59:82:c2:52:55:45:23:f3: f9:2a:2a:78:28:6c:26:6a:32:c9:df:75:17:ca:44:0f:7f:2a: ae:a5:7b:e5:d0:99:3e:97:27:1d:13:a9:5f:d7:09:29:c8:d9: 68:a6:c1:c5:e3:28:14:6e:0f:c8:32:4b:06:8a:6b:fe:ba:ce: e4:59:b6:70:d4:11:71:cf:e9:c2:dc:da:86:9c:12:82:82:58: 78:83:32:ac:ff:99:6e:1f:07:e0:9d:02:86:dc:e2:e4:30:a1: 36:f1:43:cb:a1:13:1c:27:87:19:89:15:38:25:0a:29:dd:66: 6b:ed:7e:8c:fe:95:8e:10:77:5f:70:47:98:a0:37:4f:9e:57: 6a:66:35:9c:dc:64:f5:1a:01:cd:45:6e:01:bc:15:6f:6f:cd: f6:51:f4:8e:28:14:77:9e:50:42:42:e2:a8:42:76:b5:f9:c8: 87:bb:a5:3e:64:ce:1c:88:6d:31:99:53:c6:8f:88:f1:72:7c: 5a:d6:dc:fe:7e:fa:26:d2:e0:f3:b8:47:d5:8b:c7:b2:88:80: 16:53:38:31:96:19:9a:73:98:c8:c3:30:13:23:71:b7:1d:d4: c9:00:c0:b0:99:bf:24:f3:cf:c6:76:27:d2:6e:3a:5f:fc:5c: 55:25:98:e2 [root@master01 ~]#
提示:能夠看到對應證書信息中的O=system:master,說明使用kubectl工具加載/etc/kubernetes/admin.config文件,在apiserver上認證會被是被爲system:master組上的成員;
使用kubectl 加載/etc/kubernetes/admin.conf 建立pod共享宿主機上的網絡名稱空間;
[root@master01 manifests]# cat pod-demo3.yaml apiVersion: v1 kind: Pod metadata: name: nginx-pod-demo3 namespace: myns spec: containers: - image: nginx:1.14-alpine imagePullPolicy: IfNotPresent name: nginx hostNetwork: true [root@master01 manifests]# kubectl apply -f pod-demo3.yaml --kubeconfig=/etc/kubernetes/admin.conf pod/nginx-pod-demo3 created [root@master01 manifests]# kubectl get pod -n myns --kubeconfig=/etc/kubernetes/admin.conf NAME READY STATUS RESTARTS AGE nginx-pod-demo3 1/1 Running 0 20s [root@master01 manifests]#
提示:能夠看到使用system:master組上用戶的證書在myns名稱空間下就可以正常建立共享宿主機網絡名稱空間的pod;經過上面的示例能夠看到對應psp准入控制規則的設置是生效的;