【圖解】Kubernetes Deployment 故障排查指南
來源:K8sMeetup社區(qū)
太長不看版:下面這張圖可以幫助你調(diào)試 Kubernetes 中的 Deployment。

Deployment:創(chuàng)建 Pod 副本的方法; Service:內(nèi)部負載均衡器,將流量路由到 Pod; Ingress:描述流量如何從外部集群流向 Service;
Kubernetes 中應(yīng)用程序通過內(nèi)部和外部兩層負載均衡器暴露
內(nèi)部負載均衡器叫 Service,外部負載均衡器叫 Ingress

假設(shè)你希望部署一個簡單的 Hello World 應(yīng)用程序,這個應(yīng)用程序的 YAML 應(yīng)該類似于如下內(nèi)容:

何時應(yīng)使用端口 80,何時應(yīng)使用端口 8080? 是否應(yīng)該為每個服務(wù)創(chuàng)建一個新端口,以免沖突? 標簽(label)名稱重要嗎?應(yīng)該保持標簽名稱一致嗎?
令人驚訝的是,Deployment 和 Service 之間根本沒有連接。相反,Service 直接指向 Pod,完全跳過了 Deployment。因此,你應(yīng)該關(guān)注的是 Pod 和 Service 之間是如何相互關(guān)聯(lián)的。
請記住以下三件事:
Service selector 應(yīng)至少匹配 Pod 的一個標簽;
Service 的
targetPort應(yīng)該與 Pod 的containerPort匹配;Service 端口可以是任何數(shù)字。多個 Service 可以使用同一個端口,因為每個 Service 分配到的 IP 地址不同;
下圖總結(jié)了如何連接端口:

在創(chuàng)建 Pod 時,需要為 Pod 中的每個容器定義端口 containerPort
創(chuàng)建 Service 時,可以定義 port 和 targetPort。但是哪一個應(yīng)該和容器連接呢

targetPort 和 conatinerPort 需始終匹配

targetPort 應(yīng)該也是 3000port/targetPort 應(yīng)該是匹配的。
track:canary 標簽?zāi)兀恳惨ヅ渖蠁幔?/span>matchLables selector 呢?它必須始終與 Pod 的標簽匹配,Deployment 用它來跟蹤 Pod。

any-name=my-app是any-name:my-app標簽。port-forward 命令來連接到 Service 并測試該連接。
service/<service name>是 service 的名稱(在當(dāng)前的 YAML 文件中是 "my service")。3000 是你想在計算機上開啟的端口。 80 是由 Service 在 port字段中暴露的端口。
Ingress 的 service.port必須匹配 Service 的port。Ingress 的 service.name必須匹配 Service 的name。
你已經(jīng)知道了 Service 會暴露一個 port
Ingress 有一個字段叫做 ServicePort
Service 的 port 和 Ingress 的 ServicePort 必須始終匹配
如果你要把端口 80 分配給一個 Service,必須把 ServicePort 也改成 80

kubectl port-forward,但是要注意是連接到 Ingress controller 而不是 Service。


Service selector 應(yīng)該和 Pod 的標簽匹配; Service 的 targetPort應(yīng)該和 Pod 里面容器的containerPort匹配;Service 端口可以是任意數(shù)字。多個 Service 可以使用同一個端口,因為不同的 Service 分配的 IP 地址不同; Ingress 的 service.port應(yīng)該和 Service 的port匹配;Service 的名稱應(yīng)該和 Ingress 中 service.name字段匹配;
確保 Pod 正在運行; 著重關(guān)注讓 Service 將流量路由到 Pod; 檢查 Ingress 的配置是否正確。
應(yīng)該從最底層開始為 Deployment 做故障排查。首先,檢查 Pod 是否已就緒并在運行中
如果 Pod 已就緒,應(yīng)該檢查 Service 是否能將流量路由到 Pod
最后,檢查 Service 和 Ingress 之間的連接
排查 Pod 故障

