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