Armadilloフォーラム

podmanでhealthcheckが定期的に実行されない。

minaba

2023年6月30日 13時55分

Armadillo-IoT G4についての質問です。

podmanのhealthcheck機能を使用したく設定を試しているのですが、うまく動作しません。
何が原因かわかるでしょうか?
長くて申し訳ありませんが、下記に実行状況を貼り付けました。

現象としては、起動後1度だけhealthchesk.shが動いているのですが、その後インターバルに従って起動されないように見えます。
startingのままで、healthy, unheathyの状態になりません。
version 4.3.1には--health-startup-cmdのようなオプションはまだ無いようです。(指定してみましたがエラーになりました)
podman healthcheck run を手動で実行すると起動され指定された動作をします。
Containerfile(Dockerfile)ではHEALTHCHECK CMDは指定していません。podman buildで作成したイメージです。

armadillo:~# podman -v
podman version 4.3.1

armadillo:~# podman run --health-on-failure=kill --health-cmd="/wd/healthcheck.s
h" --health-interval=30s --health-retries=1 --health-start-period=0s -d --name
dashboard --pod main_pod localhost/arm64v8/dashboard:latest
41595286f2927399b88da42067da87e3060a0e1aae9b42d249b641ea5250e050

armadillo:~# podman ps -a
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS
41595286f292 localhost/arm64v8/dashboard:latest ... 59 seconds ago Up 59 seconds ago (starting) 0.0.0.0:80->80/tcp dashboard

armadillo:~# podman exec -it dashboard /bin/bash
root@main_pod:/wd# cat healthcheck.sh
#! /bin/bash
#
# health check script
# This is test version. FIXME

#/usr/bin/touch /wd/checked

if test -e /wd/unhealthy; then
/usr/bin/touch /wd/checked_unhealthy
exit 1 # unhealthy
else
/usr/bin/touch /wd/checked_healthy
exit 0 # healthy
fi

root@main_pod:/wd# ls -l checked*
-rw-r--r-- 1 root root 0 Jun 30 00:44 checked_healthy

root@main_pod:/wd# touch unhealthy

root@main_pod:/wd# ls -l *health*
-rw-r--r-- 1 root root 0 Jun 30 00:44 checked_healthy
-rwxr-xr-x 1 root root 334 Jun 30 00:43 healthcheck.sh
-rw-r--r-- 1 root root 0 Jun 30 04:34 unhealthy
root@main_pod:/wd#

root@main_pod:/wd# exit
exit

armadillo:~# podman ps -a
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS
41595286f292 localhost/arm64v8/dashboard:latest ... 8 minutes ago Up 8 minutes ago (starting)
0.0.0.0:80->80/tcp, 0.0.0.0:1880->1880/tcp, 0.0.0.0:8086->8086/tcp dashboard

armadillo:~# podman ps -a
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS
41595286f292 localhost/arm64v8/dashboard:latest ... 10 minutes ago Up 10 minutes ago (starting
) 0.0.0.0:80->80/tcp, 0.0.0.0:1880->1880/tcp, 0.0.0.0:8086->8086/tcp dashboard

armadillo:~# podman healthcheck run dashboard
unhealthy
armadillo:~# podman ps -a
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS
41595286f292 localhost/arm64v8/dashboard:latest ... 11 minutes ago Exited (137) 2 seconds ago
(unhealthy) 0.0.0.0:80->80/tcp, 0.0.0.0:1880->1880/tcp, 0.0.0.0:8086->8086/tcp dashboard

以上、よろしくお願い致します。

コメント

at_dominique.m…

2023年6月30日 15時17分

minabaさん

お世話になっています、 マルティネです。

長くて申し訳ありませんが、下記に実行状況を貼り付けました。

いいえいいえ、色々調べてくださってありがとうございます。

podmanのhealthcheck機能を使用したく設定を試しているのですが、うまく動作しません。 何が原因かわかるでしょうか?

今回の原因は podman が systemd を想定していることです。

具体的に、podman の healthcheck の スケジューリング は systemd でしか動いてないです。systemd の場合は /run ( /run/systemd/transient/ か /run/user/1000/systemd/transient/) に systemd のタイマーを追加して、systemd に healthcheck を実行させてます。 理論上ではその判断もいいと思います:conmon (コンテナを管理するサービス)に何か問題あったら、それが healthcheck を実行できるかどうかは信用できないので、別の仕組みで実行させています。

