准入控制
一、什么是K8S之准入控制
就是在创建资源经过身份验证之后,kube-apiserver在数据写入etcd之前做一次拦截,然后对资源进行更改、判断正确性等操作。
- LimitRange,ResourceQuota
目的:能控制特定命名空间中的资源使用量,最终实现集群的公平使用和成本的控制
- LimitRange:为Pod添加默认的计算资源需求和计算资源限制;以及存储资源需求和存储资源限制;
支持分别在容器和Pod级别进行限制;
比如:指定名称空间下每个Pod CPU、内存的最低最高额度 - ResourceQuota:限制资源数量,限制计算资源总量,存储资源总量;
比如:指定名称空间下,只允许创建Pod、svc的数量, 所有Pod CPU、内存的最低最高额度
- 需要实现的功能如下:
限制运行状态的Pod的计算资源用量
限制持久存储卷的数量以控制对存储的访问
限制负载均衡器的数量以控制成本
防止滥用网络端口
提供默认的计算资源Requests以便于系统做出更优化的调度
- 一个 LimitRange(限制范围) 对象提供的限制能够做到:
在一个命名空间中实施对每个 Pod 或 Container 最小和最大的资源使用量的限制。
在一个命名空间中实施对每个 PersistentVolumeClaim 能申请的最小和最大的存储空间大小的限制。
在一个命名空间中实施对一种资源的申请值和限制值的比值的控制。
设置一个命名空间中对计算资源的默认申请/限制值,并且自动的在运行时注入到多个 Container 中。
二、启用 LimitRang
对 LimitRange 的支持自 Kubernetes 1.10 版本默认启用。
LimitRange 支持在很多 Kubernetes 发行版本中也是默认启用的。
LimitRange 的名称必须是合法的 DNS 子域名。
三、限制范围总览
管理员在一个命名空间内创建一个 LimitRange 对象。
用户在命名空间内创建 Pod ,Container 和 PersistentVolumeClaim 等资源。
LimitRanger 准入控制器对所有没有设置计算资源需求的 Pod 和 Container 设置默认值与限制值, 并跟踪其使用量以保证没有超出命名空间中存在的任意 LimitRange 对象中的最小、最大资源使用量以及使用量比值。
若创建或更新资源(Pod、 Container、PersistentVolumeClaim)违反了 LimitRange 的约束, 向 API 服务器的请求会失败,并返回 HTTP 状态码 403 FORBIDDEN 与描述哪一项约束被违反的消息。
若命名空间中的 LimitRange 启用了对 cpu 和 memory 的限制, 用户必须指定这些值的需求使用量与限制使用量。否则,系统将会拒绝创建 Pod。
LimitRange 的验证仅在 Pod 准入阶段进行,不对正在运行的 Pod 进行验证
示例1: 创建LimitRange准入控制策略
- 对Pod、容器、PVC等资源进行限制
[root@k8s-master authfiles]# cat limitrange-demo.yaml
apiVersion: v1
kind: LimitRange
metadata:
name: core-resource-limits
namespace: dev #名字空间级别资源 对整个名额空间生效
spec:
limits:
- type: Pod #对Pod限制
max:
cpu: "4" #CPU最大不能超过4核
memory: "4Gi" #内存不能超过4G
min:
cpu: "500m" #CPU最小不能小于500m
memory: "16Mi" #内存不能小于16M
- type: Container #对容器作限制
max:
cpu: "4"
memory: "1Gi"
min:
cpu: "100m"
memory: "4Mi"
default: #上阈值 #如果容器中没有做requests或limits作限制,则附加的默认值
cpu: "2"
memory: "512Mi"
defaultRequest: #下阈值
cpu: "500m"
memory: "64Mi"
maxLimitRequestRatio: #最大限制请求比率 上阈值/下阈值 也可以用倍数做限制
cpu: "4"
- type: PersistentVolumeClaim #对PV做限制
max:
storage: "10Gi"
min:
storage: "1Gi"
default:
storage: "5Gi"
defaultRequest:
storage: "1Gi"
maxLimitRequestRatio: #没有下阈值 也可以用倍数做限制
storage: "5"
- 创建LimitRange策略
[root@k8s-master authfiles]# kubectl apply -f limitrange-demo.yaml
limitrange/core-resource-limits created
[root@k8s-master authfiles]# kubectl get limitrange -n dev
NAME CREATED AT
core-resource-limits 2021-08-25T02:29:04Z
[root@k8s-master authfiles]# kubectl get pod -n dev
NAME READY STATUS RESTARTS AGE
deployment-demo-fb544c5d8-4jvgh 1/1 Running 0 16h
deployment-demo-fb544c5d8-7fq8f 1/1 Running 0 16h
deployment-demo-fb544c5d8-hdsz4 1/1 Running 0 16h
deployment-demo-fb544c5d8-qq7mp 1/1 Running 0 16h
[root@k8s-master authfiles]# kubectl describe limitrange 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 memory 4Mi 1Gi 64Mi 512Mi -
Container cpu 100m 4 500m 2 4
PersistentVolumeClaim storage 1Gi 10Gi 1Gi 5Gi 5
- 验证测试策略是否生效
[root@k8s-master authfiles]# kubectl run testpod-$RANDOM --image="ikubernetes/demoapp:v1.0" -n dev
pod/testpod created
[root@k8s-master authfiles]# kubectl get pod -n dev
NAME READY STATUS RESTARTS AGE
testpod-1017 1/1 Running 0 93s
[root@k8s-master authfiles]# kubectl get pods testpod -n dev -o yaml
...
spec:
containers:
- image: kubernetes/demoapp:v1.0
imagePullPolicy: IfNotPresent
name: testpod
resources: #默认值
limits:
cpu: "2" #最高2核
memory: 512Mi
requests:
cpu: 500m #最低500m
memory: 64Mi
- 创建小于内存限制的Pod 创建失败
[root@k8s-master authfiles]# kubectl run testpod-$RANDOM --image="ikubernetes/demoapp:v1.0" -n dev --limits='cpu=2,memory=1Gi' --requests='cpu=1,memory=8Mi'
Error from server (Forbidden): pods "testpod-10340" 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:内存资源相关限制的总量限额;
- Rescurcebuota资源还支持为本地名称空间中的PVC存储资源的需求总量和限制总量提供限额,它能够分别从名称空间中的全部PVC、隶属于特定存储类的PVC以及基于本地临时存储的PVC三个类别分别进行定义。
- requests.storage:所有PVC存储需求的总量限额;空间限制;
- persistentvolumeclaims:可以创建的PVC总数限额;数量限制;
.storageclass.storage.k8s.io/requests.storage:特定的存储类上可使用的所有PVC存储需求的总量限额; .storageclass.storage.k8s.io/persistentvolumeclaims:特定的存储类上可使用的PVC总数限额; - requests.ephemeral-storage:所有Pod可以使用的本地临时存储资源的requets总量;
- limits.ephemeral-storage:所有Pod可用的本地临时存储资源的limits总量。
示例2:创建ResourceQuota准入控制策略
[root@k8s-master authfiles]# cat resourcequota-demo.yaml
apiVersion: v1
kind: ResourceQuota
metadata:
name: resourcequota-demo
namespace: dev
spec:
hard :
pods: "5" #Pod总量
count/services: "5" #svc总量
count/configmaps: "5"
count/secrets: "5"
count/cronjobs.batch: "2"
requests.cpu: "2" #cpu下阈值总量
requests.memory: "4Gi"
limits.cpu: "4" #cpu上阈值总量
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"
[root@k8s-master authfiles]# kubectl apply -f resourcequota-demo.yaml
resourcequota/resourcequota-demo created
[root@k8s-master authfiles]# kubectl get ResourceQuota -n dev
NAME AGE REQUEST LIMIT
resourcequota-demo 33s count/configmaps: 0/5, count/cronjobs.batch: 0/2, count/deployments.apps: 0/2, count/secrets: 3/5, count/services: 0/5, count/statefulsets.apps: 0/2, 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 limits.cpu: 2/4, limits.memory: 512Mi/8Gi
- 验证测试策略是否生效
[root@k8s-master authfiles]# kubectl describe resourcequota resourcequota-demo -n dev
Name: resourcequota-demo
Namespace: dev
Resource Used Hard
-------- ---- ----
count/configmaps 0 5
count/cronjobs.batch 0 2
count/deployments.apps 0 2
count/secrets 3 5
count/services 0 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
[root@k8s-master authfiles]# kubectl run testpod-$RANDOM --image="ikubernetes/demoapp:v1.0" -n dev
pod/testpod-10678 created
[root@k8s-master authfiles]# kubectl describe resourcequota resourcequota-demo -n dev
Name: resourcequota-demo
Namespace: dev
Resource Used Hard
-------- ---- ----
count/configmaps 0 5
count/cronjobs.batch 0 2
count/deployments.apps 0 2
count/secrets 3 5
count/services 0 5
count/statefulsets.apps 0 2
limits.cpu 4 4 #配额已使用完 无法在创建Pod
limits.memory 1Gi 8Gi
longhorn.storageclass.storage.k8s.io/persistentvolumeclaims 0 6
longhorn.storageclass.storage.k8s.io/requests.storage 0 20Gi
persistentvolumeclaims 0 6
pods 2 5
requests.cpu 1 2
requests.memory 128Mi 4Gi
requests.storage 0 20Gi
[root@k8s-master authfiles]# kubectl run testpod-$RANDOM --image="ikubernetes/demoapp:v1.0" -n dev
Error from server (Forbidden): pods "testpod-30200" is forbidden: exceeded quota: resourcequota-demo, requested: limits.cpu=2, used: limits.cpu=4, limited: limits.cpu=4