容器編排系統之Pod生命週期、健康/就緒狀態探測以及資源限制
前文我們瞭解了在k8s上的資源標籤、標籤選擇器以及資源註解相關話題,回顧請參考https://www.cnblogs.com/qiuhom-1874/p/14141080.html;今天我們來聊下k8s上的核心資源pod生命週期、健康/就緒狀態探測以及pod資源限制相關話題;
1、Pod生命週期
pod生命週期是指在pod開始建立到pod退出所消耗的時間範圍,我們把開始到結束的這段時間範圍就叫做pod的生命週期;其大概過程如下圖所示
提示:上圖主要描述了一個pod從建立到退出,中間這段時間經歷的過程;從大的方向上看,pod生命週期分兩個階段,第一階段是初始化容器,第二階段是主容器的整個生命週期;其中對於主容器來來說,它的生命週期有分了三個階段,第一階段是執行post start hook,這個階段是主容器執行之後立即需要做的事;第二階段是主容器正常執行的階段,在這個階段中,我們可以定義對容器的健康狀態檢查和就緒狀態檢查;第三階段是執行pre stop hook,這個階段主要做容器即將退出前需要做的事;這裡需要注意對於初始化容器來說,一個pod中可以定義多個初始化容器,他們必須是序列執行,只有當所有的初始化容器執行完後,對應的主容器才會啟動;對於對容器的健康狀態檢查和就緒狀態檢查,我們也可以定義開始檢查的延遲時長;因為有些容器存在容器顯示running狀態,但內部程式還沒有初始化,如果立即做健康狀態檢查,可能存在健康狀態為不健康,從而導致容器重啟的狀況;
2、Pod建立過程
提示:首先使用者通過客戶端工具將請求提交給apiserver,apiserver收到使用者的請求以後,它會嘗試將使用者提交的請求內容存進etcd中,etcd存入完成後就反饋給apiserver寫入資料完成,此時apiserver就返回客戶端,說某某資源已經建立;隨後apiserver要傳送一個watch訊號給scheduler,說要建立一個新pod,請你看看在那個節點上建立合適,scheduler收到訊號以後,就開始做排程,並把排程後端結果反饋給apiserver,apiserver收到排程器的排程資訊以後,它就把對應排程資訊儲存到etcd中,隨後apiServer要傳送一個watch訊號給對應被排程的主機上的kubelet,對應主機上的kubelet收到訊息後,立刻呼叫docker,並把對應容器跑起來;當容器執行起來以後,docker會向kubelet返回容器的狀體;隨後kubelet把容器的狀態反饋給apiserver,由apiserver把容器的狀態資訊儲存到etcd中;最後當etcd中的容器狀態資訊更新完成後,隨後apiserver把容器狀態資訊更新完成的訊息傳送給對應主機的kubelet;
3、在資源配置清單中定義初始化容器
[root@master01 ~]# cat pod-demo6.yaml apiVersion: v1 kind: Pod metadata: name: nginx-pod-demo6 namespace: default labels: app: nginx env: testing annotations: descriptions: "this is test pod " spec: containers: - image: nginx:1.14-alpine imagePullPolicy: IfNotPresent name: nginx ports: - containerPort: 80 hostPort: 8080 name: web protocol: TCP initContainers: - name: init-something image: busybox command: - /bin/sh - -c - "sleep 60" [root@master01 ~]#
提示:在資源配置清單中定義初始化容器需要在spec欄位下,使用initContainers欄位來定義,這個欄位的值是一個列表物件;初始化容器的定義和主容器的定義方式很類似;上面初始化容器中主要乾了一件事,就是sleep 60,意思是在啟動主容器前,首先要讓初始化容器中的操作執行完以後,對應的主容器才會開始執行;如果定義的初始化容器有多個,則要等待所有初始化容器中的操作執行完以後,對應主容器才會開始啟動;
4、Pod生命週期的兩個函式鉤子的使用
postStart:這個函式鉤子主要用來定義在主容器啟動之後,立即需要做的事,比如執行一個命令,建立一個檔案等等;這裡需要注意的是,postStart這個函式鉤子說定義的操作,都是針對主容器的,所以執行命令或其他操作的前提都是主容器上能夠正常執行的操作;
示例:定義執行一個nginx容器,在容器啟動之後立即在對應html目錄下建立一個檔案,作為使用者自定義測試頁面
[root@master01 ~]# cat pod-demo7.yaml apiVersion: v1 kind: Pod metadata: name: nginx-pod-demo7 namespace: default labels: app: nginx env: testing annotations: descriptions: "this is test pod " spec: containers: - image: nginx:1.14-alpine imagePullPolicy: IfNotPresent name: nginx ports: - containerPort: 80 hostPort: 8080 name: web protocol: TCP lifecycle: postStart: exec: command: - /bin/sh - -c - "echo 'this is test page' > /usr/share/nginx/html/test.html" [root@master01 ~]#
提示:在資源配置清單中定義主容器啟動之後需要做的事,需要在對應主容器下用lifecycle欄位來定義;其中postStart欄位使用用來指定主容器啟動之後要做到事,這個欄位的值是一個物件;其中exec是用來定義使用exec來執行命令,command欄位用來指定要執行的命令;除了可以用exec來定義執行命令,還可以使用httpGet來向當前容器中的url發起http請求,或者使用tcpSocket來向某個主機的某個埠套接字發起請求,預設不指定host表示向當前podip發起請求;
執行配置清單
[root@master01 ~]# kubectl get pod NAME READY STATUS RESTARTS AGE myapp-dep-5bc4d8cc74-cvkbc 1/1 Running 2 7d19h myapp-dep-5bc4d8cc74-gmt7w 1/1 Running 3 7d19h myapp-dep-5bc4d8cc74-gqhh5 1/1 Running 2 7d19h ngx-dep-5c8d96d457-w6nss 1/1 Running 2 7d20h [root@master01 ~]# kubectl apply -f pod-demo7.yaml pod/nginx-pod-demo7 created [root@master01 ~]# kubectl get pod -o wide NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES myapp-dep-5bc4d8cc74-cvkbc 1/1 Running 2 7d19h 10.244.1.12 node01.k8s.org <none> <none> myapp-dep-5bc4d8cc74-gmt7w 1/1 Running 3 7d19h 10.244.3.13 node03.k8s.org <none> <none> myapp-dep-5bc4d8cc74-gqhh5 1/1 Running 2 7d19h 10.244.2.8 node02.k8s.org <none> <none> nginx-pod-demo7 1/1 Running 0 6s 10.244.1.13 node01.k8s.org <none> <none> ngx-dep-5c8d96d457-w6nss 1/1 Running 2 7d20h 10.244.2.9 node02.k8s.org <none> <none> [root@master01 ~]#
驗證:訪問對應pod看看test.html是否能夠訪問到?
[root@master01 ~]# curl 10.244.1.13/test.html this is test page [root@master01 ~]#
提示:可以看到訪問對應的pod的ip地址,能夠訪問到我們剛才定義容器啟動之後建立的檔案內容;
preStop:這個函式鉤子主要用來定義在容器結束之前需要做的事情,使用方式和postStart一樣,都是在對應主容器裡的lifesycle欄位下定義;它也可以使用exec來執行命令或者httpGet來向容器的某個url發起請求,或者使用tcpSocket向某個套接字發起請求;
示例:在容器結束前執行echo 命令
[root@master01 ~]# cat pod-demo8.yaml apiVersion: v1 kind: Pod metadata: name: nginx-pod-demo8 namespace: default labels: app: nginx env: testing annotations: descriptions: "this is test pod " spec: containers: - image: nginx:1.14-alpine imagePullPolicy: IfNotPresent name: nginx lifecycle: postStart: exec: command: - /bin/sh - -c - "echo 'this is test page' > /usr/share/nginx/html/test.html" preStop: exec: command: ["/bin/sh","-c","echo goodbye.."] [root@master01 ~]#
5、pod終止過程
提示:使用者通過客戶端工具想APIserver傳送刪除pod的指令,在APIserver收到使用者發來的刪除指令後,首先APIserver會把對應的操作寫到etcd中,並設定其寬限期,然後etcd把對應資料寫好以後,響應APIserver,隨後APIserver響應客戶端說對應容器已經標記為terminating狀態;隨後APIserver會發送一個把對應pod標記為terminating狀態的訊息給endpoint端點控制,讓其刪除與當前要刪除pod相關的所有service,(其實在k8s上我們建立service關聯pod不是直接關聯pod,是現關聯endpoint端點控制器,然後端點控制器再關聯pod),隨後APIserver會向對應要刪除pod所在主機上的kubelet傳送將pod標記為terminating狀態的訊息,當對應主機收到APIserver傳送的標記pod為terminating狀態訊息後,對應主機上的kubelet會向對應pod裡執行的容器傳送TERM訊號,隨後再執行preStop中定義的操作;隨後等待寬限期超時,如果對應的pod還沒有被刪除,此時APIserver就會向對應pod所在主機上的kubelet傳送寬限期超時的訊息,此時對應kubelet會向對應容器傳送SIGKILL訊號來強制刪除對應的容器,隨後docker把對應容器刪除後,把刪除完容器的訊息響應給APIserver,此時APIserver會向etcd傳送刪除對應pod在etcd中的所有資訊;
6、pod健康狀態探測
所謂pod健康狀態探測是指檢查對應pod是否健康,如果不健康就把對應的pod重啟;健康狀態探測是一個週期性的工作;只要發現對應pod不健康,就重啟對應pod;在k8s上對pod的健康狀態探測的方式有三種,第一種上執行命令,只有對應命令執退出碼為0就表示對應pod是處於健康狀態,否則就不健康;第二種是用httpGet來探測對應pod裡的容器的某個url是否可以訪問,只有請求對應的url狀態碼為200才表示對應pod是健康的,否則就不健康;第三種是使用tcpSocket的方式來對某個套接字傳送請求,只有套接字正常響應就表示對應pod是處於健康的,否則就是不健康;至於我們要使用那種方式來判斷pod的健康與否,這取決與pod裡的服務和業務邏輯;
示例:使用exec執行命令的方式來探測pod的健康狀態
[root@master01 ~]# cat pod-demo9.yaml apiVersion: v1 kind: Pod metadata: name: liveness-exec namespace: default labels: app: nginx env: testing annotations: descriptions: "this is test pod " spec: containers: - image: nginx:1.14-alpine imagePullPolicy: IfNotPresent name: nginx lifecycle: postStart: exec: command: - /bin/sh - -c - "echo 'this is test page' > /usr/share/nginx/html/test.html" preStop: exec: command: ["/bin/sh","-c","echo goodbay.."] livenessProbe: exec: command: ["/usr/bin/test","-e","/usr/share/nginx/html/test.html"] [root@master01 ~]#
提示:使用配置清單定義pod的健康狀態監測需要用到livenessProbe這個欄位,這個欄位的值是一個物件;以上配置表示判斷/usr/share/nginx/html/test.html這個檔案是否存在,存在就表示對應pod健康,否則就不健康;
應用配置清單
[root@master01 ~]# kubectl apply -f pod-demo9.yaml pod/liveness-exec created [root@master01 ~]# kubectl get pod NAME READY STATUS RESTARTS AGE liveness-exec 1/1 Running 0 4s myapp-dep-5bc4d8cc74-cvkbc 1/1 Running 3 8d myapp-dep-5bc4d8cc74-gmt7w 1/1 Running 4 8d myapp-dep-5bc4d8cc74-gqhh5 1/1 Running 3 8d nginx-pod-demo7 1/1 Running 1 4h45m ngx-dep-5c8d96d457-w6nss 1/1 Running 3 8d [root@master01 ~]#
提示:可以看到對應pod現在已經正常執行著,並且重啟次數為0;
測試:進入對應pod把test.html檔案刪除,看看對應pod還會正常處於健康狀態嗎?重啟次數還是0嗎?
[root@master01 ~]# kubectl exec liveness-exec -- rm -f /usr/share/nginx/html/test.html
檢視對應pod狀態
[root@master01 ~]# kubectl get pod NAME READY STATUS RESTARTS AGE liveness-exec 1/1 Running 1 2m45s myapp-dep-5bc4d8cc74-cvkbc 1/1 Running 3 8d myapp-dep-5bc4d8cc74-gmt7w 1/1 Running 4 8d myapp-dep-5bc4d8cc74-gqhh5 1/1 Running 3 8d nginx-pod-demo7 1/1 Running 1 4h48m ngx-dep-5c8d96d457-w6nss 1/1 Running 3 8d [root@master01 ~]#
提示:可以看到對應pod重啟數已經變為1了,說明pod發生了重啟;
檢視pod的詳細資訊
提示:從上面的截圖可以看到,pod健康狀態檢查不通過,就把容器給重啟了;重啟以後對應的檔案又回重新建立,所以再次健康狀態監測就通過了,所以pod處於健康狀態;
示例:使用httpGet探測對應pod是否健康
[root@master01 ~]# cat liveness-httpget.yaml apiVersion: v1 kind: Pod metadata: name: liveness-httpget namespace: default labels: app: nginx env: testing annotations: descriptions: "this is test pod " spec: containers: - image: nginx:1.14-alpine imagePullPolicy: IfNotPresent name: nginx ports: - name: http containerPort: 80 lifecycle: postStart: exec: command: - /bin/sh - -c - "echo 'this is test page' > /usr/share/nginx/html/test.html" preStop: exec: command: ["/bin/sh","-c","echo goodbay.."] livenessProbe: httpGet: path: /test.html port: http scheme: HTTP failureThreshold: 2 initialDelaySeconds: 2 periodSeconds: 3 [root@master01 ~]#
提示:failureThreshold欄位用於指定失敗閾值,即多少次失敗就把對應pod標記為不健康;預設是3次;initialDelaySeconds欄位用於指定初始化後延遲多少時間再做健康狀態監測;periodSeconds欄位用於指定監測頻率,預設是10秒一次;最小為1秒一次;以上配置清單表示對pod容器裡的/test.html這個url發起請求,如果響應碼為200就表示pod健康,否則就不健康;httpGet中必須指定埠,埠資訊可以應用上面容器中定義的埠名稱;
應用配置清單
[root@master01 ~]# kubectl apply -f liveness-httpget.yaml pod/liveness-httpget created [root@master01 ~]# kubectl get pod NAME READY STATUS RESTARTS AGE liveness-exec 1/1 Running 2 29m liveness-httpget 1/1 Running 0 5s myapp-dep-5bc4d8cc74-cvkbc 1/1 Running 3 8d myapp-dep-5bc4d8cc74-gmt7w 1/1 Running 4 8d myapp-dep-5bc4d8cc74-gqhh5 1/1 Running 3 8d nginx-pod-demo7 1/1 Running 1 5h15m ngx-dep-5c8d96d457-w6nss 1/1 Running 3 8d [root@master01 ~]#
驗證:進入對應pod,把test.html檔案刪除,看看對應pod是否會重啟?
[root@master01 ~]# kubectl exec liveness-httpget -- rm -rf /usr/share/nginx/html/test.html [root@master01 ~]# kubectl get pod NAME READY STATUS RESTARTS AGE liveness-exec 1/1 Running 2 30m liveness-httpget 1/1 Running 1 97s myapp-dep-5bc4d8cc74-cvkbc 1/1 Running 3 8d myapp-dep-5bc4d8cc74-gmt7w 1/1 Running 4 8d myapp-dep-5bc4d8cc74-gqhh5 1/1 Running 3 8d nginx-pod-demo7 1/1 Running 1 5h16m ngx-dep-5c8d96d457-w6nss 1/1 Running 3 8d [root@master01 ~]#
提示:可以看到對應pod已經發生了重啟;
檢視pod詳細資訊
提示:可以看到對應pod健康狀態探測失敗,並重啟的事件;
示例:使用tcpsocket方式來探測pod健康狀態
[root@master01 ~]# cat liveness-tcpsocket.yaml apiVersion: v1 kind: Pod metadata: name: liveness-tcpsocket namespace: default labels: app: nginx env: testing annotations: descriptions: "this is test pod " spec: containers: - image: nginx:1.14-alpine imagePullPolicy: IfNotPresent name: nginx ports: - name: http containerPort: 80 livenessProbe: tcpSocket: port: http failureThreshold: 2 initialDelaySeconds: 2 periodSeconds: 3 [root@master01 ~]#
提示:使用tcpSocket方式來探測健康與否,預設不指定host欄位表示探測對應podip;
應用資源配置清單
[root@master01 ~]# kubectl apply -f liveness-tcpsocket.yaml pod/liveness-tcpsocket created [root@master01 ~]# kubectl get pod NAME READY STATUS RESTARTS AGE liveness-exec 1/1 Running 2 42m liveness-httpget 1/1 Running 1 12m liveness-tcpsocket 1/1 Running 0 5s myapp-dep-5bc4d8cc74-cvkbc 1/1 Running 3 8d myapp-dep-5bc4d8cc74-gmt7w 1/1 Running 4 8d myapp-dep-5bc4d8cc74-gqhh5 1/1 Running 3 8d nginx-pod-demo7 1/1 Running 1 5h27m ngx-dep-5c8d96d457-w6nss 1/1 Running 3 8d [root@master01 ~]#
測試:進入pod裡的容器,修改nginx的埠為81,看看對應pod是否會重啟?
[root@master01 ~]# kubectl exec liveness-tcpsocket -it -- /bin/sh / # netstat -tnl Active Internet connections (only servers) Proto Recv-Q Send-Q Local Address Foreign Address State tcp 0 0 0.0.0.0:80 0.0.0.0:* LISTEN / # grep "listen" /etc/nginx/conf.d/default.conf listen 80; # proxy the PHP scripts to Apache listening on 127.0.0.1:80 # pass the PHP scripts to FastCGI server listening on 127.0.0.1:9000 / # sed -i 's@ listen.*@ listen 81;@g' /etc/nginx/conf.d/default.conf / # grep "listen" /etc/nginx/conf.d/default.conf listen 81; # proxy the PHP scripts to Apache listening on 127.0.0.1:80 # pass the PHP scripts to FastCGI server listening on 127.0.0.1:9000 / # nginx -s reload 2020/12/16 11:49:51 [notice] 35#35: signal process started / # command terminated with exit code 137 [root@master01 ~]#
提示:可以看到我們修改了配置檔案讓nginx監聽81埠,沒過幾秒就退出了;
檢視對應pod是否發生了重啟?
提示:可以看到對應pod裡的事件資訊說健康狀態監測10.244.3.22:80連線失敗,容器重啟了;
7、pod就緒狀態探測
所謂pod就緒狀態探測是指探測對應pod是否就緒,主要用在service關聯後端pod的一個重要依據,如果對應pod未就緒,對應service就不應該關聯pod,否則可能發生使用者訪問對應service,響應服務不可用;pod就緒狀態檢查和健康狀態檢查兩者最主要的區別是,健康狀態檢查,一旦對應pod不健康了,就會執行重啟對應pod的操作,而就緒狀態檢查是沒有許可權去重啟pod,如果對應pod沒有就緒,它不會做任何操作;同樣的對就緒狀態檢查在k8s上也有三種方式和健康狀態檢查的方式一摸一樣;
示例:使用exec方式探測pod就緒狀態
[root@master01 ~]# cat readiness-demo.yaml apiVersion: v1 kind: Pod metadata: name: readiness-demo namespace: default labels: app: nginx env: testing annotations: descriptions: "this is test pod " spec: containers: - image: nginx:1.14-alpine imagePullPolicy: IfNotPresent name: nginx ports: - name: http containerPort: 80 lifecycle: postStart: exec: command: ["/bin/sh","-c","echo 'this is test page' > /usr/share/nginx/html/test.html"] readinessProbe: exec: command: ["/usr/bin/test","-e","/usr/share/nginx/html/test.html"] failureThreshold: 2 initialDelaySeconds: 2 periodSeconds: 3 [root@master01 ~]#
提示:以上清單表示如果/usr/share/nginx/html/test.html檔案存在,則表示對應pod就緒,否則就表示為就緒;
應用配置清單
[root@master01 ~]# kubectl apply -f readiness-demo.yaml pod/readiness-demo created [root@master01 ~]# kubectl get pod NAME READY STATUS RESTARTS AGE liveness-exec 1/1 Running 2 65m liveness-httpget 1/1 Running 1 35m liveness-tcpsocket 1/1 Running 1 23m myapp-dep-5bc4d8cc74-cvkbc 1/1 Running 3 8d myapp-dep-5bc4d8cc74-gmt7w 1/1 Running 4 8d myapp-dep-5bc4d8cc74-gqhh5 1/1 Running 3 8d nginx-pod-demo7 1/1 Running 1 5h50m ngx-dep-5c8d96d457-w6nss 1/1 Running 3 8d readiness-demo 0/1 Running 0 5s [root@master01 ~]# kubectl get pod NAME READY STATUS RESTARTS AGE liveness-exec 1/1 Running 2 65m liveness-httpget 1/1 Running 1 36m liveness-tcpsocket 1/1 Running 1 23m myapp-dep-5bc4d8cc74-cvkbc 1/1 Running 3 8d myapp-dep-5bc4d8cc74-gmt7w 1/1 Running 4 8d myapp-dep-5bc4d8cc74-gqhh5 1/1 Running 3 8d nginx-pod-demo7 1/1 Running 1 5h51m ngx-dep-5c8d96d457-w6nss 1/1 Running 3 8d readiness-demo 1/1 Running 0 25s [root@master01 ~]#
提示:可以看到應用配置清單以後,對應的pod從未就緒到就緒狀態了;
測試:刪除pod容器中的test.html檔案,看看對應pod是否會從就緒狀態到未就緒狀態?
[root@master01 ~]# kubectl get pod NAME READY STATUS RESTARTS AGE liveness-exec 1/1 Running 2 67m liveness-httpget 1/1 Running 1 37m liveness-tcpsocket 1/1 Running 1 25m myapp-dep-5bc4d8cc74-cvkbc 1/1 Running 3 8d myapp-dep-5bc4d8cc74-gmt7w 1/1 Running 4 8d myapp-dep-5bc4d8cc74-gqhh5 1/1 Running 3 8d nginx-pod-demo7 1/1 Running 1 5h52m ngx-dep-5c8d96d457-w6nss 1/1 Running 3 8d readiness-demo 1/1 Running 0 2m3s [root@master01 ~]# kubectl exec readiness-demo -- rm -rf /usr/share/nginx/html/test.html [root@master01 ~]# kubectl get pod NAME READY STATUS RESTARTS AGE liveness-exec 1/1 Running 2 67m liveness-httpget 1/1 Running 1 38m liveness-tcpsocket 1/1 Running 1 25m myapp-dep-5bc4d8cc74-cvkbc 1/1 Running 3 8d myapp-dep-5bc4d8cc74-gmt7w 1/1 Running 4 8d myapp-dep-5bc4d8cc74-gqhh5 1/1 Running 3 8d nginx-pod-demo7 1/1 Running 1 5h53m ngx-dep-5c8d96d457-w6nss 1/1 Running 3 8d readiness-demo 0/1 Running 0 2m36s [root@master01 ~]#
提示:可以看到對應pod已經處於未就緒狀態了;
檢視對應pod的詳細資訊
提示:在對應pod的詳細資訊中也能看到對應的事件,不同於健康狀態探測,就緒狀態探測,它這裡不會重啟pod;
測試:建立test.html檔案,看看對應pod是否會從未就緒狀態到就緒狀態?
[root@master01 ~]# kubectl exec readiness-demo -- touch /usr/share/nginx/html/test.htm [root@master01 ~]# kubectl get pod NAME READY STATUS RESTARTS AGE liveness-exec 1/1 Running 2 72m liveness-httpget 1/1 Running 1 42m liveness-tcpsocket 1/1 Running 1 30m myapp-dep-5bc4d8cc74-cvkbc 1/1 Running 3 8d myapp-dep-5bc4d8cc74-gmt7w 1/1 Running 4 8d myapp-dep-5bc4d8cc74-gqhh5 1/1 Running 3 8d nginx-pod-demo7 1/1 Running 1 5h57m ngx-dep-5c8d96d457-w6nss 1/1 Running 3 8d readiness-demo 1/1 Running 0 7m11s [root@master01 ~]#
提示:可以看到對應pod已經處於就緒狀態;
8、pod資源限制
所謂pod資源限制就是指限制對應pod裡容器的cpu和記憶體使用量;我們知道如果一個容器不限制其資源的使用大小,很有可能發生一個容器將宿主機上的記憶體耗盡的情況,如果一旦發生記憶體耗盡,核心很有可能向容器程序發起oom(out of memory),這樣一來執行在docker上的其他容器也會相繼退出;所以為了不讓類似的情況發生,我們有必要給pod裡的容器做資源限定;
資源計量方式
對於cpu來講,它是可壓縮資源,所謂可以壓縮資源就是表示cpu不夠用時,它並不會報錯,pod可以等待;對於記憶體來講,它是不可壓縮資源,不可壓縮就是指如果記憶體不夠用對應程式就會崩潰,從而導致容器退出;cpu的計量方式是m,即1核心=1000m,0.5個核心就等於500m;記憶體的計量方式預設單位是位元組,我們在指定記憶體資源,直接加上單位即可;可以使用E、P、T、G、M、K為字尾單位,也可以使用Ei、Pi、Ti、Gi、Mi、Ki作為單位;
示例:在資源清單中限制pod資源
[root@master01 ~]# cat resource.yaml apiVersion: v1 kind: Pod metadata: name: stress-pod spec: containers: - name: stress image: ikubernetes/stress-ng command: ["/usr/bin/stress-ng", "-c 1", "-m 1", "--metrics-brief"] resources: requests: memory: "128Mi" cpu: "200m" limits: memory: "512Mi" cpu: "400m" [root@master01 ~]#
提示:定義pod的資源限制,需要用到resources這個欄位,這個欄位的值為一個物件;其中requests欄位用於指定下限,limits指定資源的上限;
應用資源清單
[root@master01 ~]# kubectl apply -f resource.yaml pod/stress-pod created [root@master01 ~]# kubectl get pod -o wide NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES liveness-exec 1/1 Running 2 147m 10.244.3.21 node03.k8s.org <none> <none> liveness-httpget 1/1 Running 1 118m 10.244.2.14 node02.k8s.org <none> <none> liveness-tcpsocket 1/1 Running 1 105m 10.244.3.22 node03.k8s.org <none> <none> myapp-dep-5bc4d8cc74-cvkbc 1/1 Running 3 8d 10.244.1.16 node01.k8s.org <none> <none> myapp-dep-5bc4d8cc74-gmt7w 1/1 Running 4 8d 10.244.3.17 node03.k8s.org <none> <none> myapp-dep-5bc4d8cc74-gqhh5 1/1 Running 3 8d 10.244.2.11 node02.k8s.org <none> <none> nginx-pod-demo7 1/1 Running 1 7h12m 10.244.1.14 node01.k8s.org <none> <none> ngx-dep-5c8d96d457-w6nss 1/1 Running 3 8d 10.244.2.12 node02.k8s.org <none> <none> readiness-demo 1/1 Running 0 82m 10.244.3.23 node03.k8s.org <none> <none> stress-pod 1/1 Running 0 13s 10.244.2.16 node02.k8s.org <none> <none> [root@master01 ~]#
提示:可以看到stress-pod被排程到node02上運行了;
測試:在node02上使用doucker stats命令檢視對應stress-pod容器佔用資源情況
提示:可以看到在node02上跑的k8s_stress_stress-pod_default容器佔有cpu和記憶體都是我們在資源清單中定義的量;
示例:當pod裡的容器資源不夠用時,對應pod是否會發生oom呢?
[root@master01 ~]# cat memleak-pod.yaml apiVersion: v1 kind: Pod metadata: name: memleak-pod spec: containers: - name: simmemleak image: saadali/simmemleak resources: requests: memory: "64Mi" cpu: "1" limits: memory: "1Gi" cpu: "1" [root@master01 ~]#
提示:以上配置清單主要限制了容器最大記憶體為1G,最小記憶體為64M,cpu上下限都為1核心;
應用配置清單
[root@master01 ~]# kubectl apply -f memleak-pod.yaml pod/memleak-pod created [root@master01 ~]# kubectl get pod NAME READY STATUS RESTARTS AGE liveness-exec 1/1 Running 2 155m liveness-httpget 1/1 Running 1 126m liveness-tcpsocket 1/1 Running 1 113m memleak-pod 0/1 ContainerCreating 0 2s myapp-dep-5bc4d8cc74-cvkbc 1/1 Running 3 8d myapp-dep-5bc4d8cc74-gmt7w 1/1 Running 4 8d myapp-dep-5bc4d8cc74-gqhh5 1/1 Running 3 8d nginx-pod-demo7 1/1 Running 1 7h21m ngx-dep-5c8d96d457-w6nss 1/1 Running 3 8d readiness-demo 1/1 Running 0 90m stress-pod 1/1 Running 0 8m46s [root@master01 ~]# kubectl get pod NAME READY STATUS RESTARTS AGE liveness-exec 1/1 Running 2 156m liveness-httpget 1/1 Running 1 126m liveness-tcpsocket 1/1 Running 1 114m memleak-pod 0/1 OOMKilled 0 21s myapp-dep-5bc4d8cc74-cvkbc 1/1 Running 3 8d myapp-dep-5bc4d8cc74-gmt7w 1/1 Running 4 8d myapp-dep-5bc4d8cc74-gqhh5 1/1 Running 3 8d nginx-pod-demo7 1/1 Running 1 7h21m ngx-dep-5c8d96d457-w6nss 1/1 Running 3 8d readiness-demo 1/1 Running 0 91m stress-pod 1/1 Running 0 9m5s [root@master01 ~]#
提示:可以看到應用資源清單以後,對應的pod處於OOMKilled狀態;原因是我們執行的映象裡面的程式一直申請記憶體,超出了最大限制;
檢視pod詳細資訊
提示:可以看到當前pod狀態為terminated狀態,原因是OOMKilled;上一次狀態為terminated,原因也是OOMKille