Kubernetes准入控制器


k8s的整体认证过程分为3步,本别是认证授权准入控制。认证和授权都是工作在短路模式,而准入控制是非短路模式,但拥有一票否决权力,如果其中任何一个准入插件拒绝那其操作就无法执行,但是它会继续向下执行直到检查完每一个准入插件以确保能分析出有哪些步骤发生错误。

k8s支持的准入控制器有数十种之多,但是有3个非常关键:

  • limitranger: 为Pod添加默认的计算资源需求和计算资源限制;以及存储资源需求和存储资源限制;支持分别在容器和Pod级别进行限制;
  • resourcequota:限制资源数量,限制计算资源总量,存储资源总量;资源类型名称ResourceQuota
  • podsecuritpolicy:在集群级别限制用户能够在Pod上可配置使用的securityContext

limitranger资源介绍

limitrange与此前在pod上做资源限制的配置方式相同,所不同的是它是在名称空间上做的所有设定。

如果pod没有定义资源限制,则会继承该名称空间上的 limitrange 中的定义。

示例

1.创建一个limitrange资源清单

root@k8s-master01:~/yaml/chapter09# vim limitrange-demo.yaml
apiVersion: v1
kind: LimitRange
metadata:
  name: core-resource-limits
  namespace: dev
spec:
  limits:
  - type: Pod
    max:
      cpu: "4"
      memory: "4Gi"
    min:
      cpu: "500m"
      memory: "16Mi"
  - type: Container
    max:
      cpu: "4"
      memory: "1Gi"
    min:
      cpu: "100m"
      memory: "4Mi"
    default:
      cpu: "2"
      memory: "512Mi"
    defaultRequest:
      cpu: "500m"
      memory: "64Mi"
    maxLimitRequestRatio:    
      cpu: "4"       # 此参数表示下阈值与上阈值之间的倍数。使用了此参数,default和defaultRequest只需定义一个即可。系统会自动计算出另一个值。
  - type: PersistentVolumeClaim
    max:
      storage: "10Gi"
    min:
      storage: "1Gi"
    default:
      storage: "5Gi"
    defaultRequest:
      storage: "1Gi"
    maxLimitRequestRatio:
      storage: "5"

2.应用此资源清单

root@k8s-master01:~/yaml/chapter09# kubectl apply -f limitrange-demo.yaml
limitrange/core-resource-limits created

# 显示limitrange的详细信息
root@k8s-master01:~/yaml/chapter09# kubectl describe limitranges core-resource-limits  -n dev
Name:                  core-resource-limits
Namespace:             dev
Type                   Resource  Min   Max   Default Request  Default Limit  Max Limit/Request Ratio
----                   --------  ---   ---   ---------------  -------------  -----------------------
Pod                    cpu       500m  4     -                -              -
Pod                    memory    16Mi  4Gi   -                -              -
Container              cpu       100m  4     500m             2              4
Container              memory    4Mi   1Gi   64Mi             512Mi          -
PersistentVolumeClaim  storage   1Gi   10Gi  1Gi              5Gi            5

3.手动创建pod测试1.

root@k8s-master01:~/yaml/chapter09# kubectl run test-pod-$RANDOM --image="ikuberentes/demoapp:v1.0" -n dev
pod/test-pod-12395 created

# 查看其yaml信息
root@k8s-master01:~/yaml/chapter09# kubectl get pod test-pod-12395 -n dev -o yaml | kubectl-neat
apiVersion: v1
kind: Pod
metadata:
  annotations:
    kubernetes.io/limit-ranger: 'LimitRanger plugin set: cpu, memory request for container
      test-pod-12395; cpu, memory limit for container test-pod-12395'
  labels:
    run: test-pod-12395
  name: test-pod-12395
  namespace: dev
spec:
  containers:
  - image: ikuberentes/demoapp:v1.0
    name: test-pod-12395
    resources:                            # 使用手动创建的pod其resources被自动定义了
      limits:
        cpu: "2"
        memory: 512Mi
      requests:
        cpu: 500m
        memory: 64Mi
  ......

3.手动创建pod测试2

