EC2 ユーザーデータと cloud-init の活用完全ガイド

EC2 起動時に走る「ユーザーデータ」と、それを実行する OS 側ツール「cloud-init」の関係を整理。シェルスクリプト形式・cloud-config 形式・MIME マルチパート形式の使い分け、16 KB 制限の回避、毎回実行への切替、Auto Scaling/Golden AMI と組み合わせた現場の定番パターンまでまとめる。

EC2 を「起動した瞬間に使える状態」にするための仕組みがユーザーデータ × cloud-init。Golden AMI で固めるか、起動時に動的に整えるか — 設計の出発点になる二択を整理する。


1. 概要(端的に)

Amazon EC2 を起動するとき、インスタンス初回ブート時に走らせるスクリプトや設定を「ユーザーデータ(user data)」として渡せる。これを実際に解釈・実行する OS 側の常駐ツールが cloud-init。Amazon Linux・Ubuntu・RHEL・SUSE などの公式 AMI には標準搭載されており、追加インストール不要で動く。

二者の関係を一行でまとめると:

  • ユーザーデータ = EC2 に「外から渡す指示書」(メタデータサービス経由で取得される)
  • cloud-init = OS の中でその指示書を読んで実行する常駐ツール

「インスタンスを叩いて 5 分後にはユーザーが触れる Web サーバーが立っている」「Auto Scaling の新ノードが自動で監視エージェントを入れて ALB に組み込まれる」— こうした体験はほぼすべて、この 2 つの組み合わせで実装されている。


2. ユーザーデータの基本仕様

項目仕様
サイズ上限16 KB(Base64 エンコード後 21,847 バイト)
取得経路インスタンスメタデータサービス(IMDS)— リンクローカル 169.254.169.254/latest/user-data
実行ユーザーLinux:root / Windows:Administrator
実行タイミング(既定)初回ブートのみ 1 回(cloud-init 側の scripts-useronce
変更タイミング停止 → 編集 → 起動 のサイクル(実行中インスタンスでは編集不可)
ログ出力先Linux:/var/log/cloud-init.log/var/log/cloud-init-output.log

ユーザーデータ自体はただの文字列で、Linux インスタンスでは大きく 3 フォーマットが使える。

2-1. シェルスクリプト形式

#!/bin/bash
yum update -y
yum install -y nginx
systemctl enable --now nginx
echo "Hello from EC2" > /usr/share/nginx/html/index.html

#!/bin/bash で始まる素朴な形式。書きやすさが圧倒的で、トラブル時もシェルとして再実行・デバッグできるのが利点。

2-2. cloud-config 形式

#cloud-config
package_update: true
packages:
  - nginx
  - amazon-cloudwatch-agent
write_files:
  - path: /usr/share/nginx/html/index.html
    content: "Hello from cloud-init"
runcmd:
  - systemctl enable --now nginx

#cloud-config で始まる YAML。宣言的で、パッケージ導入・ファイル配置・ユーザー追加・SSH キー登録などを順序を意識せず書ける。マルチディストロ対応のレシピを 1 本で共有しやすい。

2-3. MIME マルチパート形式

シェルスクリプトと cloud-config を同時に渡したい場合に使う。EKS の Managed Node Group や Auto Scaling グループの起動テンプレートで実際によく目にする形。

Content-Type: multipart/mixed; boundary="==BOUNDARY=="
MIME-Version: 1.0

--==BOUNDARY==
Content-Type: text/cloud-config; charset="us-ascii"

#cloud-config
cloud_final_modules:
  - [scripts-user, always]

--==BOUNDARY==
Content-Type: text/x-shellscript; charset="us-ascii"

#!/bin/bash
echo "boot at $(date)" >> /var/log/boot-marker.log
--==BOUNDARY==--

上の [scripts-user, always] が「毎回ブート時に再実行」へ切り替えるおまじない(後述)。


3. cloud-init の役割

cloud-init はクラウド汎用のインスタンス初期化ツールで、もともとは AWS 向けに Canonical が開発した。AWS では次の流れで動く。

  1. インスタンス起動 → systemd が cloud-init-local.servicecloud-init.servicecloud-config.servicecloud-final.service の順に呼び出す
  2. cloud-init が IMDS からユーザーデータとメタデータ(ホスト名・リージョン・IAM ロール等)を取得
  3. ユーザーデータの先頭バイトを見てハンドラを選択#! → シェル、#cloud-config → YAML パーサ、MIME → 分解)
  4. モジュールを順に実行(パッケージ更新・SSH キー登録・タイムゾーン設定・ホスト名設定・ユーザー作成…)
  5. 最後に runcmd / scripts-user でユーザー固有スクリプトを実行

設定ファイル /etc/cloud/cloud.cfg をのぞくと、初回のみ動くモジュールcloud_init_modules)と毎回動くモジュールcloud_config_modules / cloud_final_modules)の振り分けが見える。ユーザーデータの再実行制御もここで決まっている。


