新聞中心
即使在高成熟度級別 Kubernetes 集群中 pod pending 也是無處不在。

創(chuàng)新互聯(lián)建站是一家朝氣蓬勃的網(wǎng)站建設(shè)公司。公司專注于為企業(yè)提供信息化建設(shè)解決方案。從事網(wǎng)站開發(fā),網(wǎng)站制作,網(wǎng)站設(shè)計(jì),網(wǎng)站模板,微信公眾號開發(fā),軟件開發(fā),小程序設(shè)計(jì),十載建站對輕質(zhì)隔墻板等多個(gè)行業(yè),擁有多年的網(wǎng)站設(shè)計(jì)經(jīng)驗(yàn)。
如果您隨機(jī)詢問任何使用 Kubernetes DevOps 工程師來確定折磨他們噩夢的最常見錯(cuò)誤,pod pending 可能是非常常見的問題(可能僅次于 CrashLoopBackOff)。
嘗試推送更新并看到它卡住會(huì)使 DevOps 緊張。即使解決方案相當(dāng)簡單,找到 pod 掛起的原因并了解您需要應(yīng)用的更改也很重要(Kubernetes 故障排除很少是微不足道的)。
在本文中,我們將闡明導(dǎo)致此問題的不同情況,讓 DevOps 團(tuán)隊(duì)能夠快速找到解決方案,最重要的是,盡可能避免它。
Kubernetes Pod pending 是什么意思?
Kubernetes 中的 Pod 的生命周期由幾個(gè)不同的階段組成:
- 創(chuàng)建 pod 時(shí),它從Pending階段開始。
- 一旦 pod 被調(diào)度并且容器已經(jīng)啟動(dòng),pod 就會(huì)進(jìn)入Running階段。
大多數(shù) pod 只需要幾秒鐘就可以從 Pending 到 Running 并在該狀態(tài)下度過大部分時(shí)間。
至此,Pod 已被 Kubernetes 集群接受。但是一個(gè)或多個(gè)容器尚未準(zhǔn)備好對外提供服務(wù)。這包括 Pod 等待調(diào)度所花費(fèi)的時(shí)間以及通過網(wǎng)絡(luò)下載容器鏡像所花費(fèi)的時(shí)間。
當(dāng) pod 無法從 PendingtoRunning 階段前進(jìn)時(shí),生命周期將停止并保留 pod,直到阻止它前進(jìn)的問題得到修復(fù)。
如果我們使用 kubectl 列出 pod,我們將看到顯示 Kubernetes pod 掛起情況的輸出:
$ kubectl -n troubleshooting get pods
NAME READY STATUS RESTARTS AGE
stress-6d6cbc8b9d-s4sbh 0/1 Pending 0 17s除非我們解決問題,否則 pod 被卡住并且不會(huì)運(yùn)行。
排查 Kubernetes pod Pending 的常見原因
有幾個(gè)原因可以阻止 Pod 運(yùn)行,但我們將描述三個(gè)主要問題:
- 調(diào)度問題:無法在任何節(jié)點(diǎn)上調(diào)度 Pod。
- 鏡像問題:下載容器鏡像時(shí)出現(xiàn)問題。
- 依賴性問題:Pod 需要一個(gè)卷、Secret 或 ConfigMap 才能運(yùn)行。
第一個(gè)是最常見的,最后一個(gè)很少見。讓我們詳細(xì)說明每種情況。
調(diào)度問題導(dǎo)致 Kubernetes Pod Pending
創(chuàng)建 Pod 后,Kubernetes 集群做的第一件事就是嘗試調(diào)度 Pod 在其中一個(gè)節(jié)點(diǎn)上運(yùn)行。這個(gè)過程通常非??欤⑶?pod 被快速分配給具有足夠資源來運(yùn)行它的節(jié)點(diǎn)。
為了放置它,集群中的 Pod 被分配給具有更多未請求資源的節(jié)點(diǎn),并繼續(xù)其快樂而美好的生活,其中充滿了對請求的符合 SLO 的回復(fù)。
但是,如果此過程每次都有效,有幾個(gè)因素可能導(dǎo)致集群無法分配 pod。
讓我們回顧一下最常見的。
任何節(jié)點(diǎn)中都沒有足夠的資源來分配 pod
Kubernetes 使用調(diào)度請求來決定fits節(jié)點(diǎn)中是否有 pod。資源的真正使用無關(guān)緊要,只有其他 pod 已經(jīng)請求的資源。
effective requests當(dāng)一個(gè) pod 有足夠的可請求資源來參與該 pod 的內(nèi)存和 CPU 時(shí),它將被調(diào)度到一個(gè)節(jié)點(diǎn)中。并且節(jié)點(diǎn)必須沒有達(dá)到它可以運(yùn)行的最大 pod 數(shù)。
當(dāng)沒有任何節(jié)點(diǎn)滿足 pod 的所有要求時(shí),它將保持在 Kubernetes pod 掛起狀態(tài),直到釋放一些資源。
不可調(diào)度的節(jié)點(diǎn)
由于不同的問題(節(jié)點(diǎn)壓力)或人為行為(節(jié)點(diǎn)封鎖),節(jié)點(diǎn)可能會(huì)變?yōu)椴豢烧{(diào)度的狀態(tài)。這些節(jié)點(diǎn)在狀態(tài)發(fā)生變化之前不會(huì)調(diào)度任何 pod。
污點(diǎn)和容忍度
污點(diǎn)是 Kubernetes 的一種機(jī)制,它允許我們限制可以分配給不同節(jié)點(diǎn)的 pod。當(dāng)節(jié)點(diǎn)具有 taint 時(shí),只有匹配容忍度的 pod 才能在該節(jié)點(diǎn)中運(yùn)行。
這種機(jī)制允許 Kubernetes 的特殊用途,例如為不同的工作負(fù)載使用不同類型的節(jié)點(diǎn)(具有 GPU 的節(jié)點(diǎn),具有不同的 CPU/內(nèi)存比率等)。
即使我們分別描述每個(gè)原因,調(diào)度問題也往往是由這些問題的組合引起的。通常,您無法調(diào)度,因?yàn)槟承┕?jié)點(diǎn)已滿而其他節(jié)點(diǎn)已被污染,或者某個(gè)節(jié)點(diǎn)可能由于內(nèi)存壓力而無法調(diào)度。
為了找出調(diào)度問題是什么,您需要查看調(diào)度程序生成的關(guān)于 pod 的事件,其中將詳細(xì)描述阻止節(jié)點(diǎn)分配的原因。我們可以使用 kubectl describe 查看事件,例如:
$ kubectl -n troubleshooting describe pod stress-6d6cbc8b9d-s4sbh
Name: stress-6d6cbc8b9d-s4sbh
Namespace: troubleshooting
Priority: 0
Node:
Labels: app=stress
pod-template-hash=6d6cbc8b9d
Annotations:
Status: Pending
IP:
IPs:
Controlled By: ReplicaSet/stress-6d6cbc8b9d
Containers:
stress:
Image: progrium/stress
Port:
Host Port:
Args:
--cpu
1
--vm
2
--vm-bytes
150M
Limits:
cpu: 300m
memory: 120000Mi
Requests:
cpu: 200m
memory: 100000Mi
Environment:
Mounts:
/var/run/secrets/kubernetes.io/serviceaccount from kube-api-access-snrww (ro)
Conditions:
Type Status
PodScheduled False
Volumes:
kube-api-access-snrww:
Type: Projected (a volume that contains injected data from multiple sources)
TokenExpirationSeconds: 3607
ConfigMapName: kube-root-ca.crt
ConfigMapOptional:
DownwardAPI: true
QoS Class: Burstable
Node-Selectors:
Tolerations: node.kubernetes.io/not-ready:NoExecute op=Exists for 300s
node.kubernetes.io/unreachable:NoExecute op=Exists for 300s
Events:
Type Reason Age From Message
---- ------ ---- ---- -------
Warning FailedScheduling 4m17s (x41 over 34m) default-scheduler 0/5 nodes are available: 1 node(s) had taint {node-role.kubernetes.io/master: }, that the pod didn't tolerate, 4 Insufficient memory. 我們可以在輸出中看到消息中的確切原因:
0/5 nodes are available: 1 node(s) had taint {node-role.kubernetes.io/master: }, that the pod didn't tolerate, 4 Insufficient memory.
- 其中一個(gè)節(jié)點(diǎn)被污染。
- 其中四個(gè)節(jié)點(diǎn)沒有足夠的可請求內(nèi)存。
為了解決這個(gè)問題,我們有兩個(gè)選擇:
- 減少 pod 定義中的資源請求大小。
- 通過添加更多節(jié)點(diǎn)或增加每個(gè)節(jié)點(diǎn)的大小來增加集群的容量。
如果要更新當(dāng)前運(yùn)行的工作負(fù)載,還需要考慮另一個(gè)重要因素:升級策略。
由于此策略,Kubernetes 可以允許工作負(fù)載在更新過程中創(chuàng)建比平時(shí)更多的 Pod,在創(chuàng)建新 Pod 時(shí)保留舊 Pod 一段時(shí)間。這意味著工作負(fù)載可能會(huì)在一段時(shí)間內(nèi)請求比預(yù)期更多的資源。如果集群沒有足夠的備用資源,更新將被阻塞,留下一些 pod 待處理,直到進(jìn)程被解除阻塞(或回滾超時(shí)停止更新)。
由于鏡像問題,Pod Pending
一旦在一個(gè)節(jié)點(diǎn)中分配了 pod,kubelet就會(huì)嘗試啟動(dòng) pod 中的所有容器。為此,它將嘗試下載鏡像并運(yùn)行它。
有幾個(gè)錯(cuò)誤會(huì)阻止鏡像被下載:
- 鏡象名稱錯(cuò)誤。
- 錯(cuò)誤的鏡像標(biāo)簽。
- 錯(cuò)誤的存儲(chǔ)倉庫。
- 存儲(chǔ)倉庫需要身份驗(yàn)證。
Kubernetes Pod 由于依賴問題而掛起
在 pod 啟動(dòng)之前,kubelet將嘗試檢查與其他 Kubernetes 元素的所有依賴關(guān)系。如果無法滿足這些依賴項(xiàng)之一,則 pod 將保持掛起狀態(tài),直到滿足依賴項(xiàng)。
在這種情況下,kubectl 將像這樣顯示 pod:
$ kubectl -n mysql get pods
NAME READY STATUS RESTARTS AGE
mysql-0 0/1 ContainerCreating 0 97s在事件中,我們可以看到如下內(nèi)容:
Events:
Type Reason Age From Message
---- ------ ---- ---- -------
Normal Scheduled 3m19s default-scheduler Successfully assigned mysql/mysql-0 to ip-172-20-38-115.eu-west-1.compute.internal
Warning FailedMount 76s kubelet Unable to attach or mount volumes: unmounted volumes=[config], unattached volumes=[kube-api-access-gxjf8 data config]: timed out waiting for the condition
Warning FailedMount 71s (x9 over 3m19s) kubelet MountVolume.SetUp failed for volume "config" : configmap "mysql" not found該 Message 列將為您提供足夠的信息,以便能夠查明缺失的元素。常見的原因有:
- 尚未創(chuàng)建 ConfigMap 或者 Secret,或提供的名稱不正確。
- 無法在節(jié)點(diǎn)中掛載卷,因?yàn)樗形幢涣硪粋€(gè)節(jié)點(diǎn)釋放。這尤其發(fā)生在更新 statefulset 的過程中,掛載的卷必須與舊 pod 相同。
結(jié)論
了解 pod 保持在該 Pending 階段的原因是在 Kubernetes 中安全部署和更新工作負(fù)載的關(guān)鍵。能夠快速定位問題并加快部署進(jìn)度將為您省去一些麻煩并減少停機(jī)時(shí)間。
網(wǎng)頁標(biāo)題:徹底搞懂K8SPodPending故障原因及解決方案
瀏覽路徑:http://www.dlmjj.cn/article/djopdoi.html


咨詢
建站咨詢
