之前分享過幾篇最佳化pod重啟的文章,有朋友發私信問:看你的最佳化文章很過癮,可否分享下如何收集pod重啟前的現場。
的確是個好問題,之前寫文章的時候忽略了這一點,一個完整的現場對破案的作用不言而喻,今天花點時間和大夥探討一下。
守株待兔階段
這個時期處於人工盯屏階段,開啟rancher(一款k8s叢集管理工具)介面觀察pod的狀態,如果發現pod的狀態變成下圖(Container with unready status意味著健康檢查失敗)這樣的時候立刻進入容器的命令列使用jmap命令收集dump資訊。
顯然運氣的成分多一些,比較浪費時間。
全自動階段
盯屏效率太低,有沒有機制能在pod重啟前自動收集現場,無人值守,為開發在事後分析提供充分的證據。
接下來就是今天的主角登場,容器的生命週期回撥,Kubernetes 為容器提供了生命週期回撥。回撥使容器能夠了解其管理生命週期中的事件,並在執行相應的生命週期回撥時執行在處理程式中實現的程式碼。
有兩個回撥暴露給容器:
PostStart
這個回撥在容器被建立之後立即被執行。但是,不能保證回撥會在容器入口點(ENTRYPOINT)之前執行。沒有引數傳遞給處理程式。
PreStop
在容器因 API 請求或者管理事件(諸如存活態探針、啟動探針失敗、資源搶佔、資源競爭等) 而被終止之前,此回撥會被呼叫。如果容器已經處於已終止或者已完成狀態,則對 preStop 回撥的呼叫將失敗。在用來停止容器的 TERM 訊號被髮出之前,回撥必須執行結束。Pod 的終止寬限週期在 PreStop
回撥被執行之前即開始計數, 所以無論回撥函式的執行結果如何,容器最終都會在 Pod 的終止寬限期內被終止。沒有引數會被傳遞給處理程式。
我們最終決定藉助PreStop回撥來實現自動收集現場,配置如下:
lifecycle: preStop: exec: command: - /bin/sh - -c - pid=`ps -ef |grep java | grep -v grep |awk '{print $1}'`; jmap -dump:format=b,file=/data/dump/${JAR_NAME}.dump ${pid}
大致意思是在容器銷燬前透過jmap命令收集dump到指定目錄。
有兩點需要特別說明:
1.注意這個目錄需要做持久化,而且要及時清理減少磁碟佔用,因為日常的釋出也會觸發preStop;
2.另一個需要注意的是終止寬限期-terminationGracePeriodSeconds需要調整,給jmap預留充分的時間保留現場,也不能太長,調長的副作用是滾動釋出會變慢。
推薦閱讀
https://kubernetes.io/zh-cn/docs/concepts/containers/container-lifecycle-hooks/