【AWS】EC2起動停止でCloudWatch AgentがEFS上のログを「二重送信・先頭から再読込」する不具合をsystemdで完璧に解決する

EFSアイキャッチ

AWSを運用していて、「EC2を停止・起動(再起動)するたびに、CloudWatchに過去の同じログが大量に再送信されて二重課金やノイズになっている……」という経験はありませんか?

この現象、実は EFS(Elastic File System)のマウントタイミングとCloudWatch Agentの起動順序のズレ(タイミング問題)が原因です。

本記事では、AWSサポート推奨の回避策をもとに、Amazon Linux環境でsystemdの設定をチューニングし、この二重読み込み問題を100%完璧に解決する手順を実体験ベースで徹底解説します!

📋 前提環境

  • OS: Amazon Linux
  • 構成: EFSを /efs-tmp/ にマウントし、その中のログファイル(efs-text.txt)をCloudWatch Agentで監視
  • 現在の fstab 設定(自動マウント設定):
fs-xxxxxx.efs.ap-northeast-1.amazonaws.com:/ /efs-tmp efs defaults,_netdev 0 0

ログファイルの内容は下記

line0
line1
line2
line3
line4
line5
line6
line7
line8
line9
Test log entry at Thu Jul 16 15:20:11 UTC 2026

🚨 発生する不具合

EC2を停止 ➡ 起動すると、すでにCloudWatchに送信済みの過去ログ(line0line9 など)が、毎回すべて先頭から再送信(巻き戻り・重複)されてしまう。

🧐 原因:起動タイミングの「すれ違い」

OS起動時、実は以下のような順番でプロセスが動いてしまっています。

  1. OSが起動する。
  2. CloudWatch Agent が爆速で起動する。
  3. CloudWatch Agentが /efs-tmp/efs-text.txt を読みに行こうとするが、この時点でまだEFSのマウント処理(ネットワーク越し)が完了していない。
  4. エージェントの視点からは、一時的に「ファイルが消えた(空になった)」ように見える。
  5. その直後、遅れてEFSのマウントが完了し、ファイルが出現する。
  6. エージェントは「あれ?新しいファイルが急に作られたぞ!」と勘違いし、読込位置をリセットして先頭から全行を読み直してしまう。

これを防ぐには、「EFSのマウントが100%完了するまで、CloudWatch Agentの起動を絶対に待たせる」という設定が必要です。

2. 解決のためのロードマップ

