Kubernates Pod無法啓動問題分析排查

一、問題背景

近期遇到一個特別奇怪的事就是關於 K8s Pod 無法啓動的問題,因爲平時通過 Jenkins 打包成 Docker 後,再自動觸發已經建好的 Pipline 就可以部署到 Kubernates 平臺,但這次打包後發現部署應用到 Kubernates 時 Pod 總無法創建成功,然後 Pod 自動重新部署。

二、原因排查

排查問題的路徑有:

  • 通過查看 Kubernates 容器組中事件排查 Pod 無法起來的原因,類似於下面這張圖
    在這裏插入圖片描述
  • 通過查看應用的最後打印日誌排查問題;在這要說一句,在通過Pod 打印的日誌排查問題是,有時應用日誌刷的時快時慢,看不到最後打印的日誌信息(Pod 重啓後會將上一次日誌清掉)需要有耐心,不可太急躁,覺得實在太慢可以將 Pod 資源限制的 CPU 調大些;

可能存在的問題:

  1. Pod 無法起來時應該最先想到的是配置文件是否正常拉取,配置是否正確,少配置項、配置格式錯誤或編碼錯誤等等;

  2. 應用程序本身是否編寫正確,例如包衝突導致應用無法啓動;

  3. 應用程序依賴組件是否正常,例如 RabbitMQ、Mongodb、Reids、數據庫、第三方應用等等等;

  4. Pod 內存不足(因爲加上了資源限制),類似於下面的容器配置定義:

"resources": {
  "limits": {
      "cpu": "1",
      "memory": "1Gi"
    },
  "requests": {
    "cpu": "500m",
    "memory": "500Mi"
  }
}

在這裏插入圖片描述
5. 檢查 liveness 的健康檢查探針配置參數,因爲這個探針配置也會影響到 Pod 的啓動,如下配置,大概意思是 liveness 探針使用 HTTP 協議,地址 /actuator/health + port=8080,Pod 創建 300s 後開始檢測,超時是 1s,每 10s 執行一次探測,連續失敗3次即失敗,失敗後成功1次即成功;這裏說一嘴 readiness 探針,和liveness類似,兩者的主要區別在於 liveness主要用來確定何時重啓容器,默認成功;readiness 主要來確定容器是否已經就緒,默認失敗,不可相互替代。而是相互協作的關係。

"livenessProbe": {
 "httpGet": {
     "path": "/actuator/health",
     "port": 8080,
     "scheme": "HTTP"
   },
   "initialDelaySeconds": 300,
   "timeoutSeconds": 1,
   "periodSeconds": 10,
   "successThreshold": 1,
   "failureThreshold": 3
 },
 "readinessProbe": {
   "httpGet": {
     "path": "/actuator/health",
     "port": 8080,
     "scheme": "HTTP"
   },
   "initialDelaySeconds": 60,
   "timeoutSeconds": 1,
   "periodSeconds": 10,
   "successThreshold": 1,
   "failureThreshold": 3
 }

三、排查過程記錄

一條一條對着上述可能存在的問題排查,發現通過將 Pod 資源限制加至 cpu=2,memory=4Gi 時應用偶爾能夠正常啓動,但還存在不能啓動的情況,然後在本機通過 VisualVM 工具監測到應用啓動後 heap 內存用了不到 500M ,另外通過查看 Pod 日誌時,發現應用程序啓動時所帶的參數(如下圖)得出結論,不是內存問題。

exec java -Xmx512m -XX:ParallelGCThreads=1 -XX:ConcGCThreads=1  

下圖爲 Pod 日誌,可以看出 最大堆內存爲 512M。
在這裏插入圖片描述
然後應用將資源限制還原,發現 liveness 探針的 initialDelaySeconds=0,於是修改 liveness 探針的 initialDelaySeconds=300 解決問題。

四、原因分析

我這原因是因爲第 5 條原因導致。因爲應用啓動時間比較長,在資源限制不變得情況下正常啓動需要耗時60s,加上之前 liveness 的配置不合理,如下:

"livenessProbe": {
 "httpGet": {
     "path": "/actuator/health",
     "port": 8080,
     "scheme": "HTTP"
   },
   "initialDelaySeconds": 0,
   "timeoutSeconds": 1,
   "periodSeconds": 10,
   "successThreshold": 1,
   "failureThreshold": 3
 },

因爲 initialDelaySeconds 設置的是0,導致連續3次健康檢查失敗(理論是在重啓 Pod 30s 後)就會自動重啓 Pod。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章