実行されているコマンドがとても簡単なので、while ループで podman healthcheck run <container> だけでもいいです(コンテナは id か名前でも大丈夫です)

例えば以下の行を手動で実行するか /etc/atmark/containers/dashboard.conf に追加すれば healthcheck が実行されます: - 最初の sleep でコンテナが本当に実行されているかを待つ - コンテナがなくなった場合に podman healthcheck run が 125 で exit しますので、それをループ停止条件にします。

sh -c 'sleep 30; while podman healthcheck run dashboard; [ "$?" != 125 ]; do sleep 30; done' &

(まぁ、固定の名前でしたら /etc/local.d/healthcheck.startwhile true の形でもいいですね)

これは確かに分かりにくいので、マニュアルに何か注意を足しておきたいと思います。 (いずれの podman アップデートで対応されるかもしれませんが、しばらくは実装されなさそうですね。podman_start で対応するかもしれませんがすぐにはなりません。)

よろしくお願いします。

minaba

2023年6月30日 17時07分

マルティネさん、

minabaです。ご回答ありがとうございます。

まだ、よく理解できておらず、確認させてください。
1.まず、Base OSではsystemdが動いていないという理解でよろしいでしょうか?
そのため、--health-interval, --health-retries, --health-startなどのオプションは指定しても機能しないと捉えれば良いでしょうか。
ps や service -l 等としても、systemdは無いようです。

2.systemdの代わりに下記コマンドを実行して定期的にhealthcheckをさせる事ができるという事だと思いますが、dashboard.confに書くことができるというのは、dashboard.confなどの各コンテナのconfファイルはスクリプトとして実行されるという事でしょうか?
> sh -c 'sleep 30; while podman healthcheck run dashboard; [ "$?" != 125 ]; do sleep 30; done' &
それであれば、各コンテナ毎に、confファイル内に同様の記述をすれば、各コンテナでhealthcheckが機能すると理解しましたが、合っていますか?

3.healthcheck.shはテスト用に書いたものを挙げましたが、今後、コンテナが提供するサービスの稼働状況を監視して再起動したいと思っています。今回のテストではkill または stopで止めましたが実際にやりたいことはrestartです。--health-on-failure=restartは使えるでしょうか?
podmanのマニュアルには、systemd絡みで、--restartオプションとは一緒に使うなとあるのですが、
--health-on-failure=kill or stop --restart=always(あるいはset_restart always in dashboard.conf)としたほうが良いでしょうか?

4.下記はどういう動きになりますか? 固定の名前というのはコンテナの名前の事でしょうか? それともhealthcheckというサービスを動かすという意味でしょうか? すみません、理解が追い付いていません。
> (まぁ、固定の名前でしたら `/etc/local.d/healthcheck.start` に `while true` の形でもいいですね)

以上、よろしくお願いします。

> minabaさん
>
> お世話になっています、
> マルティネです。
>
> > 長くて申し訳ありませんが、下記に実行状況を貼り付けました。
>
> いいえいいえ、色々調べてくださってありがとうございます。
>
> > podmanのhealthcheck機能を使用したく設定を試しているのですが、うまく動作しません。
> > 何が原因かわかるでしょうか?
>
> 今回の原因は podman が systemd を想定していることです。
>
> 具体的に、podman の healthcheck の スケジューリング は systemd でしか動いてないです。systemd の場合は /run ( /run/systemd/transient/ か /run/user/1000/systemd/transient/) に systemd のタイマーを追加して、systemd に healthcheck を実行させてます。
> 理論上ではその判断もいいと思います:conmon (コンテナを管理するサービス)に何か問題あったら、それが healthcheck を実行できるかどうかは信用できないので、別の仕組みで実行させています。
>
> 実行されているコマンドがとても簡単なので、`while` ループで `podman healthcheck run ` だけでもいいです(コンテナは id か名前でも大丈夫です)
>
> 例えば以下の行を手動で実行するか /etc/atmark/containers/dashboard.conf に追加すれば healthcheck が実行されます:
> - 最初の sleep でコンテナが本当に実行されているかを待つ
> - コンテナがなくなった場合に podman healthcheck run が 125 で exit しますので、それをループ停止条件にします。
>
> ```
> sh -c 'sleep 30; while podman healthcheck run dashboard; [ "$?" != 125 ]; do sleep 30; done' &
> ```
>
> (まぁ、固定の名前でしたら `/etc/local.d/healthcheck.start` に `while true` の形でもいいですね)
>
>
> これは確かに分かりにくいので、マニュアルに何か注意を足しておきたいと思います。
> (いずれの podman アップデートで対応されるかもしれませんが、しばらくは実装されなさそうですね。podman_start で対応するかもしれませんがすぐにはなりません。)
>
>
> よろしくお願いします。