AWSサポートも推奨する「シーケンシャルマウントサービス」を自作し、CloudWatch Agentの起動順序を制御します。

  • Step 0: /etc/fstab の「自動マウント」を無効化する
  • Step 1: EFSを確実に順番マウントする systemd サービスを作る
  • Step 2: CloudWatch Agentに「マウント完了を待つ」依存関係を追加する(※超重要・落とし穴あり
  • Step 3: 反映とテスト

🛠️ 具体的な解決手順

⬛ Step 0:EFSの自動マウント設定をやめる

標準の自動マウント処理(fstabによるフライング起動)を停止し、後ほど作成するカスタムサービス側でマウントを制御するようにします。

sudo vi /etc/fstab

対象のEFSマウント設定のオプション末尾に noauto を追記します。

修正前:

fs-xxxxxx.efs.ap-northeast-1.amazonaws.com:/ /efs-tmp efs defaults,_netdev 0 0

修正後:

fs-xxxxxx.efs.ap-northeast-1.amazonaws.com:/ /efs-tmp efs defaults,_netdev,noauto 0 0

設定読み込み

mount -a

マウントが取れていることを確認

df -h

⬛ Step 1:EFSシーケンシャルマウントサービスを作成する

起動時に、確実にEFSのみをピンポイントでマウントするサービスファイルを作成します。

新しいサービスファイルを作成します。

sudo vi /etc/systemd/system/mount-efs-sequentially.service

以下の内容を貼り付けて保存します。

[Unit]
Description=Workaround for mounting EFS file systems sequentially at boot time
After=remote-fs.target

[Service]
Type=oneshot
# EFSマウントヘルパー(amazon-efs-utils)を使っている場合は efs、通常のNFSマウントなら nfs4 を指定
ExecStart=/bin/mount /efs-tmp
RemainAfterExit=yes

[Install]
WantedBy=multi-user.target

サービスを有効化します。

sudo systemctl daemon-reload
sudo systemctl enable mount-efs-sequentially.service

マウントできていることを確認

df -h

⬛ Step 2:CloudWatch Agentに「このサービスを待つ」設定を追加する

ここが最重要かつ、多くのエンジニアが躓くシステム管理上の罠(落とし穴)があります!

CloudWatch Agentの起動ユニットファイルに対して、先ほど作ったマウントサービスを待つように設定を追加します。

sudo systemctl edit amazon-cloudwatch-agent
#またはviエディタで開きたい場合は下記
sudo SYSTEMD_EDITOR=vi systemctl edit amazon-cloudwatch-agent

エディタが開いたら、記述する「場所」に細心の注意を払ってください。

### Anything between here and the comment below will become the new contents of the file

# 👈 必ずこの「隙間」に記述してください!
[Unit]
After=mount-efs-sequentially.service
Requires=mount-efs-sequentially.service

### Lines below this comment will be discarded

### /etc/systemd/system/amazon-cloudwatch-agent.service
# (ここより下の参考用コメント行はすべて自動的に無視されます)

⚠️【重要】ハマる「systemctl edit」の落とし穴

画面の一番下に追記したくなりますが、一番下に書くとすべてシステムに破棄(無視)されます。 必ず、上記の英語コメントの「隙間(間)」に設定を記述してください。

⬛ Step 3:設定の反映と確認

最後に、変更した設定をsystemdにリロードして正しく設定されているか確認します。

# 1. systemdに設定変更を認識させる
sudo systemctl daemon-reload

# 2. 依存関係が正しく設定されたか確認
systemctl show amazon-cloudwatch-agent | grep -E "After|Requires"

出力結果に mount-efs-sequentially.service が含まれていれば設定完了です!

3. 動作テストと確認方法

本当に順序制御が成功したか、EC2を一度「停止 ➡ 起動」して確認します。

① テストログの追記

検証用に、停止前にログを1行追加しておきます。

echo "Test log entry2 at $(date)" | sudo tee -a /efs-tmp/efs-text.txt

② 再起動(停止→起動)後にマウント状況の確認

EC2を停止・起動させたあと、ログインしてマウントされているか確認します。

df -h
設定値確認

/efs-tmp が正しく自動マウントされていれば第一関門突破です。

③ ログ(journalctl)でミリ秒単位の軌跡を答え合わせ

最も確実な証拠は、OSの起動ログ(journalctl)に刻まれています。以下のコマンドを実行します。

sudo journalctl -u mount-efs-sequentially.service -u amazon-cloudwatch-agent -b 0 -o short-precise

🌟 成功時のログ(実機ログ)

Jul 16 16:21:54.291769 ip-... systemd[1]: Starting mount-efs-sequentially.service...
Jul 16 16:21:56.194765 ip-... systemd[1]: Finished mount-efs-sequentially.service...
Jul 16 16:21:56.245017 ip-... systemd[1]: Started amazon-cloudwatch-agent.service - Amazon CloudWatch Agent.

見ての通り、マウント完了(16:21:56.194)のわずか0.05秒後に、満を持してCloudWatch Agent(16:21:56.245)が起動しています!

このミリ秒単位の徹底的な順序制御のおかげで、CloudWatchへの過去ログの重複送信は完全にゼロになりました。

Cloudwatch Logs 上も再度読み込みがされていないのを確認できました。

4. まとめ

EFSのようなネットワークファイルシステムを監視する際、エージェント側の起動速度にマウント速度が追いつかないのはAWS運用における定番の罠です。

  • /etc/fstab の自動マウントは noauto であえて抑える
  • 自作マウントサービス(mount-efs-sequentially.service)を立ち上げる
  • systemctl edit を正しい位置に書き、CloudWatch Agentをその後に走らせる

この3つをセットで行うことで、安全かつ強固なログ収集基盤を構築することができます。同じ事象で重複ログや課金に悩まされている方は、ぜひ試してみてください!