一、什么是K8S之准入控制
就是在創建資源經過身份驗證之后,kube-apiserver在數據寫入etcd之前做一次攔截,然后對資源進行更改、判斷正確性等操作。
一個 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 進行驗證。
能夠使用限制范圍創建的策略示例有:
- 在一個有兩個節點,8 GiB 內存與16個核的集群中,限制一個命名空間的 Pod 申請 100m 單位,最大 500m 單位的 CPU,以及申請 200Mi,最大 600Mi 的內存。
- 為 spec 中沒有 cpu 和內存需求值的 Container 定義默認 CPU 限制值與需求值 150m,內存默認需求值 300Mi。
在命名空間的總限制值小於 Pod 或 Container 的限制值的總和的情況下,可能會產生資源競爭。 在這種情況下,將不會創建 Container 或 Pod。
競爭和對 LimitRange 的改變都不會影響任何已經創建了的資源
四、配置LimitRange(對Pod進行配置、限額)
4.1、配置 CPU 最小和最大約束
# 創建一個命名空間,以便本練習中創建的資源和集群的其余資源相隔離
[root@k8s-master01 ~]# kubectl create namespace constraints-cpu-example
namespace/constraints-cpu-example created
# 1、LimitRange 的配置文件
[root@k8s-master01 ~]# cat cpu-constraints.yaml
apiVersion: v1
kind: LimitRange
metadata:
name: cpu-min-max-demo-lr
spec:
limits:
- max:
cpu: "800m"
min:
cpu: "200m"
type: Container
# 2、創建 LimitRange:
[root@k8s-master01 ~]# kubectl apply -f cpu-constraints.yaml -n constraints-cpu-example
limitrange/cpu-min-max-demo-lr created
# 3、查看結果
# 輸出結果顯示 CPU 的最小和最大限制符合預期。但需要注意的是,盡管你在 LimitRange 的配置文件中你沒有聲明默認值,默認值也會被自動創建。
[root@k8s-master01 ~]# kubectl get limitrange cpu-min-max-demo-lr --output=yaml --namespace=constraints-cpu-example
# 只列出關鍵的
spec:
limits:
- default:
cpu: 800m
defaultRequest:
cpu: 800m
max:
cpu: 800m
min:
cpu: 200m
type: Container
現在不管什么時候在 constraints-cpu-example 命名空間中創建容器,Kubernetes 都會執行下面這些步驟:
- 如果容器沒有聲明自己的 CPU 請求和限制,將為容器指定默認 CPU 請求和限制。
- 核查容器聲明的 CPU 請求確保其大於或者等於 200 millicpu。
- 核查容器聲明的 CPU 限制確保其小於或者等於 800 millicpu。
流程就是說,我們創建了一個namespace=constraints-cpu-example的名稱空間,然后在這個名稱空間創建了一個LimitRange。然后現在不管什么時候在 constraints-cpu-example 命名空間中創建容器,Kubernetes 都會執行上面那些步驟!我們創建的LimitRange對這個namespace=constraints-cpu-example的名稱空間里面起低調Pod都起了限制的作用
4.2、配置命名空間的最小和最大內存約束
LimitRange 的配置文件
apiVersion: v1
kind: LimitRange
metadata:
name: mem-min-max-demo-lr
spec:
limits:
- max:
memory: 1Gi
min:
memory: 500Mi
type: Container
# 輸出顯示預期的最小和最大內存約束。 但請注意,即使你沒有在 LimitRange 的配置文件中指定默認值,也會自動創建它們。
limits:
- default:
memory: 1Gi
defaultRequest:
memory: 1Gi
max:
memory: 1Gi
min:
memory: 500Mi
type: Container
現在,只要在 constraints-mem-example 命名空間中創建容器,Kubernetes 就會執行下面的步驟:
- 如果 Container 未指定自己的內存請求和限制,將為它指定默認的內存請求和限制。
- 驗證 Container 的內存請求是否大於或等於500 MiB。
- 驗證 Container 的內存限制是否小於或等於1 GiB。
4.3、配置 CPU 最小和最大約束
LimitRange 的配置文件:
apiVersion: v1
kind: LimitRange
metadata:
name: cpu-min-max-demo-lr
spec:
limits:
- max:
cpu: "800m"
min:
cpu: "200m"
type: Container
# 輸出結果顯示 CPU 的最小和最大限制符合預期。但需要注意的是,盡管你在 LimitRange 的配置文件中你沒有聲明默認值,默認值也會被自動創建。
limits:
- default:
cpu: 800m
defaultRequest:
cpu: 800m
max:
cpu: 800m
min:
cpu: 200m
type: Container
現在不管什么時候在 constraints-cpu-example 命名空間中創建容器,Kubernetes 都會執行下面這些步驟:
- 如果容器沒有聲明自己的 CPU 請求和限制,將為容器指定默認 CPU 請求和限制。
- 核查容器聲明的 CPU 請求確保其大於或者等於 200 millicpu。
- 核查容器聲明的 CPU 限制確保其小於或者等於 800 millicpu。
說明: 當創建 LimitRange 對象時,你也可以聲明大頁面和 GPU 的限制。 當這些資源同時聲明了 'default' 和 'defaultRequest' 參數時,兩個參數值必須相同。
五、ResourceQuot(對名稱空間進行配置、限額)
5.1、配置內存和 CPU 配額
# 1、創建命名空間,以便本練習中創建的資源和集群的其余部分相隔離。
[root@k8s-master01 ~]# kubectl create namespace quota-mem-cpu-example
namespace/quota-mem-cpu-example created
# 2、創建 ResourceQuota
[root@k8s-master01 ~]# vim quota-mem-cpu.yaml
apiVersion: v1
kind: ResourceQuota
metadata:
name: mem-cpu-demo
spec:
hard:
requests.cpu: "1"
requests.memory: 1Gi
limits.cpu: "2"
limits.memory: 2Gi
# 3、創建 ResourceQuota
[root@k8s-master01 ~]# kubectl apply -f quota-mem-cpu.yaml -n quota-mem-cpu-example
resourcequota/mem-cpu-demo created
# 4、查看 ResourceQuota 詳情:
[root@k8s-master01 ~]# kubectl get resourcequota mem-cpu-demo --namespace=quota-mem-cpu-example --output=yaml
# 跟我們配置的一樣
spec:
hard:
limits.cpu: "2"
limits.memory: 2Gi
requests.cpu: "1"
requests.memory: 1Gi
ResourceQuota 在 quota-mem-cpu-example 命名空間中設置了如下要求:
- 每個容器必須有內存請求和限制,以及 CPU 請求和限制。
- 所有容器的內存請求總和不能超過1 GiB。
- 所有容器的內存限制總和不能超過2 GiB。
- 所有容器的 CPU 請求總和不能超過1 cpu。
- 所有容器的 CPU 限制總和不能超過2 cpu。
也就是在名稱空間 quota-mem-cpu-example種創建Pod,必須遵守我們在上面定義的要求
5.1.1、創建 Pod
cat > quota-mem-cpu-pod.yaml << EFO
apiVersion: v1
kind: Pod
metadata:
name: quota-mem-cpu-demo
spec:
containers:
- name: quota-mem-cpu-demo-ctr
image: nginx
resources:
limits:
memory: "800Mi"
cpu: "800m"
requests:
memory: "600Mi"
cpu: "400m"
EFO
# create Pod
kubectl apply -f quota-mem-cpu-pod.yaml --namespace=quota-mem-cpu-example
# 查看配額,能看到用了多少
[root@k8s-master01 ~]# kubectl get resourcequota mem-cpu-demo --namespace=quota-mem-cpu-example --output=yaml
spec:
hard:
limits.cpu: "2"
limits.memory: 2Gi
requests.cpu: "1"
requests.memory: 1Gi
status:
hard:
limits.cpu: "2"
limits.memory: 2Gi
requests.cpu: "1"
requests.memory: 1Gi
used:
limits.cpu: 800m
limits.memory: 800Mi
requests.cpu: 400m
requests.memory: 600Mi
5.1.2、嘗試創建第二個 Pod
[root@k8s-master01 ~]# cat quota-mem-cpu-pod-2.yaml
apiVersion: v1
kind: Pod
metadata:
name: quota-mem-cpu-demo-2
spec:
containers:
- name: quota-mem-cpu-demo-2-ctr
image: redis
resources:
limits:
memory: "1Gi"
cpu: "800m"
requests:
memory: "700Mi"
cpu: "400m"
# 嘗試創建
[root@k8s-master01 ~]# kubectl apply -f quota-mem-cpu-pod-2.yaml --namespace=quota-mem-cpu-example
Error from server (Forbidden): error when creating "quota-mem-cpu-pod-2.yaml": pods "quota-mem-cpu-demo-2" is forbidden: exceeded quota: mem-cpu-demo, requested: requests.memory=700Mi, used: requests.memory=600Mi, limited: requests.memory=1Gi
# 第二個 Pod 不能被創建成功。輸出結果顯示創建第二個 Pod 會導致內存請求總量超過內存請求配額。
# 刪除你的命名空間:
kubectl delete namespace quota-mem-cpu-example
5.2、配置命名空間下 Pod 配額
如何配置一個命名空間下可運行的 Pod 個數配額?
# 1、創建一個命名空間
kubectl create namespace quota-pod-example
# 2、創建 ResourceQuota,指定改ns只可以創建2個pod
apiVersion: v1
kind: ResourceQuota
metadata:
name: pod-demo
spec:
hard:
pods: "2"
# 3、apply ResourceQuota
kubectl apply -f quota-pod.yaml --namespace=quota-pod-example
# 4、查看資源配額的詳細信息:
kubectl get resourcequota pod-demo --namespace=quota-pod-example --output=yaml
# 5、創建Deployment,且replicas是3,那么肯定只有2個Pod能正常運行!自己去試試吧
apiVersion: apps/v1
kind: Deployment
metadata:
name: pod-quota-demo
spec:
selector:
matchLabels:
purpose: quota-demo
replicas: 3
template:
metadata:
labels:
purpose: quota-demo
spec:
containers:
- name: pod-quota-demo
image: nginx
中文官網文檔:https://kubernetes.io/zh/docs/concepts/policy/limit-range/