Edited at

インスタンス作成時にUser Dataで指定した設定が遅れる理由

クラウドでComputeインスタンス作成時にUserd Dataを指定すると、OS設定をカスタマイズできる。ただし設定が終わるまでには、タイムラグがあることを理解する必要がある。今回はその理由を探ってみる。

なお今回はOracle Cloud InfrastructureでOracle Linux 7を使用しているが、Linuxであれば他のクラウドでもほぼ同じだと思われる。


実行した環境


  • Oracle Cloud Infrastructure Compute(Phoenix Region)

  • Oracle Linux 7.6

  • cloud-init-18.4-1.el7.x86_64


User Dataが実行される仕組み

User Dataの内容を実行しているのはcloud-initで、OSのサービスとして実装されている。その内容を調べてみる。


cloud-initを構成するサービス群

サービスを確認するとcloudで始まる4つのサービスがある。この中でも中心となるのはcloud-config.serviceである。

$ systemctl list-unit-files --type service| grep ^cloud

cloud-config.service enabled ★これ
cloud-final.service enabled
cloud-init-local.service enabled
cloud-init.service enabled


cloud-config.serviceの中身を確認する

サービスの内容を定義したユニットファイルを確認する。systemctl catで表示できるが、実体のファイルは/usr/lib/systemd/system/配下に存在する。

$ systemctl cat cloud-config.service

ここで重要なのはAfterである。Afterは起動順序を定義するディレクティブで、指定したユニットがアクティブになってから起動することを表す。またnetwork-online.targetは特別なターゲットで、ネットワークサービスがオンラインになったことを表す。


/usr/lib/systemd/system/cloud-config.service

# /usr/lib/systemd/system/cloud-config.service

[Unit]
Description=Apply the settings specified in cloud-config
After=network-online.target cloud-config.target ★
Wants=network-online.target cloud-config.target
ConditionPathExists=!/etc/cloud/cloud-init.disabled
ConditionKernelCommandLine=!cloud-init=disabled

[Service]
Type=oneshot
ExecStart=/usr/bin/cloud-init modules --mode=config
RemainAfterExit=yes
TimeoutSec=0

# Output needs to appear in instance console output
StandardOutput=journal+console

[Install]
WantedBy=multi-user.target


つまり以下のように定義した場合、ネットワークが完全にオンラインになったあとにcloud-config.serviceを実行することを表す。

After=network-online.target cloud-config.target


sshd.serviceの中身を確認する

さらにsshd.serviceの中身を確認する。するとAfterディレクティブにはnetwork.target sshd-keygen.serviceが設定されている。

$ systemctl cat sshd


/usr/lib/systemd/system/sshd.service

# /usr/lib/systemd/system/sshd.service

[Unit]
Description=OpenSSH server daemon
Documentation=man:sshd(8) man:sshd_config(5)
After=network.target sshd-keygen.service ★
Wants=sshd-keygen.service

[Service]
Type=notify
EnvironmentFile=/etc/sysconfig/sshd
ExecStart=/usr/sbin/sshd -D $OPTIONS
ExecReload=/bin/kill -HUP $MAINPID
KillMode=process
Restart=on-failure
RestartSec=42s

[Install]
WantedBy=multi-user.target



cloud-initとsshdではどちらが早い

両方のAfterディレクティブの内容は似ているが、わずかに違いがある。詳細はwiki/Software/systemd/NetworkTargetを参照のこと。



  • network.target:ネットワークスタックが起動したこと(sshd.serviceで指定)


  • network.online:ネットワークスタックが起動し、IPアドレスが割り当てられたこと(cloud-config.serviceで指定)

つまり起動順序としては、sshdのほうがわずかに早いか、ほぼ同時に起動されることになる。


User Dataの実行が遅れる理由

ここまで来て、理由がわかったと思う。User Dataの内容はcloud-initのサービス群で設定される。ネットワークが起動したあとに実行されるので、

「パッケージのアップデート」のような時間のかかる処理を含んでいると、sshログインしてもUser Dataの内容が反映されていない

ということが起こりえる。だけれど実行中なだけなので、時間がたてばいずれ設定される。

またわずかにsshdのほうが起動順序は早いが、これは誤差の範囲だろう。User Dataに重い処理が含まれているかどうかがポイントになる。


Kickstartとの違いを理解する

今回の件はKickstartに慣れていると戸惑う人も多いだろう。Linuxインストール時に設定をカスタマイズする手段としてはKickstartが標準的だ。あらかじめ作成した設定したファイル(Kickstartファイル)をOSのインストーラーに食わせることで、自動的に設定を済ませる機能である。サイレントインストールの仕組みと言い換えてもいいだろう。

つまりKickstartはインストールプロセスで使用するため、OSが起動した段階で、設定したすべての内容が有効になっている。それに対してcloud-initは、ネットワークが起動したあとに実行されるので、sshログインできても、まだ設定中の可能性がある。

なおKickstartファイルは、RHEL系のディストリビューションであれば、/root/anakonda-ks.cfgにある。ただしクラウドベンダ提供のイメージでは削除されていることもある。


cloud-initが終わったことを知る方法

cloud-initは/var/log/cloud-init.logにログを出力する。大量に出力されるので、内容を理解するのは困難だが、次のようにfinish: modules-finalの行が表示されれば終了している。

# tail -f /var/log/cloud-init.log

★ここから下は画面の出力★
2019-05-16 13:04:25,343 - util.py[DEBUG]: Read 14 bytes from /proc/uptime
2019-05-16 13:04:25,343 - util.py[DEBUG]: cloud-init mode 'modules' took 0.208 seconds (0.21)
2019-05-16 13:04:25,344 - handlers.py[DEBUG]: finish: modules-final: SUCCESS: running modules for final


おわりに

今回はcloud-initが実行されるタイミングだけに着目して調べた。cloud-initには多くの機能があるので、興味のあるかたは以下の設定ファイルなども眺めて欲しい。


  • /etc/cloud/cloud.cfg

  • /etc/cloud/cloud.cfg.d/


まとめ


  • クラウドのCompute(IaaS)でUser Dataを指定したとき、設定内容がすぐに反映されないことがある

  • 遅れる原因は、User Dataの基盤となるcloud-initはLinuxのサービスとして実装されているので、ネットワークが起動したあとに設定が実行されるから

  • User Dataで時間のかかる処理を記述したときは、ある程度待ってから設定を確認する

  • Kickstartとは、まったく違う仕組みであることを理解する