背景
某項目采用微服務架構,dubbo 框架,K8s 方式部署。
其中 HTTP 協議由網關應用統一處理,大部分應用僅提供 dubbo 協議。
目標
應用某個實例(pod)狀態異常時,嘗試自動重啟恢復。
解決
K8s 提供了3種存活探針(livenessProbe),以實現 pod 狀態異常時重啟。
HTTPGetAction 首先排除了,因為上文我們說了,HTTP 訪問由網關統一處理,應用本身沒有 HTTP 協議。
然后是 TCPSocketAction,該探針僅能確認 dubbo 端口是否為監聽狀態,無法實現應用狀態的的撥測。
最后是 ExecAction,該探針執行命令返回0判斷 pod 存活,非0則根據pod定義的重啟策略進行后續操作。
dubbo 框架從2.0.5 版本開始,支持通過 telnet 命令交互,我們可以使用 status 命令獲取應用本身即應用依賴的底層服務(注冊中心、數據庫等)的撥測結果。
我們只需要編寫一個簡單的 shell 腳本,抓取 dubbo 的 status 命令結果,如果是 OK 或 WARN 則返回0,否則返回1,就可以使用 ExecAction 了。
#!/bin/bash outputfile=/tmp/dubbo_health_check dubbo_port=$1 (echo 'status -l'; sleep 1) | nc -w 3 127.0.0.1 ${dubbo_port} -o ${outputfile} > /dev/null result=`grep summary ${outputfile}| awk '{print $4}' ` if [[ "${result}" == "OK" ]] || [[ "${result}" == "WARN" ]] then exit 0 else exit 1 fi
pod yaml文件中關於存活探針的部分如下所示
#(略) livenessProbe: exec: command: - /bin/bash - /opt/dubbo_health_check.sh - '20800' initialDelaySeconds: 600 timeoutSeconds: 5 periodSeconds: 60 failureThreshold: 3 #(略)
注意點
- 按 dubbo 官方文檔的說法,telnet 中執行 status 返回的結果應該和 status -l 中 summary 的結果一致,實際測試並非如此,建議使用 status -l
- 頻繁執行 status -l 可能會有性能上的隱患,參考 https://www.jianshu.com/p/f6376c148f2c
總結
dubbo 官方提供了與 pod 探針對齊的方法(參見下文),但是在我們這個應用中因為網關和其他一些原因限制了 HTTP 協議,因此使用了上文這種替代方案。
每個項目/團隊都會有一些自己的特殊需求,本文只是提供一種思路,如果有更好的解決方案,歡迎在評論區提出討論(●ˇ∀ˇ●)
參考
容器探針
https://kubernetes.io/zh/docs/concepts/workloads/pods/pod-lifecycle/#container-probes
Dubbo 與 pod 探針對齊
https://dubbo.apache.org/zh/docs/references/lifecycle/brief/
Dubbo Telnet 命令
https://dubbo.apache.org/zh/docs/v3.0/references/telnet/#status