at_dominique.m…

2023年7月3日 9時43分

minabaさん、

お世話になっています、
マルティネです。

> まだ、よく理解できておらず、確認させてください。

回答の書き方が分かりづらくてすみません。

> 1.まず、Base OSではsystemdが動いていないという理解でよろしいでしょうか?
> ps や service -l 等としても、systemdは無いようです。

はい、Armadillo Base OS (ABOS) は systemd を使ってません。その代わりに「openrc」というサービスマネージャーを使っています(Alpine OS の影響で)が、systemd のタイマーが実装されてません(そもそも podman が代わりの対応をワーニングも表示せずに一切行ってないのもおかしいと思いますが…)

本来ならは ABOS のことを気にせずコンテナを使っていただきたいところですが、こういうところでも init の影響がありましたね…

> そのため、--health-interval, --health-retries, --health-startなどのオプションは指定しても機能しないと捉えれば良いでしょうか。

試したところ、--health-cmd, --health-retries, --health-timeout, --health-on-failure は使えます。
--health-interval, --health-start-period の方は systemd のタイマーを管理する仕組みなので、そちらのオプションを使っても影響ありません。

> 2.systemdの代わりに下記コマンドを実行して定期的にhealthcheckをさせる事ができるという事だと思いますが、dashboard.confに書くことができるというのは、dashboard.confなどの各コンテナのconfファイルはスクリプトとして実行されるという事でしょうか?
> > sh -c 'sleep 30; while podman healthcheck run dashboard; [ "$?" != 125 ]; do sleep 30; done' &
> それであれば、各コンテナ毎に、confファイル内に同様の記述をすれば、各コンテナでhealthcheckが機能すると理解しましたが、合っていますか?

はい、conf ファイルを処理するときにそこに記載されているコマンドが実行されますので、あまり綺麗な対応ではありませんがその理解であっています。

> 3.healthcheck.shはテスト用に書いたものを挙げましたが、今後、コンテナが提供するサービスの稼働状況を監視して再起動したいと思っています。今回のテストではkill または stopで止めましたが実際にやりたいことはrestartです。--health-on-failure=restartは使えるでしょうか?
> podmanのマニュアルには、systemd絡みで、--restartオプションとは一緒に使うなとあるのですが、
> --health-on-failure=kill or stop --restart=always(あるいはset_restart always in dashboard.conf)としたほうが良いでしょうか?

--health-on-failure=restart で問題ありません。
restart の場合は新しいコンテナが podman healthcheck run コマンドから再起動されます。
(ちなみに、試したところ --restart=always でも、--health-on-failure=kill では停止されてます。)

> 4.下記はどういう動きになりますか? 固定の名前というのはコンテナの名前の事でしょうか? それともhealthcheckというサービスを動かすという意味でしょうか? すみません、理解が追い付いていません。
> > (まぁ、固定の名前でしたら `/etc/local.d/healthcheck.start` に `while true` の形でもいいですね)

すみません。コンテナの名前は /etc/atmark/containers/*.conf のファイル名と同じ名前になりますので、コンテナを追加やリネームしない限りは「固定の名前」と言う意図でした。
その場合は、分かりにくい「conf ファイルにコマンドを実行させる」より、常に実行されている local.d の仕組みでコンテナの有無関係なく「while true; do podman healthcheck run dashboard; sleep 30; done」等を実行させた方が分かりやすいと思いました。

コマンドを定期的に実行すれば何でもいいですので、余計なことを書いただけです。

healthcheck については今まであまり考えてなかったが、今後のために一つのやり方を決めて、もう少し分かりやすく案内したいと思います。
それまではお手数ですが、コンフィグファイルや local.d等で試してみてください。

よろしくお願いします。

minaba

2023年7月3日 15時42分

マルティネさん、

minabaです。
ありがとうございます。だいぶ理解が進みました。

dashboard.confに教えていただいた下記のスクリプトを入れて試してみました。動作しています。
sh -c 'sleep 30; while podman healthcheck run dashboard; [ "$?" != 125 ]; do sleep 30; done' &

ただ、unhealthyになった後、リスタートするのですが、その後startingのままになってしまい、
なぜかを調べていたところ、touchしたunhealthyがきていない事によって、何度もrestartしている事がわかりました。
今回はテスト用に作成したhealthcheck.shなので、同じような現象は避けられるかとは思いますが、
疑問なのは、restartの仕様です。コンテナが再作成されると思っていましたが、コンテナを再利用して起動するのでしょうか。

armadillo:~# podman exec -it dashboard /bin/bash
root@main_pod:/wd# ls -l checked*
-rw-r--r-- 1 root root 0 Jul 3 05:48 checked_healthy
root@main_pod:/wd# touch unhealthy
root@main_pod:/wd# exit
exit
armadillo:~# podman ps -a
b3451bc0c25f localhost/arm64v8/dashboard:latest ... 19 minutes ago Up 18 minutes ago (healthy)
0.0.0.0:80->80/tcp dashboard
armadillo:~# podman ps -a
b3451bc0c25f localhost/arm64v8/dashboard:latest ... 19 minutes ago Stopping (unhealthy) 0.0.0
.0:80->80/tcp dashboard
armadillo:~# podman ps -a
b3451bc0c25f localhost/arm64v8/dashboard:latest ... 19 minutes ago Up 5 seconds ago (starting)
0.0.0.0:80->80/tcp dashboard
armadillo:~# podman ps -a
b3451bc0c25f localhost/arm64v8/dashboard:latest ... 19 minutes ago Up 5 seconds ago (starting)
0.0.0.0:80->80/tcp dashboard

root@main_pod:/wd# armadillo:~# ps |grep dashboard
1594 root 0:00 sh -c sleep 30; while podman healthcheck run dashboard; [ "$?" != 125 ]; do sleep 30; done

armadillo:~# podman exec -it dashboard /bin/bash
root@main_pod:/wd# ls -l *healthy*
-rw-r--r-- 1 root root 0 Jul 3 05:49 checked_healthy
-rw-r--r-- 1 root root 0 Jul 3 06:14 checked_unhealthy
-rw-r--r-- 1 root root 0 Jul 3 05:49 unhealthy

以上、よろしくお願いします。

> minabaさん、
>
> お世話になっています、
> マルティネです。
>
> > まだ、よく理解できておらず、確認させてください。
>
> 回答の書き方が分かりづらくてすみません。
>
> > 1.まず、Base OSではsystemdが動いていないという理解でよろしいでしょうか?
> > ps や service -l 等としても、systemdは無いようです。
>
> はい、Armadillo Base OS (ABOS) は systemd を使ってません。その代わりに「openrc」というサービスマネージャーを使っています(Alpine OS の影響で)が、systemd のタイマーが実装されてません(そもそも podman が代わりの対応をワーニングも表示せずに一切行ってないのもおかしいと思いますが…)
>
> 本来ならは ABOS のことを気にせずコンテナを使っていただきたいところですが、こういうところでも init の影響がありましたね…
>
> > そのため、--health-interval, --health-retries, --health-startなどのオプションは指定しても機能しないと捉えれば良いでしょうか。
>
> 試したところ、--health-cmd, --health-retries, --health-timeout, --health-on-failure は使えます。
> --health-interval, --health-start-period の方は systemd のタイマーを管理する仕組みなので、そちらのオプションを使っても影響ありません。
>
> > 2.systemdの代わりに下記コマンドを実行して定期的にhealthcheckをさせる事ができるという事だと思いますが、dashboard.confに書くことができるというのは、dashboard.confなどの各コンテナのconfファイルはスクリプトとして実行されるという事でしょうか?
> > > sh -c 'sleep 30; while podman healthcheck run dashboard; [ "$?" != 125 ]; do sleep 30; done' &
> > それであれば、各コンテナ毎に、confファイル内に同様の記述をすれば、各コンテナでhealthcheckが機能すると理解しましたが、合っていますか?
>
> はい、conf ファイルを処理するときにそこに記載されているコマンドが実行されますので、あまり綺麗な対応ではありませんがその理解であっています。
>
> > 3.healthcheck.shはテスト用に書いたものを挙げましたが、今後、コンテナが提供するサービスの稼働状況を監視して再起動したいと思っています。今回のテストではkill または stopで止めましたが実際にやりたいことはrestartです。--health-on-failure=restartは使えるでしょうか?
> > podmanのマニュアルには、systemd絡みで、--restartオプションとは一緒に使うなとあるのですが、
> > --health-on-failure=kill or stop --restart=always(あるいはset_restart always in dashboard.conf)としたほうが良いでしょうか?
>
> --health-on-failure=restart で問題ありません。
> restart の場合は新しいコンテナが podman healthcheck run コマンドから再起動されます。
> (ちなみに、試したところ --restart=always でも、--health-on-failure=kill では停止されてます。)
>
> > 4.下記はどういう動きになりますか? 固定の名前というのはコンテナの名前の事でしょうか? それともhealthcheckというサービスを動かすという意味でしょうか? すみません、理解が追い付いていません。
> > > (まぁ、固定の名前でしたら `/etc/local.d/healthcheck.start` に `while true` の形でもいいですね)
>
> すみません。コンテナの名前は /etc/atmark/containers/*.conf のファイル名と同じ名前になりますので、コンテナを追加やリネームしない限りは「固定の名前」と言う意図でした。
> その場合は、分かりにくい「conf ファイルにコマンドを実行させる」より、常に実行されている local.d の仕組みでコンテナの有無関係なく「while true; do podman healthcheck run dashboard; sleep 30; done」等を実行させた方が分かりやすいと思いました。
>
> コマンドを定期的に実行すれば何でもいいですので、余計なことを書いただけです。
>
> healthcheck については今まであまり考えてなかったが、今後のために一つのやり方を決めて、もう少し分かりやすく案内したいと思います。
> それまではお手数ですが、コンフィグファイルや local.d等で試してみてください。
>
> よろしくお願いします。

at_dominique.m…

2023年7月3日 16時40分

minabaさん、

マルティネです。

> ただ、unhealthyになった後、リスタートするのですが、その後startingのままになってしまい、

healthcheck が一度成功するまでは starting ですね。

> なぜかを調べていたところ、touchしたunhealthyがきていない事によって、何度もrestartしている事がわかりました。
> 今回はテスト用に作成したhealthcheck.shなので、同じような現象は避けられるかとは思いますが、
> 疑問なのは、restartの仕様です。コンテナが再作成されると思っていましたが、コンテナを再利用して起動するのでしょうか。

はい、podman 内のコマンドは基本的にストレージを再利用しますので、以下のどれかの方法でリスタートする場合にコンテナのストレージはそのまま再利用されます:
- podman run の --restart=on-failure|always の場合にコンテナ内のプロセスが停止した時
- podman ps -a で Status が Exited の際に podman start [container]でコンテナを起動する時
- podman healthcheck run [container] で失敗数によって再起動させる時

podman_start で再起動する場合だけはストレージを消して、新しく作ります。分かりにくい実装になってしまってすみません。

本件の様にファイルを確認する形であれば、コンテナコンフィグの set_command (あるいはコンテナ自体の entrypoint かデフォルトのコマンドを使う場合そのイメージのデフォルト)で healthy ファイルを作り直すことで対応できますが、結局サービスを使う実装になると思いますのでおそらく何もしなくてもいいと思います。

コンテナのストレージの変更でサービスが失敗することになった場合は healthcheck による restart が少し足りないですね。
そこは podman としてどうしようもないですが、いくつかの対応を考えられます:
- コンテナのコンフィグに 「set_readonly true」でコンテナのファイルシステムを読み取り専用にしたら、再利用されても綺麗な状態で起動されます(ボリュームは add_volumes の 「:ro」パラメタを指定しない限り書き込み可能のままになります)
- healthcheck を止めて、「podman exec [container] /wd/healthcheck.sh || podman_start [container]」で --health-retries は対応されてませんが完全に再起動されてます。

よろしくお願いします。

minaba

2023年7月3日 17時52分

マルティネさん、

minabaです。

ありがとうございます。rerunではなく、restartという事ですね。

どのように対処するかはもう少し検討する事にします。

試しに--rmを付けてみましたが、--restartとコンフリクトしてNGでした。
コンテナの内容によらず一般解にするのは、結構難しいかもしれません。