systemd 管理のサービスをcloud-init の後に実行する

6月 30, 2022AmazonLinux_CentOS,AWS,EC2

概要

やりたいこと

  • Amazon Linux, CentOS などの systemd を使用するLinux において、systemd 管理のサービスを cloud-init の処理後に起動させる方法です。
  • cloud-init は、AWS, Azure などのクラウドのインスタンスを起動時に、初期設定のタスクを行ったり、スクリプトを実行することができる機能です。
  • cloud-init の処理は、systemd 管理のサービス起動より前に実行される保証はありません。本記事の内容は、systemd 管理のサービス起動より先に、cloud-init の処理を実行させたい場合に効果があります。

 

シチュエーション

  • 今回の設定は、どういったシチュエーションに効果があるでしょうか。
  • 例えば、AWS のCloudWatch Agent を利用してLinux OS のログをCloudWatch Logs に転送させる環境があります。この環境では、cloud-init にホスト名を再設定するためのスクリプトを実装しています。もし、CloudWatch Agent のサービスがcloud-init の処理より前に起動した場合、CloudWatch Logs には古いホスト名を用いたログストリーム名が作成されるかもしれません。
  • 例えば、Linux に監視用のエージェントがインストールされ、監視サーバーからホスト名を利用して管理されている環境があります。この環境では、cloud-init にホスト名を再設定するためのスクリプトを実装しています。もし、監視用のエージェントがcloud-init の処理より前に起動した場合、監視サーバーには古いホスト名が表示されるかもしれません。

 

cloud-init のスクリプト

  • cloud-init のスクリプトは、/etc/cloud/cloud.cfg.d/ 配下に配置します。以下のスクリプトは例であり、実際はこちらの記事で紹介するようなスクリプトを利用します。
$ cd /etc/cloud/cloud.cfg.d/
$ cat 00_set_hostname.cfg
bootcmd:
 - /etc/cloud/cloud.cfg.d/00_set_hostname.sh
$ cat 00_set_hostname.sh
/usr/bin/hostnamectl set-hostname changed-hostname

 

systemd 管理のサービスをcloud-init の後に実行するには

【方法①】systemd の設定ファイルをカスタマイズする

  • systemd の設定ファイルは、下記の2種類があります。/usr/lib/systemd 配下のファイルはインストール時に配置されたデフォルトの設定ファイルとなります。/etc/systemd 配下のファイルはユーザーがカスタマイズするための設定ファイルとなります。/etc/systemd 配下に設定ファイルがない場合は、/usr/lib/systemd 配下からコピーして利用します。
    • /usr/lib/systemd/system
    • /etc/systemd/system
  • どちらのパスにも設定ファイルが配置されている場合は、/etc/systemd 配下の設定ファイルが優先されます。
  • 以下を参考に、systemd の実行順序を制御する記述を追加します。例として、systemd で管理される CloudWatch Agent を使用します。 CloudWatch AgentのUnitファイルである /etc/systemd/system/amazon-cloudwatch-agent.service を編集します。以下のように、Unitに After=cloud-final.service を追記します。
[Unit]
Description=Amazon CloudWatch Agent
After=network-online.target
After=cloud-final.service <== こちらを追記
  • CloudWatch Agent サービスを再起動します。Unitファイルの変更を適用するため、sudo systemctl daemon-reload を実行します。
$ sudo systemctl daemon-reload
$ sudo systemctl restart amazon-cloudwatch-agent
$ sudo systemctl status amazon-cloudwatch-agent

 

【方法②】systemd にdrop-in のユニット構成ファイルを追加する

  • 方法①に記載した方法以外に、systemd にdrop-in のユニット構成ファイル (/etc/systemd/system/[サービス名].d/override.conf) を追加作成する方法があります。こちらは、Unit の差分だけを記載する方法です。
  • 方法①はパッケージのアップデートによって、カスタマイズした設定ファイルが上書きされる可能性がありますので、方法②を推奨します。
  • 以下を参考に、systemd にdrop-in のユニット構成ファイルを追加作成します。例として、systemd で管理される CloudWatch Agent を使用します。vi で作成することもできますが、systemctl edit コマンドが便利です。
$ sudo systemctl edit amazon-cloudwatch-agent
[Unit] <== こちらを追記
After=cloud-final.service <== こちらを追記
  • 念のため、drop-in のユニット構成ファイルが追加作成されたことを確認します。
$ ls -l /etc/systemd/system/amazon-cloudwatch-agent.service.d/override.conf
-rw-r--r-- 1 root root 26 Jul  5 00:39 /etc/systemd/system/amazon-cloudwatch-agent.service.d/override.conf
$ cat /etc/systemd/system/amazon-cloudwatch-agent.service.d/override.conf
[Unit]
After=cloud-final.service
  • systemctl show コマンドで確認することも可能です。なお、[Unit]の記載漏れ等の誤りがあれば、systemctl show コマンドに変更内容が表示されません。
** 変更前 **
$ systemctl show amazon-cloudwatch-agent --property After
After=system.slice systemd-journald.socket basic.target network-online.target

** 変更後 **
$ systemctl show amazon-cloudwatch-agent --property After
After=cloud-final.service network-online.target systemd-journald.socket basic.target system.slice

 

  • systemctl cat コマンドで確認することも可能です。
$ systemctl cat amazon-cloudwatch-agent
# /etc/systemd/system/amazon-cloudwatch-agent.service
# Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
# SPDX-License-Identifier: MIT

# Location: /etc/systemd/system/amazon-cloudwatch-agent.service
# systemctl enable amazon-cloudwatch-agent
# systemctl start amazon-cloudwatch-agent
# systemctl | grep amazon-cloudwatch-agent
# https://www.freedesktop.org/software/systemd/man/systemd.unit.html

[Unit]
Description=Amazon CloudWatch Agent
After=network-online.target

[Service]
Type=simple
ExecStart=/opt/aws/amazon-cloudwatch-agent/bin/start-amazon-cloudwatch-agent
KillMode=process
Restart=on-failure
RestartSec=60s

[Install]
WantedBy=multi-user.target

# /etc/systemd/system/amazon-cloudwatch-agent.service.d/override.conf
[Unit]
After=cloud-final.service

 

  • こちらの方法は、systemctl daemon-reload コマンドは不要です。

 

補足

cloud-init の実行順序について

  • systemd のUnitファイルのAfter に指定できるパラメータは、下記となります。cloud-init の処理は、以下のステップで実行され、cloud-final.service はすべてのサービスが起動後に実行される処理となります。
    • cloud-init-local.service
    • cloud-init.service
    • cloud-config.service
    • cloud-final.service
  • 上記ステップの詳しい処理は、/etc/cloud/cloud.cfg を参照ください。

 

bootcmd モジュールの実行タイミングについて

  • cloud-init のモジュールには、Module frequency (実行タイミング)が定義されています。
    • Per instance: モジュールがインスタンスの初回起動時に実行されることを意味します。
    • Per once: モジュールが一度だけ実行されることを意味します。
    • Per always: モジュールが起動ごとに実行されることを意味します。
  • bootcmd モジュールのModule frequencyは、「always」であり、OS起動時に毎回実行されます。スクリプトの意図と異なる場合は、実装方法の見直しを検討します。
  • cloud-init の資料は、参考資料を参照ください。

 

参考資料