4. ユーザーデータ × cloud-init:書き方の使い分け

ユーザーデータ 3 フォーマット比較
評価項目
シェルスクリプト
cloud-config (YAML) 推奨
MIME マルチパート
先頭バイト `#!/bin/bash` 等 `#cloud-config` `Content-Type: multipart/...`
書きやすさ ◎(手に馴染む) ○(YAML を覚える必要) △(境界文字列の管理)
宣言性 ×(命令的)
マルチディストロ対応 △(パッケージ管理コマンドが異なる)
デバッグ容易性 ◎(シェルで再実行可) ○(cloud-init log を読む) △(分解して確認)
毎回ブート時に再実行 cloud-init 側設定で可 cloud-config で明示宣言 ◎(best practice)
想定ユースケース アドホック起動・PoC 本番ブートストラップ Auto Scaling / EKS Node Group
PoC はシェル、運用は cloud-config、Auto Scaling や EKS は MIME マルチパートが現実解。

5. 現場で多い活用パターン 6 つ

5-1. Web サーバーの即時セットアップ

yum install -y nginxsystemctl enable --now nginx までを 1 本で書く。検証環境やデモ用 EC2 で最初に書く定番。

5-2. CloudWatch エージェントの自動導入

CloudWatch Agent をインストールし、設定 JSON を SSM Parameter Store から取得して amazon-cloudwatch-agent-ctl で起動。Auto Scaling の新ノードでもログ集約が自動でつながる。詳細は CloudWatch Logs も参照。

5-3. ECS / EKS のクラスターノード登録

ECS Optimized AMI なら echo "ECS_CLUSTER=my-cluster" >> /etc/ecs/ecs.config、EKS なら /etc/eks/bootstrap.sh my-cluster --kubelet-extra-args ... をユーザーデータに書く。これでオートスケールしたノードがそのままクラスターに参加する。

5-4. SSM Session Manager 用エージェント有効化

Amazon Linux 2023 では SSM Agent はプリインストールだが、IAM ロールAmazonSSMManagedInstanceCore)の付与systemctl enable amazon-ssm-agent だけ書いておくと、SSH 鍵運用を一切やらずに踏み台レス化できる。

5-5. Golden AMI × 差分のみユーザーデータ

EC2 Image Builder で焼いた Golden AMI を使い、ユーザーデータでは環境固有の差分(環境変数、シークレット参照、起動メッセージ)だけを書く。起動時間 1〜2 分で本番投入できる。

5-6. Auto Scaling 起動テンプレートでのブートストラップ

EC2 Auto Scaling の起動テンプレートにユーザーデータを埋め込み、新ノードが「起動 → エージェント導入 → ヘルスチェック合格 → ALB ターゲット組み込み」まで自走する形にする。MIME マルチパートで「毎回実行」にしておくと、停止からの再起動でも整合性が崩れない。


6. つまずきポイントとトラブルシューティング

よくある失敗と対処

