ようへいの日々精進XP

よかろうもん

systemd 環境下で条件に従ったサービス起動制御の一例

要件

  • Amazon EC2 の systemd 環境下 (CentOS 7) にて, Datadog Agent を動かすにあたり本番環境だけで動かしたい
  • AMI (Amazon Machine Image) は Datadog Agent を事前に組み込んだ AMI が用意されていて, 本番環境以外でもこの AMI は利用する
  • 本番環境には EC2 タグの prod を付与する運用ルールになっていて, AutoScaling Group にて EC2 の起動制御が行う

やったこと

ユニットファイルの修正

systemd 環境下でサービスの起動制御はユニットファイルにて行われます. Datadog Agent についても, エージェントが正常にインストールされると, 以下のようなユニットファイルが作成されます.

$ cat /usr/lib/systemd/system/datadog-agent.service
[Unit]
Description=Datadog Agent
After=network.target
Wants=datadog-agent-trace.service datadog-agent-process.service datadog-agent-sysprobe.service

[Service]
Type=simple
PIDFile=/opt/datadog-agent/run/agent.pid
User=dd-agent
Restart=on-failure
ExecStart=/opt/datadog-agent/bin/agent/agent run -p /opt/datadog-agent/run/agent.pid
# Since systemd 229, should be in [Unit] but in order to support systemd <229,
# it is also supported to have it here.
StartLimitInterval=10
StartLimitBurst=5

[Install]
WantedBy=multi-user.target

今回は, ユニットファイルの [Unit] セクションの ConditionPathExists= を利用することにしました. この ConditionPathExists= は以下のように解説されています.

With ConditionPathExists= a file existence condition is checked before a unit is started. If the specified absolute path name does not exist, the condition will fail. If the absolute path name passed to ConditionPathExists= is prefixed with an exclamation mark ("!"), the test is negated, and the unit is only started if the path does not exist.

  • ユニットが開始される前に ConditionPathExists= で指定された絶対パスがチェックされ, 指定されたパスが存在しない場合にはチェックは失敗する
  • ConditionPathExists= で指定絶対パス名の前に感嘆符 (!) が付いている場合, チェックそのものは無効になり, パスが存在しない場合にのみユニットが開始される

ということなので, 以下のようにユニットファイルを記載して, /path/to/datadog-agent/disabled にファイルを置くことで Datadog Agent の起動を抑制することが出来るはずです.

[Unit]
Description=Datadog Agent
After=network.target
Wants=datadog-agent-trace.service datadog-agent-process.service datadog-agent-sysprobe.service
ConditionPathExists=!/path/to/datadog-agent/disabled

[Service]
Type=simple
PIDFile=/opt/datadog-agent/run/agent.pid
User=dd-agent
Restart=on-failure
ExecStart=/opt/datadog-agent/bin/agent/agent run -p /opt/datadog-agent/run/agent.pid
# Since systemd 229, should be in [Unit] but in order to support systemd <229,
# it is also supported to have it here.
StartLimitInterval=10
StartLimitBurst=5

[Install]
WantedBy=multi-user.target

Datadog Agent を起動したくなったら /path/to/datadog-agent/disabled を削除した上で, 以下のようにサービスを起動すれば良いです.

sudo systemctl start datadog-agent

例えば...

EC2 の User data には以下のように仕込むことで, 起動時にサービスの起動を制御出来るようになる... はず. (EC2 に environment というタグキーが付与されていて, 開発環境の EC2 は dev がタグの値が付与される場合)

#!/bin/bash

INSTANCE_ID=$(curl -s http://169.254.169.254/latest/meta-data/instance-id)
ENVIRONMENT=$(aws --region=ap-northeast-1 ec2 describe-tags \
  --filters="Name=resource-id,Values=${INSTANCE_ID}" \
  --query='Tags[?Key==`environment`].Value' --output=text)

if [ "${ENVIRONMENT}" == "dev" ];
  touch /path/to/datadog-agent/disabled
fi

実際に開発環境と見立てた EC2 で Datadog Agent を起動しようとすると, 一見は起動したように見えるが, 実際には起動していないことが判ります.

$ sudo systemctl start datadog-agent
$ sudo systemctl status datadog-agent
● datadog-agent.service - Datadog Agent
   Loaded: loaded (/usr/lib/systemd/system/datadog-agent.service; enabled; vendor preset: disabled)
   Active: inactive (dead) since Sat 2020-04-11 11:27:33 JST; 1 day 6h ago
Condition: start condition failed at Sun 2020-04-12 18:02:57 JST; 2s ago
           ConditionPathExists=!/path/to/datadog-agent/disabled was not met
 Main PID: 27623 (code=exited, status=0/SUCCESS)

Warning: Journal has been rotated since unit was started. Log output is incomplete or unavailable.

以上

メモでした.

それぞれの環境毎に AMI を用意すれば良くないかい?ってセルフ突っ込みをしたいけど, AMI を作る際の手を抜きたいし, 開発環境でもちょっと Datadog Agent を動かしたいなあってことがある時に disabled ファイルだけ削除すればシュッと動かせるので個人的には悪い手法ではないと思っています.

参考

man7.org