root@k8s-master01:~/yaml/chapter09# kubectl run testpod-$RANDOM --image="ikubernetes/demoapp:v1.0" -n dev --limits='cpu=2,memory=1Gi' --requests='cpu=1,memory=8Mi'
Flag --limits has been deprecated, has no effect and will be removed in the future.
Flag --requests has been deprecated, has no effect and will be removed in the future.
Error from server (Forbidden): pods "testpod-20703" is forbidden: minimum memory usage per Pod is 16Mi, but request is 8388608

# 没有创建成功。内存小了

ResourceQuota资源的作用是什么

ResourceQuota 资源可限制名称空间中处于非终止状态的所有Pod对象的计算资源需求及计算资源限制总量。

  • cpu或requests.cpu:CPU资源相关请求的总量限额;
  • memory或requests.memory:内存资源相关请求的总量限额;
  • limits.cpu:CPU资源相关限制的总量限额;
  • limits.memory:内存资源相关限制的总量限额;

ResourceQuota 资源还支持为本地名称空间中的PVC存储资源的需求总量和限制总量提供限额,它能够分别从名称空间中的全部PVC、隶属于特定存储类的PVC以及基于本地临时存储的PVC三个类别分别进行定义。

  • requests.storage:所有PVC存储需求的总量限额;空间限制;
  • persistentvolumeclaims:可以创建的PVC总数限额;数量限制;
  • <storage-class-name>.storageclass.storage.k8s.io/requests.storage:特定的存储类上可使用的所有PVC存储需求的总量限额;
  • <storage-class-name>.storageclass.storage.k8s.io/persistentvolumeclaims:特定的存储类上可使用的PVC总数限额;
  • requests.ephemeral-storage:所有Pod可以使用的本地临时存储资源的requets总量;
  • limits.ephemeral-storage:所有Pod可用的本地临时存储资源的limits总量。

在v1.9版本之前的Kubernetes系统上,ResourceQuota 仅支持在有限的几种资源集上设定对象计数配额,例如 pods 、 services 和 configmaps 等,而自v1.9版本起开始支持以count/<resource>.<group>的格式支持对所有资源类型对象的计数配额,例如count/deployments.appscount/deployments.extensionscount/services等。

示例

1.RescoureQuota资源清单

root@k8s-master01:~/yaml/chapter09# vim resourcequota-demo.yaml
apiVersion: v1
kind: ResourceQuota
metadata:
  name: resourcequota-demo
  namespace: dev
spec:
  hard:
    pods: "5"
    count/services: "5"
    count/configmaps: "5"
    count/secrets: "5"
    requests.cpu: "2"
    requests.memory: "4Gi"
    limits.cpu: "4"
    limits.memory: "8Gi"
    count/deployments.apps: "2"
    count/statefulsets.apps: "2"
    persistentvolumeclaims: "6"
    requests.storage: "20Gi"
    longhorn.storageclass.storage.k8s.io/requests.storage: "20Gi"
    longhorn.storageclass.storage.k8s.io/persistentvolumeclaims: "6"

2.应用资源清单

root@k8s-master01:~/yaml/chapter09# kubectl apply -f resourcequota-demo.yaml
resourcequota/resourcequota-demo created

# 查看dev名称空间下resourcequotas的详细信息
root@k8s-master01:~/yaml/chapter09# kubectl describe resourcequotas -n dev resourcequota-demo
Name:                                                        resourcequota-demo
Namespace:                                                   dev
Resource                                                     Used   Hard
--------                                                     ----   ----
count/configmaps                                             1      5
count/deployments.apps                                       0      2
count/secrets                                                3      5
count/services                                               1      5
count/statefulsets.apps                                      0      2
limits.cpu                                                   2      4
limits.memory                                                512Mi  8Gi
longhorn.storageclass.storage.k8s.io/persistentvolumeclaims  0      6
longhorn.storageclass.storage.k8s.io/requests.storage        0      20Gi
persistentvolumeclaims                                       0      6
pods                                                         1      5
requests.cpu                                                 500m   2
requests.memory                                              64Mi   4Gi
requests.storage                                             0      20Gi

PodSecurityPolicy是什么

PodSecurityPolicy 是用来在集群级别限制用户能够在Pod上可配置使用的 securityContext

资源清单定义格式如下

