Docker 原生健康檢查能力
自 1.12 版本之后,Docker 引入了原生的健康檢查實現。對于容器而言,最簡單的健康檢查是進程級的健康檢查,即檢驗進程是否存活。Docker Daemon 會自動監控容器中的 PID1 進程,如果 docker run 命令中指明了 restart policy,可以根據策略自動重啟已結束的容器。在很多實際場景下,僅使用進程級健康檢查機制還遠遠不夠。比如,容器進程雖然依舊運行卻由于應用死鎖無法繼續響應用戶請求,這樣的問題是無法通過進程監控發現的。
容器啟動之后,初始狀態會為 starting (啟動中)。Docker Engine 會等待 interval 時間,開始執行健康檢查命令,并周期性執行。如果單次檢查返回值非 0 或者運行需要比指定 timeout 時間還長,則本次檢查被認為失敗。如果健康檢查連續失敗超過了 retries 重試次數,狀態就會變為 unhealthy (不健康)。
注:
一旦有一次健康檢查成功,Docker 會將容器置回 healthy (健康)狀態
當容器的健康狀態發生變化時,Docker Engine 會發出一個 health_status 事件。通過檢查容器監控狀態有以下兩種方式:
1. Dockerfile 方式
可以在 Dockerfile 中聲明應用自身的健康檢測配置。HEALTHCHECK指令聲明了健康檢測命令,用這個命令來判斷容器主進程的服務狀態是否正常,從而比較真實的反應容器實際狀態。
HEALTHCHECK指令格式:
HEALTHCHECK [選項] CMD <命令>:設置檢查容器健康狀況的命令
HEALTHCHECK NONE:如果基礎鏡像有健康檢查指令,使用這行可以屏蔽掉
注 :在 Dockerfile 中HEALTHCHECK只可以出現一次,如果寫了多個,只有最后一個生效。
使用包含HEALTHCHECK指令的 Dockerfile 構建出來的鏡像,在實例化 Docker 容器的時候,就具備了健康狀態檢查的功能。啟動容器后會自動進行健康檢查。參數參考:https://docs.docker.com/engine/reference/builder/#healthcheck
HEALTHCHECK 支持下列選項:
--interval=<間隔>:兩次健康檢查的間隔,默認為 30 秒;
--timeout=<間隔>:健康檢查命令運行超時時間,如果超過這個時間,本次健康檢查就被視為失敗,默認 30 秒;
--retries=<次數>:當連續失敗指定次數后,則將容器狀態視為 unhealthy,默認 3 次。
--start-period=<間隔>: 應用的啟動的初始化時間,在啟動過程中的健康檢查失效不會計入,默認 0 秒;
參數作用解釋如下:
運行狀態檢查首先會在容器啟動后的 interval 秒內運行,然后在前一次檢查完成后的 interval 秒內再次運行。
如果一次狀態檢查花費的時間超過 timeout 秒,則認為這次檢查失敗。
容器的運行狀態檢查連續失敗 retries 次才會被視為不健康。
start period 為需要時間啟動的容器提供初始化時間。在此期間的探測失敗將不計入最大重試次數。
但是,如果在啟動期間健康檢查成功,則認為容器已啟動,所有連續失敗的情況都將計算到最大重試次數。
在HEALTHCHECK [選項] CMD后面的命令,格式和ENTRYPOINT一樣,分為 shell 格式,和 exec 格 式。命令的返回值決定了該次健康檢查的成功與否:
0:成功;
1:失敗;
2:保留值,不要使用
假設有個鏡像是個最簡單的 Web 服務,我們希望增加健康檢查來判斷其 Web 服務是否在正常工作,我們可以用 curl 來幫助判斷,其 Dockerfile 的HEALTHCHECK可以這么寫:
FROMnginx:1.23 HEALTHCHECK--interval=5s--timeout=3s--retries=3 CMDcurl-fshttp://localhost/||exit1
這里設置了每 5 秒檢查一次(這里為了試驗所以間隔非常短,實際應該相對較長),如果健康檢查命令超過 3 秒沒響應,并且重試 3 次都沒響應就視為失敗,并且使用curl -fs http://localhost/ || exit 1作為健康檢查命令。
使用docker build來構建這個鏡像:
dockerbuild-tmyweb:v1.
構建好后啟動容器:
dockerrun-d--namewebmyweb:v1
當運行該鏡像后,可以通過docker container ls看到最初的狀態為(health: starting):
dockercontainerls CONTAINERIDIMAGECOMMANDCREATEDSTATUSPORTSNAMES 7068d793c6e4myweb:v1"/docker-entrypoint.…"3secondsagoUp2seconds(health:starting)80/tcpweb
在等待幾秒鐘后,再次docker container ls,就會看到健康狀態變化為了(healthy):
$dockercontainerls CONTAINERIDIMAGECOMMANDCREATEDSTATUSPORTSNAMES 7068d793c6e4myweb:v1"/docker-entrypoint.…"18secondsagoUp16seconds(healthy)80/tcpweb
如果健康檢查連續失敗超過了重試次數,狀態就會變為(unhealthy)。
為了幫助排障,健康檢查命令的輸出(包括stdout以及stderr)都會被存儲于健康狀態里,可以用 docker inspect來查看。
$dockerinspect--format'{{json.State.Health}}'web|python-mjson.tool { "FailingStreak":0, "Log":[ { "End":"2022-08-20T1438.19224648+08:00", "ExitCode":0, "Output":"xxx", "Start":"2022-08-20T1438.116041192+08:00" }, { "End":"2022-08-20T1443.271105619+08:00", "ExitCode":0, "Output":"xxx", "Start":"2022-08-20T1443.200932585+08:00" } ], "Status":"healthy" }
2. docker run 方式
另外一種方法是在 docker run 命令中,直接指明 healthcheck 相關策略:
$dockerrun-d --name=myweb --health-cmd="curl-fshttp://localhost/||exit1" --health-interval=5s --health-retries=12 --health-timeout=2s nginx:1.23
通過執行docker run --help | grep health命令查看相關的參數及解釋如下:
--health-cmd string:運行檢查健康狀況的命令
--health-interval duration:運行間隔時間(ms|s|m|h)(缺省為 0s)
--health-retries int:需要報告不健康的連續失敗次數
--health-start-period duration :容器在開始健康重試倒計時之前初始化的起始周期(ms|s|m|h)(默認 0)
--health-timeout duration:允許一次檢查運行的最大時間(ms|s|m|h)(默認為 0s)
--no-healthcheck:禁用任何容器指定的HEALTHCHECK,會使得 Dockerfile 構建出來的HEALTHCHECK功能失效。
如果是以 supervisor 來管理容器的多個服務,想通過子服務的狀態來判斷容器的監控狀態,可以使用supervisorctl status來做判斷,比如:
$dockerrun--rm-d --name=myweb --health-cmd="supervisorctlstatus" --health-interval=5s --health-retries=3 --health-timeout=2s nginx:v1
按照此參數的設置,如果supervisorctl status檢查子服務有一個不為正常的RUNNING狀態,那么在等待大約 15 秒左右,容器的監控狀態就會從(healthy)變為(unhealthy)
3. docker-composer 方式
在 docker-composer 中,可以使用以下方式來實現對容器的健康狀況檢查(以通過 supervisor 管理子進程的容器為例):
version:'3' services: web: image:nginx:v1 container_name:web healthcheck: test:["CMD","supervisorctl","status"] interval:5s timeout:2s retries:3
執行成功后,等待數秒查詢容器的狀態:
$docker-composeps NameCommandStatePorts -------------------------------------------------------------------------------- websupervisord-c/etc/superv...Up(healthy)443/tcp,80/tcp
當通過手動supervisorctl stop停掉里面的一些子服務,導致里面的子服務狀態不全為RUNNING狀態時,再查看容器的狀態:
#docker-composeps NameCommandStatePorts ---------------------------------------------------------------------------------- websupervisord-c/etc/superv...Up(unhealthy)443/tcp,80/tcp
-
存儲
+關注
關注
13文章
4296瀏覽量
85799 -
容器
+關注
關注
0文章
495瀏覽量
22060 -
Docker
+關注
關注
0文章
457瀏覽量
11846
原文標題:Docker 容器的 health 健康狀態檢查
文章出處:【微信號:magedu-Linux,微信公眾號:馬哥Linux運維】歡迎添加關注!文章轉載請注明出處。
發布評論請先 登錄
相關推薦
評論