Kubernetes-應用部署問題定位和處理

HitTwice發表於2018-08-23

作者:Daniel_Ji 來源: Kubernetes 中文社群

原文連結: https://www.kubernetes.org.cn/4354.html

1、應用部署問題處理的整體思路

在將容器化的應用部署到Kubernetes叢集中,可能會出現各種問題。根據Kubernetes的架構設計原理,容器化應用對外提供服務出現的主要問題在三個點上:

1) 應用本身的問題 :此問題為應用本身的問題,不在此文中進行詳細的闡述;

2) 作為容器化應用邏輯主機的Pod的問題 :此部分的問題主要涉及到容器化應用是否在容器雲中正常部署和執行,這裡會涉及到CPU、記憶體、儲存資源等問題;

3) 代理容器化應用服務的問題 :第三方服務或使用者會通過代理服務訪問容器化應用,如果代理服務存在問題,則容器雲應用將無法對外提供服務能力,這裡會涉及到服務是否存在、DNS解析是否正確等問題。

在本文中,以部署的高可用MySQL(請參考: Kubernetes-部署高可用的MySQL )為例展示如何進行問題定位和處理。另外為了能夠在Kubernetes叢集外訪問MySQL資料庫,對外暴露了MySQL master的NodePort型別服務,服務名稱為mysql-0-svc。

2、除錯Pods

在除錯Pod之前,通過kubectl get pods命令檢視一下Pod的執行狀態。

$ kubectl get pods --namespace=kube-public

對於特定的Pod,可以通過kubectl describe pods命令檢視詳細的資訊。

$ kubectl describe pods/mysql-0 --namespace=kube-public

在Pod的生命週期中,有如下的幾個狀態:

  • Pending: Pod已經被Kubernetes系統接受,但是還有一個或者多個容器映象未被建立。這包括Pod正在被排程和從網路上下載映象的時間。

  • Running: Pod已經被繫結到了一個Node,所有的容器也已經被建立。至少有一個容器已經在執行,或者在啟動或者重新啟動的過程中。

  • Succeeded: 在Pod中的所有的容器都已經被成功的終止,並且不會再重啟。

  • Failed: 在Pod中所有容器都已經被終止,並且至少有一個容器是非正常終止的。即,容器以非零狀態退出或者被系統強行終止的。

  • Unknown: 由於某些原因,Pod不能被獲取,典型的情況是在與Pod的主機進行通訊中發生了失敗。

  • Waiting:由於某些原因,Pod已被排程到了Node節點上,但無法正常執行。

  • Crashing:由於某些原因,Pod處於崩潰狀態。

根據Pod所處的狀態,相應的處理方式不同。

2.1 Pod處於待命(Pending)狀態

如果Pod被卡在待命(Pending)狀態,則意味著它無法被安排到Node節點上。造成這種情況通常因為某種型別的資源不足,從而導致Pod無法被排程。通過檢視 kubectl describe … 命令的輸出內容,應該有為什麼Pod無法被排程的原因。這些原因包括:

  • 沒有足夠的資源 :叢集中的CPU或記憶體可能已經耗盡了,在這種情況下,需要刪除Pod,調整資源請求或向叢集中新增新的Node節點。

  • 正在使用 hostPort :將Pod繫結到了數量有限的hostPort。在大多數情況下,沒有必要使用hostPort,可以嘗試使用服務來暴露Pod。如果確實需要hostPort,那麼只能排程與Kubernetes叢集中的節點一樣多的Pod。

2.2 Pod處於等待(Waiting)狀態

如果Pod處於等待(Waiting)狀態,則它已被排程到一個工作Node上,但它無法在該Node上執行。同樣,通過 kubectl describe … 應該是能夠獲取有用的資訊。處於等待(Waiting)狀態的最常見的原因是 無法拉取映象 。有三件事需要檢查:

  • 確保映象名稱正確無誤。

  • 確認映象倉庫中是否存在此映象?

  • 在機器上,執行 docker pull <image> 命令,檢視是否可以拉取映象。

2.3 Pod崩潰(Crashing)或其他不健康

首先,通過執行 kubectl logs ${POD_NAME} ${CONTAINER_NAME} 檢視當前容器的日誌:

$ kubectl logs mysql-0 mysql --namespace=kube-public

如果容器之前已崩潰,可以使用以下命令訪問上一個容器的崩潰日誌:

$ kubectl logs --previous mysql-0 mysql --namespace=kube-public

或者,也可以使用 kubectl exec 在該容器內執行命令:

$ kubectl exec ${POD_NAME} -c ${CONTAINER_NAME} -- ${CMD} ${ARG1} ${ARG2} ... ${ARGN}

