[Terraform]EC2 LinuxのOS設定やパッケージ追加をユーザデータとcloud-initで完結させる

OSやミドルウェア設定をユーザデータとcloud-initを活用して楽しよう!
2021.11.14

こんにちは!コンサル部のinomaso(@inomasosan)です。

先日、ユーザデータでApacheセットアップしたブログを書きましたが、どうせならOSの設定等もまとめて実施したくなりました。
ちょっと調べてみると、ユーザデータとcloud-initディレクティブだといい感じに実装できそうだったので、検証してみました。

やりたいこと

以下をEC2初回起動時に自動実行

  • OS設定
    • 全てのパッケージアップデート
    • ロケール設定
    • タイムゾーン設定
    • ホスト名設定
    • カスタムAMIからEC2起動時にホスト名、ロケール、タイムゾーンの上書き回避
  • Apache設定
    • パッケージ追加
    • ディレクトリ配下の所有者やグループ変更
    • サービス自動起動設定
  • 1分後にOS再起動

検証環境

今回実行した環境は以下の通りです。

項目 バージョン
macOS BigSur 11.6
Terraform 1.0.7
AWSプロバイダー 3.65.0

Terraformコード

aws_ec2.tf

resource "aws_instance" "ec2" {
  ## AmazonLinux2
  ami = "ami-0e60b6d05dc38ff11"
  ...中略...
  user_data = file("cloud-config.cfg")
}

cloud-config.cfg

#cloud-config
repo_update: true
repo_upgrade: all

locale: ja_JP.utf8
timezone: Asia/Tokyo

packages:
 - httpd

runcmd:
 - chown -R apache:apache /var/www/html
 - systemctl start httpd
 - systemctl enable httpd
 - hostnamectl set-hostname hogehoge
 - sudo cp -p /etc/cloud/cloud.cfg /etc/cloud/cloud.cfg.original
 - [ sed, -i, -e, '$a preserve_hostname: true', /etc/cloud/cloud.cfg, --follow-symlinks]
 - sed -i -e "s/- locale/#- locale/" -e "s/- timezone/#- timezone/" /etc/cloud/cloud.cfg --follow-symlinks
 - shutdown -r +1

cloud-config.cfgの解説

1行目:#cloud-config

ユーザーデータでcloud-initディレクティブをインスタンスに渡します。

2-3行目:repo_update, repo_upgrade

repo_updateによってローカルにキャッシュされているパッケージリストがリポジトリと同期され最新の状態になり、repo_upgradeによって実際にパッケージの更新が行われます。

5-6行目:locale, timezone

ロケールとタイムゾーンを設定します。

8行目:packages

指定したパッケージをインストールします。

11行目:runcmd

指定したコマンドを実行します。

17行目:preserve_hostname

カスタムAMIからEC2起動時にホスト名の上書きを回避するため、preserve_hostnametrueに設定します。 また、YAML形式なのでコロン(:)を含めるために、括弧([])の配列で書く必要があります。 尚、/etc/cloud/cloud.cfgにシンボリックリンクは無いのですが、念のため--follow-symlinksオプションにてsedの書き換えで実ファイルになり、リンクが切れてしまうことを防ぎます。

18行目:locale, timezone

カスタムAMIからEC2起動時にロケールとタイムゾーンの上書きを回避するために、- locale- timezoneをコメントアウトしています。

19行目:shutdown

yum updateによるkernelやglibcの有効化や、ホスト名の反映のために、1分後にOS再起動します。

参考URL

まとめ

OSやミドルウェア設定のためにAnsible等を導入するのも中々大変なので、ユーザデータとcloud-initを活用して楽していきたいですね!

この記事が、どなたかのお役に立てば幸いです。それでは!