症状原因対処
スクリプトが動いていない既定の「初回のみ」設定scripts-user: always で毎回実行に切替
編集を反映できない実行中インスタンスでは編集不可停止 → 編集 → 起動 のサイクル
16 KB を超えるスクリプトが肥大化S3 に本体を置き、ユーザーデータでは aws s3 cp → 実行に分割
環境変数が読めない.bashrc を期待しているcloud-init は非ログインシェル — /etc/profile.d/ に書く
IAM 権限不足で失敗インスタンスプロファイル未設定起動時に IAM ロール(S3/SSM 等)をアタッチ
Windows で動かないPowerShell 構文が必要<powershell></powershell> または <script></script> タグで囲む

デバッグの第一手

# ユーザーデータの実行出力を確認
sudo less /var/log/cloud-init-output.log

# cloud-init 全体のフェーズログ
sudo less /var/log/cloud-init.log

# IMDS から実際に渡ったユーザーデータを取得
IMDS=169.254.169.254
TOKEN=$(curl -X PUT "$IMDS/latest/api/token" \
  -H "X-aws-ec2-metadata-token-ttl-seconds: 60")
curl -H "X-aws-ec2-metadata-token: $TOKEN" \
  "$IMDS/latest/user-data"

IMDSv2 を強制している環境ではトークンを取ってから user-data エンドポイントを叩く点だけ注意。


7. メリット・デメリット


8. ベストプラクティス

  • 「焼くか、起動時に流すか」の境界を最初に決める — 重い処理(依存ライブラリ/カーネルパッチ)は EC2 Image Builder で AMI 化し、ユーザーデータは環境差分だけに絞る。
  • 16 KB を超えたら S3 へ逃がす — ユーザーデータは「ブートローダー」と割り切り、本体スクリプトは S3 に置いて aws s3 cp で取得 → 実行する形にする。
  • 必ず IAM ロールをアタッチ — Secrets Manager・Parameter Store・S3 を扱う前提なら、最初から最小権限ロールをセット。
  • set -euxo pipefail をスクリプト先頭に — エラー時に黙って続行されると後追いが地獄。失敗即停止+ログを残す。
  • cloud-init-output.log を CloudWatch Logs に送るawslogs.conf で常時取り込んでおくと、起動失敗時に SSH 不要で原因が読める。
  • MIME マルチパートで再実行可能設計 — Auto Scaling や EKS Node Group では「毎回 boot 時に整合性を取り直す」設計が結果として一番安定する。
  • 検証は cloud-init を再実行できる状態でcloud-init clean --logs → 再起動で「真の初回ブート」を再現できる。AMI 化前の最終チェックに使う。
  • シークレットを直書きしない — ユーザーデータは IMDS で誰でも取得できる(同インスタンス内の任意プロセスから読める)。値は Secrets Manager / Parameter Store の参照に留める。

9. 関連用語

  • Amazon EC2 — ユーザーデータが届く対象の仮想サーバー
  • AMI — cloud-init を含むベースイメージ(Golden AMI 戦略の基盤)
  • EC2 Image Builder — 「焼く側」のマネージドサービス
  • EC2 Auto Scaling — ユーザーデータ × 起動テンプレートでスケール時のブートストラップを自動化
  • Systems Manager — Parameter Store・Session Manager・RunCommand の連携先
  • IAM Role — インスタンスプロファイルとして S3/SSM へのアクセス権限を付与
  • CloudWatch Logscloud-init-output.log の集約先
  • AWS CloudFormationUserData プロパティで宣言的に管理

10. 関連サイト

AWS 公式

参考記事



🎓 試験での出題傾向

試験重要度主な出題パターン
CLFEC2 起動時の初期化手段としてユーザーデータが使えることの理解
SAAAuto Scaling × ユーザーデータ × Golden AMI の組み合わせ、起動時間短縮設計
DVAcloud-config・MIME マルチパートの形式選択、再実行制御
SOA16 KB 制限・トラブルシュート・CloudWatch Logs へのログ集約

特に SAA / SOA では「Auto Scaling で新ノードが立ち上がったら自動でエージェントを入れたい」「Golden AMI と組み合わせてスケール時間を最小化したい」場面でユーザーデータ vs Image Builder vs SSM RunCommandの選択を問う問題が頻出する。「重い処理は Image Builder で AMI 化/軽い差分はユーザーデータ/後追い変更は SSM」の三層構造で覚えておくと判断がブレない。