請注意,這-c ${CONTAINER_NAME}是可選的,對於僅包含單個容器的Pod,可以省略。

如果這些方法都不起作用,可以找到執行該pod的主機,並通過SSH連線到該主機。

2.4 Pod正在執行,但沒有按照要求執行

如果Pod沒有按預期執行,可能是Pod描述中存在錯誤,並且在建立Pod時忽略了該錯誤。通常可能是,Pod描述的一部分巢狀不正確,或鍵名不正確,因此鍵被忽略。例如,如果拼寫錯誤command,commnd則將建立Pod,但不會按照希望使用命令列。

首先,要做的第一件事是刪除此Pod,並嘗試使用–validate選項再次建立它。例如,執行 kubectl create –validate -f mypod.yaml 。如果拼寫錯誤command,commnd那麼會出現如下錯誤:

I0805 10:43:25.129850   46757 schema.go:126] unknown field: commnd
I0805 10:43:25.129973   46757 schema.go:129] this may be a false alarm, see https://github.com/kubernetes/kubernetes/issues/6842pods/mypod

接下來,要檢查的是apiserver上的Pod是否與要建立的Pod相匹配。例如,執行 kubectl get pods/mypod -o yaml > mypod- on-apiserver.yaml,然後將原始的Pod描述mypod.yaml與從apiserver返回的描述檔案mypod-on-apiserver.yaml進行比較。“apiserver”版本通常會有一些不在原始版本上的內容,這不影響。但是,如果原始版本上有不在apiserver版本上的行,則可能意味著原始版本Pod描述規範存在問題。

3、除錯代理服務

根據Kubernetes的架構設計,使用者或其它應用通過代理服務訪問容器化應用。因此需要通過除錯確認代理服務是否正常,需要做的工作包括:

1)檢查代理服務本身是否存在;

2)檢查代理服務是否能夠正常通過DNS進行解析;

3)檢查代理服務本身是否正確。

3.1 檢查服務是否存在

在除錯服務時,第一步要做的就是檢查服務是否存在。在本文的前面說明了,在Kubernetes中通過NodePort型別對外暴露了MySQL master。通過執行 kubectl get svc 命令,可以獲取是否存在相應服務:

$ kubectl get svc/mysql-0-svc --namespace=kube-public

通過返回的結果可以看出,在Kubernetes叢集中存在此服務。

3.2 能否通過DNS解析正常解析代理服務

對於處於同一個名稱空間的容器化應用,可以直接通過代理服務的名稱(mysql-0-svc)訪問MySQL master。

$ kubectl exec -it redis-ha-redis-ha-sentinel-5947b9569-r2b56 --namespace=kube-public -- nslookup mysql-0-svc

對Kubernetes叢集中不同名稱空間的容器化應用,則需要通過新增名稱空間名稱後(mysql-0-svc.kube-public)訪問MySQL master:

$ kubectl exec -it gf1-6497d5df45-98g8v -- nslookup mysql-0-svc.kube-public

根據返回的可以看出,通過DNS能夠正確的解析代理服務。

3.2.1 DNS是否正常工作

如果通過上述的操作都無法正常解析服務,通過 kubectl exec -it  ${POD_NAME}  — nslookup 命令檢查一下Kubernetes master是否正常工作:

$ kubectl exec -it gf1-6497d5df45-98g8v -- nslookup kubernetes.default

如果此操作也失敗,則需要檢查Kubernetes叢集中的DNS服務是否正常執行。

3.3 代理服務本身是否正確

如果代理服務也存在,DNS解析也沒有問題。則需要檢查一下代理服務本身是否有問題:

$ kubectl get service mysql-0-svc -o yaml --namespace=kube-public

例如訪問的埠是否正確?targetPort是否指向了正確的Pods埠?這裡的埠協議是否與Pod暴露出來的埠協議一致等。

參考材料

1.《Debug Services》地址:https://kubernetes.io/docs/tasks/debug-application-cluster/debug-service/#does-the-service-work-by-ip

2.《Troubleshooting》地址:https://kubernetes.io/docs/tasks/debug-application-cluster/troubleshooting/

3.《Application Introspection and Debugging》地址:https://kubernetes.io/docs/tasks/debug-application-cluster/debug-application-introspection/

4.《Troubleshoot Applications》地址:https://kubernetes.io/docs/tasks/debug-application-cluster/debug-application/

作者簡介:
季向遠,北京神舟航天軟體技術有限公司。本文版權歸原作者所有。

來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/31473948/viewspace-2212675/,如需轉載,請註明出處,否則將追究法律責任。

相關文章