理論+實操:K8S中的pod 資源限制

前言:
學習參考kubernetes官方文檔,以kubernetes爲準

pod是容器的集合,容器中的隱患(cpu、IO、MEM),在k8s中依然存在

官方文檔:https://kubernetes.io/docs/concepts/configuration/manage-compute-resources-container/

雲計算 兩大塊虛擬化

OpenStack ——創建虛擬硬件資源池——創建虛擬機實例

比如:vdisk 虛擬磁盤

容器—》容器編排—容器羣集管理 例如:docker—docker-compose-----kubernetes虛擬硬件 ---- 資源限制

一:pod和container的資源請求和限制

spec.containers[].resources.limits.cpu //cpu上限

spec.containers[].resources.limits.memory //內存上限

spec.containers[].resources.requests.cpu //創建時分配的基本CPU資源

spec.containers[].resources.requests.memory //創建時分配的基本內存資源

一種是最大上限,一種是基本分配

儘管只能在個別容器上指定請求和限制,但是我們可以方便地計算出 Pod 資源請求和限制。特定資源類型的Pod 資源請求/限制是 Pod 中每個容器的該類型的資源請求/限制的總和。

1.1 cpu的含義

CPU 資源的限制和請求以 cpu 爲單位。

Kubernetes 中的一個 cpu 等於:

  • 1 AWS vCPU
  • 1 GCP Core
  • 1 Azure vCore
  • 1 Hyperthread 在帶有超線程的裸機 Intel 處理器上

允許浮點數請求。具有 spec.containers[].resources.requests.cpu 爲 0.5 的容器保證了一半 CPU 要求 1 CPU的一半。表達式 0.1 等價於表達式 100m,可以看作 “100 millicpu”。有些人說成是“一百毫 cpu”,其實說的是同樣的事情。具有小數點(如 0.1)的請求由 API 轉換爲100m,精度不超過 1m。因此,可能會優先選擇 100m 的形式。

CPU 總是要用絕對數量,不可以使用相對數量;0.1 的 CPU 在單核、雙核、48核的機器中的意義是一樣的。

1.2 內存的含義

內存的限制和請求以字節爲單位。您可以使用以下後綴之一作爲平均整數或定點整數表示內存:E,P,T,G,M,K。您還可以使用兩個字母的等效的冪數:Ei,Pi,Ti ,Gi,Mi,Ki。例如,以下代表大致相同的值:

128974848, 129e6, 129M, 123Mi

1.3 舉例驗證

以下 Pod 有兩個容器。每個容器的請求爲 0.25 cpu 和 64MiB(226 字節)內存,每個容器的限制爲 0.5 cpu 和 128MiB 內存。您可以說該 Pod 請求 0.5 cpu 和 128 MiB 的內存,限制爲 1 cpu 和 256MiB 的內存。

apiVersion: v1
kind: Pod
metadata:
  name: frontend
spec:
  containers:
  - name: db
    image: mysql
    env:
    - name: MYSQL_ROOT_PASSWORD
      value: "password"
    resources:
      requests:
        memory: "64Mi"
        cpu: "250m"
      limits:
        memory: "128Mi"
        cpu: "500m"
  - name: wp
    image: wordpress
    resources:
      requests:
        memory: "64Mi"
        cpu: "250m"
      limits:
        memory: "128Mi"
        cpu: "500m"

1.4 具有資源請求的pod如何調度

當您創建一個 Pod 時,Kubernetes 調度程序將爲 Pod 選擇一個節點。

每個節點具有每種資源類型的最大容量:可爲 Pod 提供的 CPU 和內存量。

調度程序確保對於每種資源類型,調度的容器的資源請求的總和小於節點的容量。

注意,儘管節點上的實際內存或 CPU 資源使用量非常低,但如果容量檢查失敗,則調度程序仍然拒絕在該節點上放置 Pod。

當資源使用量稍後增加時,例如在請求率的每日峯值期間,這便可以防止節點上的資源短缺。

1.5 具有資源限制的pod如何運行

當 kubelet 啓動一個 Pod 的容器時,它會將 CPU 和內存限制傳遞到容器運行時。

當使用 Docker 時:

  • spec.containers[].resources.requests.cpu 的值將轉換成 millicore 值,這是個浮點數,並乘以 1024,這個數字中的較大者或 2 用作 docker run 命令中的 --cpu-shares 標誌的值。
  • spec.containers[].resources.limits.cpu 被轉換成 millicore 值。被乘以 100000 然後 除以 1000。這個數字用作 docker run 命令中的 --cpu-quota 標誌的值。[--cpu-quota ] 標誌被設置成了 100000,表示測量配額使用的默認100ms 週期。如果 [--cpu-cfs-quota] 標誌設置爲 true,則 kubelet 會強制執行 cpu 限制。從 Kubernetes 1.2 版本起,此標誌默認爲 true。

注意: 默認配額限制爲 100 毫秒。 CPU配額的最小單位爲 1 毫秒。

如果容器超過其內存限制,則可能會被終止。如果可重新啓動,則與所有其他類型的運行時故障一樣,kubelet 將重新啓動它。

如果一個容器超過其內存請求,那麼當節點內存不足時,它的 Pod 可能被逐出。

容器可能被允許也可能不被允許超過其 CPU 限制時間。但是,由於 CPU 使用率過高,不會被殺死。

1.6 pod處於pending狀態且時間顯示failedscheduling

如果調度器找不到任何該 Pod 可以匹配的節點,則該 Pod 將保持不可調度狀態,直到找到一個可以被調度到的位置。每當調度器找不到 Pod 可以調度的地方時,會產生一個事件,如下所示:

kubectl describe pod frontend | grep -A 3 Events
Events:
  FirstSeen LastSeen   Count  From          Subobject   PathReason      Message
  36s   5s     6      {scheduler }              FailedScheduling  Failed for reason PodExceedsFreeCPU and possibly others

上述示例中,由於節點上的 CPU 資源不足,名爲 “frontend” 的 Pod 將無法調度。由於內存不足(PodExceedsFreeMemory),類似的錯誤消息也可能會導致失敗。一般來說,如果有這種類型的消息而處於 pending 狀態,可以嘗試如下幾件事情:

  • 向集羣添加更多節點。
  • 終止不需要的 Pod,爲待處理的 Pod 騰出空間。
  • 檢查 Pod 所需的資源是否大於所有節點的資源。 例如,如果全部節點的容量爲cpu:1,那麼一個請求爲 cpu:1.1的 Pod 永遠不會被調度。

1.7 kubectl describe nodes 檢查節點容量分配和分配的數量

kubectl describe nodes e2e-test-node-pool-4lw4
Name:            e2e-test-node-pool-4lw4
[ ... lines removed for clarity ...]
Capacity:
 cpu:                               2
 memory:                            7679792Ki
 pods:                              110
Allocatable:
 cpu:                               1800m
 memory:                            7474992Ki
 pods:                              110
[ ... lines removed for clarity ...]
Non-terminated Pods:        (5 in total)
  Namespace    Name                                  CPU Requests  CPU Limits  Memory Requests  Memory Limits
  ---------    ----                                  ------------  ----------  ---------------  -------------
  kube-system  fluentd-gcp-v1.38-28bv1               100m (5%)     0 (0%)      200Mi (2%)       200Mi (2%)
  kube-system  kube-dns-3297075139-61lj3             260m (13%)    0 (0%)      100Mi (1%)       170Mi (2%)
  kube-system  kube-proxy-e2e-test-...               100m (5%)     0 (0%)      0 (0%)           0 (0%)
  kube-system  monitoring-influxdb-grafana-v4-z1m12  200m (10%)    200m (10%)  600Mi (8%)       600Mi (8%)
  kube-system  node-problem-detector-v0.1-fj7m3      20m (1%)      200m (10%)  20Mi (0%)        100Mi (1%)
Allocated resources:
  (Total limits may be over 100 percent, i.e., overcommitted.)
  CPU Requests    CPU Limits    Memory Requests    Memory Limits
  ------------    ----------    ---------------    -------------
  680m (34%)      400m (20%)    920Mi (12%)        1070Mi (14%)

在上面的輸出中,您可以看到如果 Pod 請求超過 1120m CPU 或者 6.23Gi 內存,節點將無法滿足。

通過查看 Pods 部分,您將看到哪些 Pod 佔用的節點上的資源。

Pod 可用的資源量小於節點容量,因爲系統守護程序使用一部分可用資源。 NodeStatusallocatable 字段給出了可用於 Pod 的資源量。 有關更多信息,請參閱官方文檔 節點可分配資源

可以將 資源配額 功能配置爲限制可以使用的資源總量。如果與 namespace 配合一起使用,就可以防止一個團隊佔用所有資源

1.8 容器被終止

容器可能因爲資源枯竭而被終止了。要查看容器是否因爲遇到資源限制而被殺死,請在相關的 Pod 上調用 kubectl describe pod

kubectl describe pod simmemleak-hra99
Name:                           simmemleak-hra99
Namespace:                      default
Image(s):                       saadali/simmemleak
Node:                           kubernetes-node-tf0f/10.240.216.66
Labels:                         name=simmemleak
Status:                         Running
Reason:
Message:
IP:                             10.244.2.75
Replication Controllers:        simmemleak (1/1 replicas created)
Containers:
  simmemleak:
    Image:  saadali/simmemleak
    Limits:
      cpu:                      100m
      memory:                   50Mi
    State:                      Running
      Started:                  Tue, 07 Jul 2015 12:54:41 -0700
    Last Termination State:     Terminated
      Exit Code:                1
      Started:                  Fri, 07 Jul 2015 12:54:30 -0700
      Finished:                 Fri, 07 Jul 2015 12:54:33 -0700
    Ready:                      False
    Restart Count:              5
Conditions:
  Type      Status
  Ready     False
Events:
  FirstSeen                         LastSeen                         Count  From                              SubobjectPath                       Reason      Message
  Tue, 07 Jul 2015 12:53:51 -0700   Tue, 07 Jul 2015 12:53:51 -0700  1      {scheduler }                                                          scheduled   Successfully assigned simmemleak-hra99 to kubernetes-node-tf0f
  Tue, 07 Jul 2015 12:53:51 -0700   Tue, 07 Jul 2015 12:53:51 -0700  1      {kubelet kubernetes-node-tf0f}    implicitly required container POD   pulled      Pod container image "k8s.gcr.io/pause:0.8.0" already present on machine
  Tue, 07 Jul 2015 12:53:51 -0700   Tue, 07 Jul 2015 12:53:51 -0700  1      {kubelet kubernetes-node-tf0f}    implicitly required container POD   created     Created with docker id 6a41280f516d
  Tue, 07 Jul 2015 12:53:51 -0700   Tue, 07 Jul 2015 12:53:51 -0700  1      {kubelet kubernetes-node-tf0f}    implicitly required container POD   started     Started with docker id 6a41280f516d
  Tue, 07 Jul 2015 12:53:51 -0700   Tue, 07 Jul 2015 12:53:51 -0700  1      {kubelet kubernetes-node-tf0f}    spec.containers{simmemleak}         created     Created with docker id 87348f12526a

Restart Count: 5 意味着 Pod 中的 simmemleak 容器被終止並重啓了五次。

可以使用 kubectl get pod 命令加上 -o go-template=... 選項來獲取之前終止容器的狀態。

kubectl get pod -o go-template='{{range.status.containerStatuses}}{{"Container Name: "}}{{.name}}{{"\r\nLastState: "}}{{.lastState}}{{end}}'  simmemleak-hra99
Container Name: simmemleak
LastState: map[terminated:map[exitCode:137 reason:OOM Killed startedAt:2015-07-07T20:58:43Z finishedAt:2015-07-07T20:58:43Z containerID:docker://0e4095bba1feccdfe7ef9fb6ebffe972b4b14285d5acdec6f0d3ae8a22fad8b2]]

可以看到容器因爲 reason:OOM killed 被終止,OOM 表示 Out Of Memory。

二:演示

2.1 編寫yaml文件

[root@master1 ~]# vim pod2.yaml
apiVersion: v1
kind: Pod
metadata:
  name: frontend
spec:
  containers: 
  #兩個容器,分別是名爲db的mysql,名爲wp的wordpress
  - name: db
    image: mysql
    env:
    - name: MYSQL_ROOT_PASSWORD
      value: "password"
    resources: 
    #資源管理
      requests:
      #請求資源
        memory: "64Mi"
        cpu: "250m"
      limits:
      #限制資源
        memory: "128Mi"
        cpu: "500m"
  - name: wp
    image: wordpress
    resources:
      requests:
        memory: "64Mi"
        cpu: "250m"
      limits:
        memory: "128Mi"
        cpu: "500m"

2.2 創建資源

[root@master1 ~]# kubectl apply -f pod2.yaml
pod/frontend created

2.3 查看pod具體事件

[root@master1 ~]# kubectl get pods
NAME                                READY   STATUS              RESTARTS   AGE
frontend                            0/2     ContainerCreating   0          45s
[root@master1 ~]# kubectl describe pod frontend		#這裏只截取事件
Events:
  Type     Reason     Age                From                      Message
  ----     ------     ----               ----                      -------
  Normal   Scheduled  79s                default-scheduler         Successfully assigned default/frontend to 192.168.247.143
  Normal   Pulling    58s                kubelet, 192.168.247.143  pulling image "wordpress"
  Normal   Pulled     26s                kubelet, 192.168.247.143  Successfully pulled image "wordpress"
  Normal   Pulling    25s (x2 over 78s)  kubelet, 192.168.247.143  pulling image "mysql"
  Normal   Started    25s                kubelet, 192.168.247.143  Started container
  Normal   Created    25s                kubelet, 192.168.247.143  Created container
  Normal   Pulled     24s (x2 over 58s)  kubelet, 192.168.247.143  Successfully pulled image "mysql"
  Normal   Created    23s (x2 over 58s)  kubelet, 192.168.247.143  Created container
  Normal   Started    23s (x2 over 58s)  kubelet, 192.168.247.143  Started container
  Warning  BackOff    6s                 kubelet, 192.168.247.143  Back-off restarting failed container


yaml文件有誤,但不影響驗證

2.4 查看node節點的docker

[root@node01 ~]# docker ps -a | grep wp
a99b989fb2a7        wordpress                                                             "docker-entrypoint.s…"   2 minutes ago       Up 2 minutes                                    k8s_wp_frontend_default_50ec30e1-94b3-11ea-a668-000c29db840b_0
[root@node01 ~]# docker ps -a | grep mysql
a5f2dccad7cb        mysql                                                                 "docker-entrypoint.s…"   5 seconds ago        Up 4 seconds                                    k8s_db_frontend_default_50ec30e1-94b3-11ea-a668-000c29db840b_4
a2bad2be413f        mysql                                                                 "docker-entrypoint.s…"   About a minute ago   Exited (1) 56 seconds ago                       k8s_db_frontend_default_50ec30e1-94b3-11ea-a668-000c29db840b_3

2.5 回到master,發現已經重啓四次

[root@master1 ~]# kubectl get pods -w
NAME                                READY   STATUS             RESTARTS   AGE
frontend                            1/2     CrashLoopBackOff   4          4m9s
frontend   2/2   Running   5     4m47s
frontend   1/2   OOMKilled   5     4m55s
frontend   1/2   CrashLoopBackOff   5     5m10s

2.6 查看pod所在node節點的描述信息

備註:從pod事件中可以知道pod在192.168.247.143node01上

[root@master1 ~]# kubectl describe node 192.168.247.143
Name:               192.168.247.143
Roles:              <none>
Labels:             beta.kubernetes.io/arch=amd64
                    beta.kubernetes.io/os=linux
                    kubernetes.io/hostname=192.168.247.143
Annotations:        node.alpha.kubernetes.io/ttl: 0
                    volumes.kubernetes.io/controller-managed-attach-detach: true
CreationTimestamp:  Thu, 30 Apr 2020 11:40:08 +0800
Taints:             <none>
Unschedulable:      false
Conditions:
  Type             Status  LastHeartbeatTime                 LastTransitionTime                Reason                       Message
  ----             ------  -----------------                 ------------------                ------                       -------
  OutOfDisk        False   Wed, 13 May 2020 08:55:30 +0800   Fri, 08 May 2020 13:03:43 +0800   KubeletHasSufficientDisk     kubelet has sufficient disk space available
  MemoryPressure   False   Wed, 13 May 2020 08:55:30 +0800   Fri, 08 May 2020 13:03:43 +0800   KubeletHasSufficientMemory   kubelet has sufficient memory available
  DiskPressure     False   Wed, 13 May 2020 08:55:30 +0800   Fri, 08 May 2020 13:03:43 +0800   KubeletHasNoDiskPressure     kubelet has no disk pressure
  PIDPressure      False   Wed, 13 May 2020 08:55:30 +0800   Thu, 30 Apr 2020 11:40:08 +0800   KubeletHasSufficientPID      kubelet has sufficient PID available
  Ready            True    Wed, 13 May 2020 08:55:30 +0800   Tue, 12 May 2020 08:40:28 +0800   KubeletReady                 kubelet is posting ready status
Addresses:
  InternalIP:  192.168.247.143
  Hostname:    192.168.247.143
Capacity:
 cpu:                2
 ephemeral-storage:  309307844Ki
 hugepages-1Gi:      0
 hugepages-2Mi:      0
 memory:             3861364Ki
 pods:               110
Allocatable:
 cpu:                2
 ephemeral-storage:  285058108559
 hugepages-1Gi:      0
 hugepages-2Mi:      0
 memory:             3758964Ki
 pods:               110
System Info:
 Machine ID:                 e7c72a193a404cf587718e10bd4e5533
 System UUID:                13744D56-2BA1-6509-242B-ED05BBAA67FF
 Boot ID:                    54684508-2c2f-4e1f-81c7-427c94c4c16b
 Kernel Version:             3.10.0-1062.el7.x86_64
 OS Image:                   CentOS Linux 7 (Core)
 Operating System:           linux
 Architecture:               amd64
 Container Runtime Version:  docker://19.3.8
 Kubelet Version:            v1.12.3
 Kube-Proxy Version:         v1.12.3
Non-terminated Pods:         (4 in total)
  Namespace                  Name                                 CPU Requests  CPU Limits  Memory Requests  Memory Limits
  ---------                  ----                                 ------------  ----------  ---------------  -------------
  default                    frontend                             500m (25%)    1 (50%)     128Mi (3%)       256Mi (6%)
  default                    my-tomcat-6cbc7c4d65-hdmhc           0 (0%)        0 (0%)      0 (0%)           0 (0%)
  default                    nginx-deployment-78cdb5b557-f2hx2    0 (0%)        0 (0%)      0 (0%)           0 (0%)
  default                    pod1                                 0 (0%)        0 (0%)      0 (0%)           0 (0%)
Allocated resources:
  (Total limits may be over 100 percent, i.e., overcommitted.)
  Resource  Requests    Limits
  --------  --------    ------
  cpu       500m (25%)  1 (50%)
  memory    128Mi (3%)  256Mi (6%)
Events:     <none>
[root@master1 ~]# 

2.7 node的限額信息

在這裏插入圖片描述

百分比是佔用當前硬件的百分比,pod是k8s的最小執行單位

對pod的資源限制參數是pod內容器的限制之和

命名空間在不指定的情況下默認命名空間

[root@master1 ~]# kubectl get ns
NAME          STATUS   AGE
default       Active   12d
kube-public   Active   12d
kube-system   Active   12d
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章