Kubernetes中Pod容器的資源限制和探針配置方式
在 Kubernetes 中,定義 Pod 時可以選擇性地為每個容器設定所需要的資源數(shù)量。
最常見的可設定資源是 CPU 和內存大小,以及其他類型的資源;另一方面,通過配置探針,可以確保容器在運行時保持健康,并且只有在準備好接收流量時才會被負載均衡器引導流量。
從而提高應用程序的可靠性和穩(wěn)定性。
一、容器管理資源概念
1.1.概述
在 K8s 中,對 Pod 容器的資源限制主要圍繞著兩個關鍵參數(shù):request 資源和 limit 資源,用于配置 CPU 和內存的使用情況;避免資源競爭和不必要的浪費,同時確保 Pod 在運行時具有足夠的資源支持。
官網(wǎng)示例:
https://kubernetes.io/docs/concepts/configuration/manage-compute-resources-container/
1.2. Pod 和 容器 的資源請求和限制
spec.containers[].resources.requests.cpu //定義創(chuàng)建容器時預分配的CPU資源 spec.containers[].resources.requests.memory //定義創(chuàng)建容器時預分配的內存資源 spec.containers[].resources.limits.cpu //定義 cpu 的資源上限 spec.containers[].resources.limits.memory //定義內存的資源上限
request 預留資源
創(chuàng)建 pod 容器時需要預留的資源量,cpu(0.5 或 500m),內存 Mi、Gi(以2為底的冪數(shù)),M、G(以10為底)。
spec.containers[].resources.requests.cpu spec.containers[].resources.requests.memory
limit 限制資源
pod 容器能夠使用資源量的一個上限。如:4Gi 代表內存上限不允許超過上限值;1 代表 cpu 上限不允許超過上限值。
spec.containers[].resources.limits.cpu spec.containers[].resources.limits.memory
1.3. K8s 中的資源單位
1.3.1 CPU 資源單位
CPU 資源的 request 和 limit 以 cpu 為單位。在 K8s 中,一個 CPU 等于 1 個物理 CPU 核 或者 1 個虛擬核, 取決于節(jié)點是一臺物理主機還是運行在某物理主機上的虛擬機。
當定義一個容器,將其 spec.containers[].resources.requests.cpu 設置為 0.5 時, 所請求的 CPU 是請求 1.0 CPU 時的一半。 對于 CPU 資源單位,數(shù)量表達式 0.1 等價于表達式 100m(一百毫核),可以看作 “100 millicpu”。
注意:K8s 不允許設置精度小于 1m 或 0.001 的 CPU 資源。
1.3.2 內存資源單位
內存的 request 和 limit 以字節(jié)為單位。 可以使用普通的整數(shù),或者帶有以下 數(shù)量后綴 的定點數(shù)字來表示內存:E、P、T、G、M、k。 也可以使用對應的 2 的冪數(shù):Ei、Pi、Ti、Gi、Mi、Ki。
PS:在買硬盤的時候,操作系統(tǒng)報的數(shù)量要比產品標出或商家號稱的小一些,主要原因是標出的是以 MB、GB為單位的,1GB 就是1,000,000,000Byte,而操作系統(tǒng)是以2進制為處理單位的,因此檢查硬盤容量時是以MiB、GiB為單位,1GiB=2^30=1,073,741,824,相比較而言,1GiB要比1GB多出1,073,741,824-1,000,000,000=73,741,824Byte,所以檢測實際結果要比標出的少一些。
1.4. 資源限制配置規(guī)則
如果 Pod 運行所在的節(jié)點具有足夠的可用資源,容器可以使用超出所設置的 request 資源量。不過,容器不可以使用超出所設置的 limit 資源量。
如果給容器設置了內存的 limit 值,但未設置內存的 request 值,Kubernetes 會自動為其設置與內存 limit 相匹配的 request 值;類似的 cpu 同理。
1.5. 容器資源示例
1.5.1 request 與 limit 創(chuàng)建 pod 模板
以下例子中的 Pod 有兩個容器。每個容器的 request 值為 0.25 cpu 和 64MiB 內存,每個容器的 limit 值為 0.5 cpu 和 128MiB 內存。那么可以認為該 Pod 的總的資源 request 為 0.5 cpu 和 128 MiB 內存,總的資源 limit 為 1 cpu 和 256MiB 內存。
[root@master01 demo]# vim demo1.yaml
apiVersion: v1
kind: Pod
metadata:
name: demo-01
spec:
containers:
- name: app
image: images.my-company.example/app:v4
env: # 定義了容器的環(huán)境變量
- name: MYSQL_ROOT_PASSWORD # 設置環(huán)境變量
value: "123456" # 環(huán)境變量的值
resources: # 容器的資源限制和請求
requests: # 容器的資源請求
memory: "64Mi" # 請求容器使用的內存量為64MiB
cpu: "250m" # 請求容器使用的CPU量為250 m
limits: # 容器的資源限制
memory: "128Mi" # 限制容器使用的最大內存量為128MiB
cpu: "500m" # 限制容器使用的最大CPU量為500 m
- name: log-aggregator
image: images.my-company.example/log-aggregator:v6
resources: # 容器的資源限制和請求
requests: # 容器的資源請求
memory: "64Mi" # 容器使用的內存量為64MiB
cpu: "250m" # 第二個容器使用的CPU量為250 m
limits: # 容器的資源限制
memory: "128Mi" # 限制第二個容器使用的最大內存量為128MiB
cpu: "500m" # 限制第二個容器使用的最大CPU量為500 m1.5.2. OOMKilled 內存耗盡保護機制
為了模擬內存耗盡情況并觀察OOMKilled(Out Of Memory Killed)內存耗盡保護機制的效果,我們將調整數(shù)據(jù)庫容器的資源請求(requests)和內存限制(limits)到一個較小的值,以便觸發(fā)內存不足的情況。
請注意,在生產環(huán)境中,調整容器的資源請求和限制應該謹慎進行,以避免對系統(tǒng)產生不可預料的影響。
① 創(chuàng)建 yaml 文件
[root@master01 demo]# vim demo2.yaml
apiVersion: v1
kind: Pod
metadata:
name: web-db
spec:
containers:
- name: web
image: nginx
env:
- name: WEB_ROOT_PASSWORD
value: "123123"
resources:
requests:
memory: "64Mi"
cpu: "250m"
limits:
memory: "128Mi"
cpu: "500m"
- name: db
image: mysql
env:
- name: MYSQL_ROOT_PASSWORD
value: "123123"
resources:
requests:
memory: "64Mi"
cpu: "0.25"
limits:
memory: "128Mi"
cpu: "500m"② 啟動 pod
[root@master01 demo]# kubectl apply -f demo2.yaml pod/web-db created
③ 查看資源信息
[root@master01 demo]# kubectl get pod web-db -w NAME READY STATUS RESTARTS AGE web-db 0/2 ContainerCreating 0 18s web-db 2/2 Running 0 63s web-db 1/2 OOMKilled 0 76s web-db 2/2 Running 1 93s web-db 1/2 OOMKilled 1 105s web-db 1/2 CrashLoopBackOff 1 2m web-db 2/2 Running 2 2m1s web-db 1/2 OOMKilled 2 2m14s web-db 1/2 CrashLoopBackOff 2 2m28s # 多次出現(xiàn)的 OOMKilled 表示容器由于內存耗盡而被系統(tǒng)終止 [root@master01 demo]# kubectl describe pod web-db Events: Type Reason Age From Message ---- ------ ---- ---- ------- Normal Scheduled 3m20s default-scheduler Successfully assigned default/web-db to node01 Normal Pulling 3m19s kubelet Pulling image "nginx" Normal Pulled 3m4s kubelet Successfully pulled image "nginx" in 15.521857377s Normal Created 3m4s kubelet Created container web Normal Started 3m4s kubelet Started container web Normal Pulled 2m18s kubelet Successfully pulled image "mysql" in 46.048445572s Normal Pulled 108s kubelet Successfully pulled image "mysql" in 15.474925496s Normal Pulled 80s kubelet Successfully pulled image "mysql" in 399.833869ms Normal Pulling 38s (x4 over 3m4s) kubelet Pulling image "mysql" Normal Created 38s (x4 over 2m17s) kubelet Created container db Normal Started 38s (x4 over 2m17s) kubelet Started container db Normal Pulled 38s kubelet Successfully pulled image "mysql" in 388.467767ms Warning BackOff 13s (x5 over 95s) kubelet Back-off restarting failed container # 容器 "db" 失敗并且在多次嘗試后仍然無法成功啟動,導致觸發(fā)了 BackOff 機制
④ 調整資源配額限制
[root@master01 demo]# kubectl delete -f demo2.yaml
pod "web-db" deleted
[root@master01 demo]# vim demo2.yaml
resources:
requests:
memory: "128Mi"
cpu: "0.5"
limits:
memory: "1Gi"
cpu: "1000m"⑤ 再次嘗試啟動 pod
[root@master01 demo]# kubectl apply -f demo2.yaml pod/web-db created [root@master01 demo]# kubectl get pod web-db NAME READY STATUS RESTARTS AGE web-db 2/2 Running 0 42s
⑥ 查看 node 節(jié)點資源占比
[root@master01 demo]# kubectl get pod web-db -o wide NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES web-db 2/2 Running 0 94s 10.244.1.22 node01 <none> <none> [root@master01 demo]# kubectl describe node node01 Namespace Name CPU Requests CPU Limits Memory Requests Memory Limits AGE --------- ---- ------------ ---------- --------------- ------------- --- default pod-01 0 (0%) 0 (0%) 0 (0%) 0 (0%) 4h19m default web-db 750m (37%) 1500m (75%) 192Mi (11%) 1152Mi (66%) 2m13s kube-flannel kube-flannel-ds-wz8p2 100m (5%) 0 (0%) 50Mi (2%) 0 (0%) 8d kube-system kube-proxy-w7vl7 0 (0%) 0 (0%) 0 (0%) 0 (0%) 8d Allocated resources: (Total limits may be over 100 percent, i.e., overcommitted.) Resource Requests Limits -------- -------- ------ cpu 850m (42%) 1500m (75%) memory 242Mi (14%) 1152Mi (66%) ephemeral-storage 0 (0%) 0 (0%) hugepages-1Gi 0 (0%) 0 (0%) hugepages-2Mi 0 (0%) 0 (0%)
Pod "web-db" 的資源請求和限制如下:
- CPU 請求:750m,CPU 限制:1500m
- 內存請求:192Mi,內存限制:1152Mi
已分配的資源情況如下:
- CPU 請求總量:850m(42%),CPU 限制總量:1500m(75%)
- 內存請求總量:242Mi(14%),內存限制總量:1152Mi(66%)
二、Pod 容器的探針
2.1. 概述
探針是由 kubelet 對容器執(zhí)行的定期診斷。容器的探針是一種關鍵的機制,用于監(jiān)測和管理容器的健康狀態(tài),確保容器在各種情況下都能正常運行。通過配置適當?shù)奶结?,可以提高容器的可靠性和穩(wěn)定性,確保容器能夠有效應對各種運行時情況,并及時處理健康狀態(tài)的變化。
2.2.探針的三種規(guī)則
2.2.1 存活探針(Liveness Probe)
用于確定容器是否正在運行并且健康。如果存活探針失敗,Kubernetes 將根據(jù)重啟策略(如 `RestartPolicy`)嘗試重新啟動容器。如果容器不提供存活探針,則默認狀態(tài)為 Success。
2.2.2 就緒探針(Readiness Probe)
用于確定容器是否已準備好接收流量。如果就緒探針失敗,容器將被從 Service 的負載均衡池中移除該 Pod 的 IP 地址,直到就緒探針再次成功。初始延遲之前的就緒狀態(tài)默認為 Failure。如果容器不提供就緒探針,則默認狀態(tài)為 Success。
2.2.3 啟動探針(Startup Probe)
1.17版本增加的。用于確定容器是否已經(jīng)啟動并且已經(jīng)準備好接收其它探針的檢查。啟動探針在容器啟動后執(zhí)行,但在就緒探針和存活探針之前執(zhí)行。
如果 startupProbe 失敗,kubelet 將殺死容器,容器將根據(jù) restartPolicy 來重啟。如果容器沒有配置 startupProbe, 則默認狀態(tài)為 Success。
以上規(guī)則可以同時定義。在 readinessProbe 檢測成功之前,Pod 的 running 狀態(tài)是不會變成 ready 狀態(tài)的。通過配置這些探針,可以確保容器在運行時保持健康,并且只有在準備好接收流量時才會被負載均衡器引導流量。這有助于提高應用程序的可靠性和穩(wěn)定性。
2.3. 探針三種檢查方法
- exec :在容器內執(zhí)行指定命令。如果命令退出時返回碼為0則認為診斷成功;
- tcpSocket :對指定端口上的容器的IP地址進行TCP檢查(三次握手)。如果端口打開,則診斷被認為是成功的;
- httpGet :對指定的端口和路徑上的容器的IP地址執(zhí)行HTTPGet請求。如果響應的狀態(tài)碼大于等于200且小于400,則診斷被認為是成功的。
每次探測都將獲得以下三種結果之一:
- 成功:容器通過了診斷;
- 失?。喝萜魑赐ㄟ^診斷;
- 未知:診斷失敗,因此不會采取任何行動。
2.4.探針配置示例
2.4.1 定義存活命令
許多長時間運行的應用最終會進入損壞狀態(tài),除非重新啟動,否則無法被恢復。 Kubernetes 提供了存活探針來發(fā)現(xiàn)并處理這種情況。
示例1:livenessProbe 規(guī)則,配合 exec 檢查方法。
① 編輯 pod 的 yaml 配置文件
[root@master01 demo]# vim demo3.yaml
apiVersion: v1
kind: Pod
metadata: # 元數(shù)據(jù)
labels: # Pod 的標簽
test: liveness
name: liveness-exec
spec: # Pod 的規(guī)格
containers: # 容器列表
- name: liveness # 容器的名稱
image: busybox # 一個輕量級的 BusyBox 鏡像
imagePullPolicy: IfNotPresent # 鏡像拉取策略,先本地后倉庫
args: # 容器的啟動參數(shù)部分
- /bin/sh
- -c # 后面的內容將作為 shell 的命令執(zhí)行
- touch /tmp/healthy; sleep 10; rm -rf /tmp/healthy; sleep 10
# 在容器啟動時執(zhí)行的命令,首先創(chuàng)建一個/tmp/healthy文件,然后等待10秒,接著刪除該文件,最后再等待10秒
livenessProbe: # 定義存活探針的配置
exec: # 使用 exec 方式執(zhí)行命令
command: # 要執(zhí)行的命令
- cat
- /tmp/healthy # 讀取 /tmp/healthy 文件的內容
failureThreshold: 1 # 存活探針的失敗閾值為1,即連續(xù)失敗1次后認為探針失敗,默認值是3。最小值是1
initialDelaySeconds: 3 # 容器啟動后等待3秒開始進行存活探測,其實是4秒,默認是0秒,最小值是0
periodSeconds: 2 # 每隔2秒進行一次存活探測,默認是10秒。最小值是1。這個容器生命的前 10 秒,/tmp/healthy 文件是存在的。 所以在這最開始的 10 秒內,執(zhí)行命令 cat /tmp/healthy 會返回成功代碼。 10 秒之后,執(zhí)行命令 cat /tmp/healthy 就會返回失敗代碼。
② 啟動 pod
[root@master01 demo]# kubectl apply -f demo3.yaml pod/liveness-exec created
③ 查看容器狀態(tài)詳情信息
[root@master01 demo]# kubectl get pod liveness-exec -w NAME READY STATUS RESTARTS AGE liveness-exec 1/1 Running 0 3s liveness-exec 1/1 Running 1 22s liveness-exec 1/1 Running 2 43s liveness-exec 1/1 Running 3 63s liveness-exec 1/1 Running 4 83s liveness-exec 0/1 CrashLoopBackOff 4 103s # Pod中的容器liveness由于存活探針失敗而不斷重啟,并最終進入了CrashLoopBackOff狀態(tài) # 輸出結果顯示RESTARTS的值增加了1。 請注意,一旦失敗的容器恢復為運行狀態(tài),RESTARTS計數(shù)器就會加1 查看 Pod 的事件: [root@master01 demo]# kubectl describe pod liveness-exec Events: Type Reason Age From Message ---- ------ ---- ---- ------- Normal Scheduled 2m24s default-scheduler Successfully assigned default/liveness-exec to node01 Normal Pulled 62s (x5 over 2m24s) kubelet Container image "busybox" already present on machine Normal Created 62s (x5 over 2m24s) kubelet Created container liveness Normal Started 62s (x5 over 2m24s) kubelet Started container liveness Warning Unhealthy 51s (x5 over 2m13s) kubelet Liveness probe failed: cat: can't open '/tmp/healthy': No such file or directory Normal Killing 51s (x5 over 2m13s) kubelet Container liveness failed liveness probe, will be restarted # 顯示存活探針失敗了,這個失敗的容器被殺死并且被重建了 # 是否重啟還是根據(jù)重啟策略來決定,這里明顯是always
2.4.2 定義一個存活態(tài) HTTP 請求接口
另外一種類型的存活探測方式是使用 HTTP GET 請求。
示例2:livenessProbe 規(guī)則,配合 httpGet 檢查方法。
① 編輯 pod 的 yaml 配置文件
[root@master01 demo]# vim demo4.yaml
apiVersion: v1
kind: Pod
metadata:
name: liveness-httpget
namespace: default
spec:
containers:
- name: liveness-httpget-container
image: soscscs/myapp:v1
imagePullPolicy: IfNotPresent # 鏡像拉取策略
ports:
- name: http
containerPort: 80 # 容器內部的端口號為 80
livenessProbe: # 定義存活探針的配置
httpGet: # 使用HTTP GET請求方式進行探測
port: http # 探測請求發(fā)送到的端口為http,即容器內部的80端口
path: /index.html # 探測請求的路徑為 /index.html
initialDelaySeconds: 1 # 容器啟動后等待1秒后開始進行存活探測
periodSeconds: 3 # 每隔3秒進行一次存活探測
timeoutSeconds: 5 # 超時時間為5秒如果存活探針發(fā)送的 HTTPGET 請求返回成功(即能夠訪問到 /index.html),則認為容器是健康的。如果請求失?。o法訪問到 /index.html 或返回錯誤),則認為容器不健康處理程序返回失敗代碼,kubelet 會殺死這個容器并且重新啟動它。
② 啟動 pod
[root@master01 demo]# kubectl apply -f demo4.yaml pod/liveness-httpget created [root@master01 demo]# kubectl get pod liveness-httpget -o wide NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES liveness-httpget 1/1 Running 0 65s 10.244.1.24 node01 <none> <none> 嘗試訪問頁面: [root@master01 demo]# curl 10.244.1.24 Hello MyApp | Version: v1 | <a href="hostname.html" rel="external nofollow" >Pod Name</a> [root@master01 demo]# curl 10.244.1.24 -I Server: nginx/1.12.2
③ 刪除容器中 index.html
[root@master01 demo]# kubectl exec -it liveness-httpget -- rm -f /usr/share/nginx/html/index.html
③ 查看容器狀態(tài)詳情信息
[root@master01 demo]# kubectl get pod liveness-httpget NAME READY STATUS RESTARTS AGE liveness-httpget 1/1 Running 2 5m42s [root@master01 demo]# kubectl describe pod liveness-httpget Events: Type Reason Age From Message ---- ------ ---- ---- ------- Normal Scheduled 6m32s default-scheduler Successfully assigned default/liveness-httpget to node01 Normal Pulling 6m32s kubelet Pulling image "soscscs/myapp:v1" Normal Pulled 6m14s kubelet Successfully pulled image "soscscs/myapp:v1" in 18.054706565s Normal Created 66s (x3 over 6m13s) kubelet Created container liveness-httpget-container Warning Unhealthy 66s (x6 over 2m54s) kubelet Liveness probe failed: HTTP probe failed with statuscode: 404 Normal Killing 66s (x2 over 2m48s) kubelet Container liveness-httpget-container failed liveness probe, will be restarted Normal Pulled 66s (x2 over 2m48s) kubelet Container image "soscscs/myapp:v1" already present on machine Normal Started 65s (x3 over 6m13s) kubelet Started container liveness-httpget-container
容器中的存活探針失敗是因為 HTTP 探測返回了狀態(tài)碼 404,表示無法訪問到指定的路徑 /index.html。因此,容器被標記為不健康,被 Kubernetes 系統(tǒng)自動重新啟動以嘗試恢復其健康狀態(tài)。
2.4.3 定義 TCP 的存活探測
使用這種配置時,kubelet 會嘗試在指定端口和容器建立套接字鏈接。 如果能建立連接,這個容器就被看作是健康的,如果不能則這個容器就被看作是有問題的。
示例3:livenessProbe 規(guī)則,配合 tcpSocket 檢查方法。
① 編輯 pod 的 yaml 配置文件
[root@master01 demo]# vim demo5.yaml
apiVersion: v1
kind: Pod
metadata:
name: probe-tcp
spec:
containers:
- name: nginx
image: soscscs/myapp:v1
livenessProbe:
initialDelaySeconds: 5 # 容器啟動后等待 5 秒后開始執(zhí)行存活探針
timeoutSeconds: 1 # 探測超時時間為 1 秒
tcpSocket: # 使用 TCP 探測方式
port: 8080 # 探測的端口為 8080
periodSeconds: 10 # 每隔 10 秒執(zhí)行一次存活探針
failureThreshold: 2 # 如果連續(xù) 2 次探測失敗,則認為容器不健康上面的 YAML 文件描述了一個名為 probe-tcp 的 Pod,其中包含一個名為 nginx 的容器,使用鏡像 soscscs/myapp:v1,配置了一個針對端口 8080 的 TCP 探測器,用于檢測容器的健康狀態(tài)。由于業(yè)務本身端口是 80,所有這步就是探針肯定是失敗的,持續(xù)查看探針過程。
② 啟動 pod
[root@master01 demo]# kubectl apply -f demo5.yaml pod/probe-tcp created 使用kubectl工具在名為probe-tcp的容器中執(zhí)行netstat -natp命令: [root@master01 demo]# kubectl exec -it probe-tcp -- netstat -natp Active Internet connections (servers and established) Proto Recv-Q Send-Q Local Address Foreign Address State PID/Program name tcp 0 0 0.0.0.0:80 0.0.0.0:* LISTEN 1/nginx: master pr
③ 持續(xù)查看容器狀態(tài)詳情信息
[root@master01 demo]# kubectl get pod -w NAME READY STATUS RESTARTS AGE probe-tcp 0/1 Pending 0 0s probe-tcp 0/1 Pending 0 0s probe-tcp 0/1 ContainerCreating 0 0s probe-tcp 1/1 Running 0 2s probe-tcp 1/1 Running 1 18s probe-tcp 1/1 Running 2 38s probe-tcp 1/1 Running 3 57s probe-tcp 1/1 Running 4 78s # 由于探測8080端口失敗,可以看到 Pod 重啟了多次 # 理論上第一次重啟時間為:5+1+10=16秒 # 理論上第二次重啟時間為:+20秒 # 理論上第三次重啟時間為:+20秒 # 理論上第四次重啟時間為:+20秒
2.4.4 定義 readinessProbe 就緒探針
有時候,應用會暫時性地無法為請求提供服務。 例如,應用在啟動時可能需要加載大量的數(shù)據(jù)或配置文件,或是啟動后要依賴等待外部服務。 在這種情況下,既不想殺死應用,也不想給它發(fā)送請求。 Kubernetes 提供了就緒探針來發(fā)現(xiàn)并緩解這些情況。 容器所在 Pod 上報還未就緒的信息,并且不接受通過 Kubernetes Service 的流量。
示例4: readinessProbe 和 livenessProbe 規(guī)則,配合 httpGet 檢查方法。
① 編輯 pod 的 yaml 配置文件
[root@master01 demo]# vim demo6.yaml
apiVersion: v1
kind: Pod
metadata:
name: readiness-httpget
namespace: default
spec:
containers:
- name: readiness-httpget-container
image: soscscs/myapp:v1
imagePullPolicy: IfNotPresent
ports:
- name: http
containerPort: 80 # 指定容器將監(jiān)聽的端口為 80
readinessProbe: # 定義容器的就緒性探針
httpGet: # 指定用于就緒性檢查的 HTTP GET 請求
port: 80 # 指定進行就緒性檢查的端口(端口 80)
path: /index1.html # 指定就緒性檢查期間請求的路徑("/index1.html")
initialDelaySeconds: 1 # 指定容器啟動后開始就緒性探針的等待時間(1 秒)
periodSeconds: 3 # 指定連續(xù)就緒性探針之間的間隔(3 秒)
livenessProbe: # 定義容器的存活性探針
httpGet: # 指定用于存活性檢查的 HTTP GET 請求
port: http # 指定進行存活性檢查的端口("http"端口)
path: /index.html # 指定存活性檢查期間請求的路徑("/index.html")
initialDelaySeconds: 1 # 指定容器啟動后開始存活性探針的等待時間(1 秒)
periodSeconds: 3 # 指定連續(xù)存活性探針之間的間隔(3 秒)
timeoutSeconds: 10 # 指定存活性探針在等待響應的最大時間(10 秒)② 啟動 pod
[root@master01 demo]# kubectl apply -f demo6.yaml pod/readiness-httpget created
③ 查看容器狀態(tài)詳情信息
[root@master01 demo]# kubectl get pod NAME READY STATUS RESTARTS AGE readiness-httpget 0/1 Running 0 17s # 0/1表示該Pod中的容器當前處于未就緒狀態(tài) [root@master01 demo]# kubectl describe pod readiness-httpget Events: Type Reason Age From Message ---- ------ ---- ---- ------- Normal Scheduled 39s default-scheduler Successfully assigned default/readiness-httpget to node01 Normal Pulled 38s kubelet Container image "soscscs/myapp:v1" already present on machine Normal Created 38s kubelet Created container readiness-httpget-container Normal Started 38s kubelet Started container readiness-httpget-container Warning Unhealthy 3s (x12 over 36s) kubelet Readiness probe failed: HTTP probe failed with statuscode: 404 # 就緒性探針失敗,因為 HTTP 探測返回了狀態(tài)碼 404,由于就緒性探針配置中指定的路徑/index1.html不存在或有誤。
④ 創(chuàng)建 index1.html 頁面
[root@master01 demo]# kubectl exec -it readiness-httpget sh kubectl exec [POD] [COMMAND] is DEPRECATED and will be removed in a future version. Use kubectl exec [POD] -- [COMMAND] instead. / # echo "index1" > /usr/share/nginx/html/index1.html / # exit
⑤ 再次查看 pod 狀態(tài)
[root@master01 demo]# kubectl get pod NAME READY STATUS RESTARTS AGE readiness-httpget 1/1 Running 0 5m36s # 已就緒
⑥ 刪除原有 index.html,查看存活探針結果
[root@master01 demo]# kubectl get pod NAME READY STATUS RESTARTS AGE readiness-httpget 0/1 Running 1 9m32s [root@master01 demo]# kubectl describe pod readiness-httpget Warning Unhealthy 33s kubelet Liveness probe failed: HTTP probe failed with statuscode: 404 # 無法找到 index.html 頁面
2.4.5 多資源配置就緒檢測
下面這個 YAML 文件定義了三個名為 myapp1、myapp2 和 myapp3 的 Pod,它們使用相同的鏡像并具有相似的配置,以及一個名為 myapp 的 Service,用于將流量路由到這些 Pod 上的端口 80。
測試目的:readiness 探測失敗,pod 無法進入 ready 狀態(tài),則端點控制器會將 pod 從 endpoints 中剔除刪除該 pod 的 IP 地址。
示例5: readinessProbe 規(guī)則,配合 httpGet 檢查方法。
① 編輯 pod 的 yaml 配置文件
[root@master01 demo]# vim readiness-httpget.yaml
apiVersion: v1
kind: Pod
metadata:
name: myapp1
labels:
app: myapp
spec:
containers:
- name: myapp
image: soscscs/myapp:v1
ports:
- name: http
containerPort: 80 # 容器內部的端口號為 80
readinessProbe: # 定義了就緒性探針
httpGet: # 指定了使用 HTTP GET 請求進行探測
port: 80 # 指定了探測的端口為 80
path: /index.html # 指定健康檢查發(fā)送請求的路徑為 /index.html
initialDelaySeconds: 5 # 容器創(chuàng)建后等待 5 秒開始執(zhí)行健康檢查
periodSeconds: 5 # 每隔 5 秒進行一次健康檢查
timeoutSeconds: 10 # 健康檢查的超時時間為 10 秒
---
apiVersion: v1
kind: Pod
metadata:
name: myapp2
labels:
app: myapp
spec:
containers:
- name: myapp
image: soscscs/myapp:v1
ports:
- name: http
containerPort: 80
readinessProbe:
httpGet:
port: 80
path: /index.html
initialDelaySeconds: 5
periodSeconds: 5
timeoutSeconds: 10
---
apiVersion: v1
kind: Pod
metadata:
name: myapp3
labels:
app: myapp
spec:
containers:
- name: myapp
image: soscscs/myapp:v1
ports:
- name: http
containerPort: 80
readinessProbe:
httpGet:
port: 80
path: /index.html
initialDelaySeconds: 5
periodSeconds: 5
timeoutSeconds: 10
---
apiVersion: v1
kind: Service
metadata:
name: myapp
spec:
selector:
app: myapp
type: ClusterIP
ports:
- name: http
port: 80
targetPort: 80② 啟動 pod
[root@master01 demo]# kubectl apply -f readiness-httpget.yaml pod/myapp1 created pod/myapp2 created pod/myapp3 created service/myapp created
③ 查看 pod、svc 以及關聯(lián)后端的節(jié)點信息
[root@master01 demo]# kubectl get pod,svc,endpoints -o wide NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES pod/myapp1 1/1 Running 0 28s 10.244.1.27 node01 <none> <none> pod/myapp2 1/1 Running 0 28s 10.244.2.10 node02 <none> <none> pod/myapp3 1/1 Running 0 27s 10.244.1.28 node01 <none> <none> NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE SELECTOR service/kubernetes ClusterIP 10.96.0.1 <none> 443/TCP 10d <none> service/myapp ClusterIP 10.96.35.59 <none> 80/TCP 27s app=myapp service/nginx NodePort 10.96.75.23 <none> 80:32165/TCP 10d app=nginx service/nginx-deployment NodePort 10.96.101.251 <none> 30000:31603/TCP 9d app=nginx-deployment NAME ENDPOINTS AGE endpoints/kubernetes 192.168.190.100:6443 10d endpoints/myapp 10.244.1.27:80,10.244.1.28:80,10.244.2.10:80 27s endpoints/nginx <none> 10d endpoints/nginx-deployment 10.244.1.10:80,10.244.1.11:80,10.244.2.6:80 9d
④ 刪除 index.html
[root@master01 demo]# kubectl exec -it myapp3 -- rm -rf /usr/share/nginx/html/index.html
⑤ 再次查看關聯(lián)后端的節(jié)點
[root@master01 demo]# kubectl get pod,svc,endpoints -o wide NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES pod/myapp1 1/1 Running 0 2m42s 10.244.1.27 node01 <none> <none> pod/myapp2 1/1 Running 0 2m42s 10.244.2.10 node02 <none> <none> pod/myapp3 0/1 Running 0 2m41s 10.244.1.28 node01 <none> <none> NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE SELECTOR service/kubernetes ClusterIP 10.96.0.1 <none> 443/TCP 10d <none> service/myapp ClusterIP 10.96.35.59 <none> 80/TCP 2m41s app=myapp service/nginx NodePort 10.96.75.23 <none> 80:32165/TCP 10d app=nginx service/nginx-deployment NodePort 10.96.101.251 <none> 30000:31603/TCP 9d app=nginx-deployment NAME ENDPOINTS AGE endpoints/kubernetes 192.168.190.100:6443 10d endpoints/myapp 10.244.1.27:80,10.244.2.10:80 2m41s endpoints/nginx <none> 10d endpoints/nginx-deployment 10.244.1.10:80,10.244.1.11:80,10.244.2.6:80 9d
此時可以看到對于 readiness 探測失敗,pod myapp3 無法進入 reday 狀態(tài),端點控制器將 pod myapp3 的 ip 從 endpoints 中剔除刪除。
2.4.6 啟動和退出動作
以下將演示在 Kubernetes 中如何定義容器的生命周期事件,包括容器啟動后和終止前的操作,以及如何使用初始化容器來執(zhí)行特定任務。
示例6:根據(jù)日志反饋的內容了解容器處于生命周期的哪個階段
① 編輯 pod 的 yaml 配置文件
[root@master01 demo]# vim post.yaml
apiVersion: v1
kind: Pod
metadata:
name: lifecycle-demo
spec:
containers:
- name: lifecycle-demo-container
image: soscscs/myapp:v1
lifecycle: # 此為關鍵字段,定義容器的生命周期
postStart: # 容器啟動后執(zhí)行的操作
exec: # 使用執(zhí)行命令的方式
command: ["/bin/sh", "-c", "echo Hello Start >> /var/log/nginx/message"]
# 執(zhí)行的命令是往日志中寫入啟動信息
preStop: # 容器終止前執(zhí)行的操作
exec: # 使用執(zhí)行命令的方式
command: ["/bin/sh", "-c", "echo Hello Stop >> /var/log/nginx/message"]
# 執(zhí)行的命令是往日志中寫入停止信息
volumeMounts: # 掛載卷到容器內部
- name: message-log # 卷的名稱
mountPath: /var/log/nginx/ # 掛載路徑
readOnly: false # 是否只讀
initContainers: # 初始化容器
- name: init-myservice # 初始化容器的名稱
image: soscscs/myapp:v1 # 初始化容器使用的鏡像
command: ["/bin/sh", "-c", "echo 'Hello initContainers' >> /var/log/nginx/message"] # 初始化容器執(zhí)行的命令,往日志中寫入初始化信息
volumeMounts: # 掛載卷到容器內部
- name: message-log # 卷的名稱
mountPath: /var/log/nginx/ # 掛載路徑
readOnly: false # 是否只讀
volumes: # 定義卷
- name: message-log # 卷的名稱
hostPath: # 使用主機路徑
path: /data/volumes/nginx/log/ # 主機上的路徑
type: DirectoryOrCreate # 類型為目錄或創(chuàng)建② 啟動 pod
[root@master01 demo]# kubectl create -f post.yaml pod/lifecycle-demo created
③ 查看 pod 詳情
[root@master01 demo]# kubectl get pods -o wide NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES lifecycle-demo 1/1 Running 0 6s 10.244.1.29 node01 <none> <none>
④ 查看容器日志
[root@master01 demo]# kubectl exec -it lifecycle-demo -- cat /var/log/nginx/message Hello initContainers Start
由此可見,首先啟動了 init 容器,然后啟動成功后返回信息“Start”,代表啟動成功。
⑤ 在 node01 節(jié)點查看日志
[root@node01 ~]# cd /data/volumes/nginx/log/ [root@node01 log]# ls access.log error.log message [root@node01 log]# cat message Hello initContainers Start
⑥ 刪除 pod 后,再在 node01 節(jié)點上查看日志
[root@master01 demo]# kubectl delete pod lifecycle-demo pod "lifecycle-demo" deleted [root@node01 log]# cat message Hello initContainers Start Stop
由此課件,當在容器被終結之前, Kubernetes 將發(fā)送一個 preStop 事件,即探針關閉生命周期結束。
三、補充概念
3.1.pod 的狀態(tài)
- pending:pod已經(jīng)被系統(tǒng)認可了,但是內部的container還沒有創(chuàng)建出來。這里包含調度到node上的時間以及下載鏡像的時間,會持續(xù)一小段時間。
- Running:pod已經(jīng)與node綁定了(調度成功),而且pod中所有的container已經(jīng)創(chuàng)建出來,至少有一個容器在運行中,或者容器的進程正在啟動或者重啟狀態(tài)。--這里需要注意pod雖然已經(jīng)Running了,但是內部的container不一定完全可用。因此需要進一步檢測container的狀態(tài)。
- Succeeded:這個狀態(tài)很少出現(xiàn),表明pod中的所有container已經(jīng)成功的terminated了,而且不會再被拉起了。
- Failed:pod中的所有容器都被terminated,至少一個container是非正常終止的。(退出的時候返回了一個非0的值或者是被系統(tǒng)直接終止)
- unknown:由于某些原因pod的狀態(tài)獲取不到,有可能是由于通信問題。 一般情況下pod最常見的就是前兩種狀態(tài)。而且當Running的時候,需要進一步關注container的狀態(tài)
3.2.Container生命周期
- Waiting:啟動到運行中間的一個等待狀態(tài)。
- Running:運行狀態(tài)。
- Terminated:終止狀態(tài)。 如果沒有任何異常的情況下,container應該會從Waiting狀態(tài)變?yōu)镽unning狀態(tài),這時容器可用。
但如果長時間處于Waiting狀態(tài),container會有一個字段reason表明它所處的狀態(tài)和原因,如果這個原因很容易能標識這個容器再也無法啟動起來時,例如ContainerCannotRun,整個服務啟動就會迅速返回。(這里是一個失敗狀態(tài)返回的特性,不詳細闡述)
總結
以上為個人經(jīng)驗,希望能給大家一個參考,也希望大家多多支持腳本之家。
相關文章
k8s?clientConfig和rawConfig區(qū)別解析
k8s clientConfig和rawConfig區(qū)別k8s.io/client-gov0.28.2基于kubeconfig可以創(chuàng)建clientConfig和rawConfig,兩者區(qū)別在于,clientConfig包含了訪問kube-apiserver的地址和認證鑒權信息,感興趣的朋友一起看看吧2025-03-03
tkestack/gpu-manager在k8s1.23版本之后的使用方法
這篇文章主要介紹了tkestack/gpu-manager在k8s1.23版本之后的使用,本文給大家介紹的非常詳細,對大家的學習或工作具有一定的參考借鑒價值,需要的朋友可以參考下2023-04-04
Rancher部署配置開源Rainbond云原生應用管理平臺
這篇文章主要為大家介紹了Rancher部署配置開源Rainbond云原生應用管理平臺,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進步,早日升職加薪2022-04-04