apiVersion: policy/v1beta1  # PSP资源所属的API群组及版本
kind: PodSecurityPolicy  # 资源类型标识
metadata:
  name <string>  # 资源名称
spec:  
  allowPrivilegeEscalation  <boolean>  # 是否允许权限升级
  allowedCSIDrivers <[]Object>  #内联CSI驱动程序列表,必须在Pod规范中显式定义
  allowedCapabilities <[]string>  # 允许使用的内核能力列表,“*”表示all
  allowedFlexVolumes <[]Object>  # 允许使用的Flexvolume列表,空值表示“all
  allowedHostPaths <[]Object>  # 允许使用的主机路径列表,空值表示all
  allowedProcMountTypes <[]string> # 允许使用的ProcMountType列表,空值表示默认
  allowedUnsafeSysctls <[]string> # 允许使用的非安全sysctl参数,空值表示不允许
  defaultAddCapabilities  <[]string>  # 默认即添加到Pod对象的内核能力,可被drop
  defaultAllowPrivilegeEscalation <boolean> # 是否默认允许内核权限升级
  forbiddenSysctls  <[]string> # 禁止使用的sysctl参数,空表示不禁用
  fsGroup <Object>  # 允许在SecurityContext中使用的fsgroup,必选字段
    rule <string>  # 允许使用的FSGroup的规则,支持RunAsAny和MustRunAs
    ranges <[]Object> # 允许使用的组ID范围,需要与MustRunAs规则一同使用
      max  <integer>  # 最大组ID号
      min  <integer>  # 最小组ID号
  hostIPC <boolean> # 是否允许Pod使用hostIPC
  hostNetwork <boolean> # 是否允许Pod使用hostNetwork
  hostPID <boolean> # 是否允许Pod使用hostPID
  hostPorts <[]Object>  # 允许Pod使用的主机端口暴露其服务的范围
    max  <integer>  # 最大端口号,必选字段
    min  <integer>  # 最小端口号,必选字段
  privileged  <boolean>  # 是否允许运行特权Pod
  readOnlyRootFilesystem  <boolean>  # 是否设定容器的根文件系统为“只读”
  requiredDropCapabilities <[]string> # 必须要禁用的内核能力列表  
  runAsGroup  <Object>  # 允许Pod在runAsGroup中使用的值列表,未定义表示不限制
  runAsUser <Object> # 允许Pod在runAsUser中使用的值列表,必选字段
    rule <string>  # 支持RunAsAny、MustRunAs和MustRunAsNonRoot
    ranges <[]Object> # 允许使用的组ID范围,需要跟“MustRunAs”规则一同使用
      max  <integer>  # 最大组ID号
      min  <integer>  # 最小组ID号
  runtimeClass <Object> # 允许Pod使用的运行类,未定义表示不限制
    allowedRuntimeClassNames <[]string> # 可使用的runtimeClass列表,“*”表示all
    defaultRuntimeClassName <string> # 默认使用的runtimeClass
  seLinux <Object> # 允许Pod使用的selinux标签,必选字段
    rule <string>  # MustRunAs表示使用seLinuxOptions定义的值;RunAsAny表示可使用任意值
    seLinuxOptions  <Object>  # 自定义seLinux选项对象,与MustRunAs协作生效
  supplementalGroups  <Object> # 允许Pod在SecurityContext中使用附加组,必选字段
  volumes <[]string>  # 允许Pod使用的存储卷插件列表,空表示禁用,“*”表示全部
注:由于psp的规则过于严格,一旦启用将会导致k8s上的pod寸步难行,默认k8s没有启用psp准入控制器。

如何启用PSP

kubeadm部署的k8s需要修改其静态pod的配置文件/etc/kubernetes/manifests/kube-apiserver.yaml ,在kube-apiserver命令中添加--enable-admission-plugins PodSecurityPolicy

但是需要注意一旦加入此参数就意味着psp已经启动,其将会导致所有的pod都无法运行。因为启用了psp控制器但未定义任何psp资源,那就意味着任何pod运行都会被拒绝,包括API Server自身都有可能被拒绝,因此启用psp之前需要先创建资源。 且psp创建完毕后还需要对其进行用户的绑定和授权。