K8S之准入控制


一、什么是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 啟用了對 cpumemory 的限制, 用戶必須指定這些值的需求使用量與限制使用量。否則,系統將會拒絕創建 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/


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM