Provisioning Script とは
IBM Cloud の IaaS サーバーに起動スクリプトを指定できる機能です。
Github や Gist などを使って https
の URL
を公開することで、そのスクリプトを起動時にダウンロードし、IaaS サーバーでの初期作業を自動化することができます。
Provisioning Script の実態
プロビジョニング過程の最終再起動後に Ubuntu の systemd
を使って、以下のようなサービスが起動するように設定されています。
指定した Provisioning Script は、 /root/install_complete.sh
に追記されて、 install_complete.service
の ExecStart
で実行されます。
Type=oneshot
は、一度だけ指定のコマンドを実行するタイプのサービスにです。
ExecStart
で指定された Provisioning Script を含むシェルスクリプトを実行して、それが完了したタイミングで起動完了(かつサービス終了)と判断します。
# cat install_complete.service
[Unit]
Description=INSTALL_COMPLETE
After=network.target
[Service]
ExecStart=/root/install_complete.sh
Type=oneshot
TimeoutSec=0
[Install]
WantedBy=multi-user.target
systemd
のバグ
タイムアウト設定を無効 (TimeoutSec=0
) にしている、または明示的に指定していない場合、100s 程度で強制終了するバグが確認されています。
server - Systemctl service timed out during start - Ask Ubuntu
1446015 – systemd fails to start a service if TimeoutSec=infinity is used
systemd - Services timed out at boot but could start manually what could be the problem? - Unix & Linux Stack Exchange
実際にこのような結果になりました。
ログは journalctl
で確認可能です。
(他にも journalctl | grep postinstall
, journalctl -f
など)
Jul 03 13:02:50 khayama-mc.ibmcloud.com systemd[1]: install_complete.service: Start operation timed out. Terminating.
Jul 03 13:02:50 khayama-mc.ibmcloud.com systemd[1]: install_complete.service: Failed with result 'timeout'.
Jul 03 13:02:50 khayama-mc.ibmcloud.com systemd[1]: Failed to start install_complete.service.
Jul 03 13:02:50 khayama-mc.ibmcloud.com systemd[1]: Startup finished in 4.130s (kernel) + 1min 35.993s (userspace) = 1min 40.124s.
lines 4646-4675/4675 (END)
バグを回避する方法
Type
を別のものに変えるか、TimeoutSec
を 0
以外の値に明示的に指定することで回避可能です。
例として、 Provisioning Script
の中で TimeoutSec=5min
として install_complete.service
を再作成するスクリプトを示します。
install_complete.sh
に起動スクリプトの内容を書き込み、systemd
をリロード後にリスタートさせることで 100s 以上時間がかかるスクリプトでも正常に完了されることができます。
# !/bin/bash
# Write down your provisioning script into this part
cat > /root/install_complete.sh <<EOF
# !/bin/bash
# update packages
DEBIAN_FRONTEND=noninteractive apt-get update
DEBIAN_FRONTEND=noninteractive apt-get upgrade -y
# reboot
reboot
EOF
chmod 755 /root/install_complete.sh
# You do not have to change this part
# set timeoutsec explicitly to prevent timeout fail
cat > /etc/systemd/system/install_complete.service <<EOF
[Unit]
Description=INSTALL_COMPLETE
After=network.target
[Service]
ExecStart=/root/install_complete.sh
Type=oneshot
TimeoutSec=5min
[Install]
WantedBy=multi-user.target
EOF
# run your script above without timeout fail bug
systemctl daemon-reload
systemctl restart install_complete.service