Kubernetes 應用故障的一些定位方法_Kubernetes中文社群
常備工作
準備一個工具映象
其中包含 nslookup, ping, curl, 甚至是 ab、siege 等常用工具以及一個順手的 Shell。一言不合就可以用靜態 Pod 的方式將其執行到 Kubernetes 之中進行內部診斷。
sysctl -a | grep forwarding
你猜這是幹啥的?
服務狀態查詢
各個 Kubernetes 元件的狀態檢查。可以使用 Ansible 之類的工具進行快速查詢。
Service 不通
這裡我們首先假設 Pod 工作正常
目前我們的應用均採用的是 NodePort 模式對外提供服務:
- 邏輯:Service 將 符合其選擇器的 Pod 暴露的埠
- 技術:Kube-proxy 通過網路外掛,一般利用 Iptables vxLan 等烏七八糟的蜜汁技術,完成對外服務負載均衡,並分發給各個 Pod 的內部 IP 的相應埠。
前面我們假設 Pod 是正常工作的,因此,這裡只考慮 Service 的情況。
通過上面的陳述我們能看到大致的一些要素,下面從內向外進行列表:
Pod 能夠正常工作
見後文
Service 的選擇器能夠正確的找到 Pod
這裡我們可以使用kubectl describe svc panic-service
命令,檢視輸出內容的endpoint
一節內容,如果其中有 Pod 地址,也就說明選擇器和 Pod 的標籤是匹配的。如果為空,則需要對服務或者 Pod Controller 的定義進行排查。
Proxy 的工作狀態
- 首先可以使用
systemctl -l Kube-proxy
來檢視服務狀況。 - 還可以使用其他 Node 的同一埠測試訪問,看是否單一節點的故障。
DNS 工作狀態
Kubectl 檢視 DNS 各個 Pod 的存活狀態。
利用上面提到的工具 Pod 嘗試解析服務。失敗了其實也沒啥辦法,刪 DNS Pod 重啟吧。
埠是否定義正確
看 Pod 的埠是否能夠正確偵聽,是否符合服務定義。例如 Service 定義了到 Pod 8080 埠的訪問,而 Pod 開放的卻是 80,這樣的情況跟標籤無法匹配一樣,是很常見的問題。
說完了服務,我們來說說 Pod
兩個順手的命令:
kubectl get po -o wide | grep -v Running
kubectl describe po unhealthy
一般來說,一個行為端正的 Pod,應該是以 Running 狀態持續執行的。在進入 Running 之前,大致有排程、建立、初始化等幾個環節,如果正常執行之後出了故障,會發生重啟。如果在啟動容器內程序時出現問題,則會進入 CrashLoopBackOff 的狀態。
除了 Running/Complet 以及 CrashLoopBackOff:
這幾種情況其實不同,不過隨性寫到這,就不深究了,首先是 describe 一下。
Pod 啟動有幾個條件:
- 有符合要求的節點供其執行
- Taint 隔離的節點,要求 Pod 有顯式宣告對該種 Taint 的容錯能力,才可以在其上執行。
- 節點和 Pod 的親和性定義
- Node Selector 的定義
- 符合其需求的資源
- CPU 和 記憶體的 request limit 定義
- 可能存在的第三方資源需求定義
- 載入卷(nfs gluster ceph 等)/Secret/Configmap 的定義
- 映象必須存在,可 Pull
排程部分一般來說檢視 Pod 定義,和節點的 Describe 進行匹配即可,Describe 內容中也會明確說出無合適 Pod。
資源部分 CPU 和記憶體的 Describe 結果也會很明顯。
儲存部分,往往就需要更復雜的排查:
- 首先看看是不是每個 Node 都如此。
- 是否安裝了對應的客戶端驅動。
- 對分散式儲存的訪問網路是否可用。
- 儲存服務容量是否足夠分配。
- 是否能夠成功的手工 Mount。
至於對 ConfigMap 和 Secret 的依賴,很簡單,Kubectl 查詢即可。
CrashLoopBackOff 以及 Restart 大於 1
這種情況一般來說屬於業務內部的問題,可以通過 kubectl logs -f
命令進行檢視,目前經驗比較多的非業務情況是:
- 對於 Kubernetes API 進行訪問的應用,經常會是因為RBAC 許可權不足導致無法啟動
- 依賴的 Service 無法訪問。