kubectl logs <pod name>有助于檢索 Pod 中容器的日志;kubectl describe pod <pod name>對檢索與 Pod 相關(guān)的事件列表很有用;kubectl get pod <pod name>可提取 Kubernetes 中存儲的 Pod 的 YAML 定義;kubectl exec -ti <pod name> bash可在 Pod 中的一個容器運行一個交互式命令。
常見的 Pod 報錯
ImagePullBackoff ImageInspectError ErrImagePull ErrImageNeverPull RegistryUnavailable InvalidImageName
CrashLoopBackOff RunContainerError KillContainerError VerifyNonRootError RunInitContainerError CreatePodSandboxError ConfigPodSandboxError KillPodSandboxError SetupNetworkError TeardownNetworkError
ImagePullBackOff
鏡像名稱無效——比如,你拼錯了鏡像名稱,或者鏡像不存在。 為鏡像指定了一個不存在的標簽。 正在檢索的鏡像屬于私有 registry,Kubernetes 沒有訪問的憑證。
CrashLoopBackOff
應(yīng)用程序中存在錯誤,阻止了容器的啟動; 容器配置有誤:StackOverFlow 上這個問題就是如此 https://stackoverflow.com/questions/41604499/my-kubernetes-pods-keep-crashing-with-crashloopbackoff-but-i-cant-find-any-lo Liveness 探針失敗多次。

RunContainerError
掛載不存在的卷,如 ConfigMap 或 Secret; 將只讀卷掛載為讀寫卷。
kubectl describe pod <pod-name> 命令檢查和分析這個錯誤。Pod 處于 Pending 的狀態(tài)
集群沒有足夠的資源(例如 CPU 和內(nèi)存)來運行 Pod。 當(dāng)前的命名空間具有 ResourceQuota 對象,創(chuàng)建 Pod 將使命名空間超過配額。 該 Pod 綁定了一個處于 Pending 狀態(tài)的 PersistentVolumeClaim。
kubectl describe 命令中檢查事件。

Pod 處于未就緒狀態(tài)
kubectl describe 中的“事件”以驗證錯誤。排查 Service 故障

<ip address:port> ,當(dāng) Service 定位到一個 Pod 后,至少應(yīng)該有一個 Endpoint。正在運行的 Pod 沒有正確的標簽(應(yīng)該檢查一下是否在正確的命名空間中); Service 的 selector標簽拼寫有誤。
targetPort 可能出問題了。如何測試 Service 呢?無論什么類型的 Service,都可以用 kubectl port-forward 來連接:
<service-name>是 Service 的名稱;3000是你想在計算機上打開的端口;80是 Service 暴露的端口。
Pod 在運行中且是就緒狀態(tài); Service 可以分發(fā)流量分配到 Pod。
service.name 和 service.port 連接到 Service。應(yīng)該檢查一下這些配置是否正確。
將 Ingress 暴露到公網(wǎng)的方式; 將集群暴露到公網(wǎng)的方式;


最后,連接到 Pod:

如果解決了,那么就是基礎(chǔ)設(shè)施問題。你要看一下流量是如何路由到集群的。 如果沒有解決,那么是 Ingress controller 的問題,你應(yīng)該調(diào)試 controller。
調(diào)試 Ingress Nginx
kubectl ingress-nginx 來進行如下操作:檢查日志、Backend、證書等; 連接到 Ingress; 檢查當(dāng)前配置。
kubectl ingress-nginx lint:用于檢查nginx.conf;kubectl ingress-nginx backend:用于檢查 Backend(類似kubectl describe ingress <ingress-name>);kubectl ingress-nginx logs:用于檢查日志。
請注意,你可能需要使用 --namespace
為 Ingress controller 指定正確的命名空間。
出現(xiàn)故障的 Job 和 CronJob; StatefulSet 和 DaemonSet。
- END -
公眾號后臺回復(fù)「加群」加入一線高級工程師技術(shù)交流群,一起交流進步。
推薦閱讀 讓運維簡單高效,輕松搞定運維管理平臺 備份和遷移 Kubernetes 利器:Velero 搭建一套完整的企業(yè)級 K8s 集群(v1.20,二進制方式) 記一次 Kubernetes 機器內(nèi)核問題排查 Shell 腳本進階,經(jīng)典用法及其案例 Kubernetes 集群網(wǎng)絡(luò)從懵圈到熟悉 記一次 Linux服務(wù)器被入侵后的排查思路 5個面試的關(guān)鍵技巧,助你拿到想要的offer!
點亮,服務(wù)器三年不宕機


