terraform cloudで初めるAWS その4: cloud-init編

Share on:

これはシリーズ化する予定なので続きは←リンクからどうぞ。

ちなみに最低限AWSでEC2を起動してSSHした事程度は事ある人向けの記事です

前回まで

ボリュームをアタッチしてファイルシステムを作ってmountしてみる所までやりました。ただ、マウントの自動化は出来ていないという所までやりました。

cloud-initとは

Linux用の構成スクリプトです。今は提供されたAMIイメージを適当に起動していますがこれが起動した後に最低限の構成を行うのがcloud-initであります。

もともとEC2用に開発されたものではありますが実は今は汎用的に使う事ができるそーです(他で使ったことない)、が、やっぱりEC2で開発されたものなのでEC2では使えるぞって事になります。

ためしに適当に作成したEC2インスタンスにSSHして以下のコマンドを確認してみましょう。

1$ sudo cloud-init --version
2cloud-init 0.7.7

このように全てのEC2イメージはこれで構成されているはずで、つまりコマンドが入ってたりこの仕組みが使えるという事になります。

ちなみにオフィシャルドキュメントはここです

https://cloudinit.readthedocs.io/en/latest/index.html

cloud.cfgを見てみよう

Debianの場合なぜ「admin」なんていうユーザが作成されているかがここで理解できてきます。

/etc/cloud/cloud.cfg(抜粋)

 1# System and/or distro specific settings
 2# (not accessible to handlers/transforms)
 3system_info:
 4   # This will affect which distro class gets used
 5   distro: debian
 6   # Default user name + that default users groups (if added/used)
 7   default_user:
 8     name: admin
 9     sudo: ALL=(ALL) NOPASSWD:ALL
10     shell: /bin/bash
11     lock_passwd: True
12     gecos: Debian
13     groups: [adm, audio, cdrom, dialout, dip, floppy, netdev, plugdev, sudo, video]
14     sudo: ["ALL=(ALL) NOPASSWD:ALL"]
15     shell: /bin/bash

なるほど、内容はわかったがどうやって変更する?

まあ問題はこれでしょう。これはuser_dataという仕組みで注入する事ができます

https://docs.aws.amazon.com/ja_jp/AWSEC2/latest/UserGuide/user-data.html

細かい設定を読むのは酷なので問題の「terraformから注入」を行います。

その前に現在のEC2関連の設定を見ておきましょう。

1resource "aws_instance" "web" {
2  instance_type = "t2.micro"
3  ami           = "ami-0662319323823ba88" # jessie
4  subnet_id     = aws_subnet.pub.id
5  key_name      = "xxxxxxxx"
6  tags = {
7    Name = local.workspace
8  }
9}

ここに

1  user_data     = data.template_cloudinit_config.web.rendered
2  tags = {
3    Name = local.workspace
4  }

こんなのを入れました。要するにuser_dataって奴です。見ての通りdata(data source)で定義されていますんで、実物のデータを用意する必要があります。

1data "template_cloudinit_config" "web" {
2  gzip          = true
3  base64_encode = true
4
5  part {
6    content_type = "text/cloud-config"
7    content      = templatefile("cloud-init.yml", {})
8  }
9}

この設定を見るとわかるように

1    content      = templatefile("cloud-init.yml", {})

ここからcloud-init.ymlというファイルを用意する必要があるのがわかります。これを作って注入すればよさそうですね。 ,{} の部分は引数を渡せるのですが、今回は使いません

ディスクをマウントする

cloud-init.ymlですが、これは実はつきつめると結構奥の深いものになっています。なので今回はディスクのマウントのみに絞って解説します。とはいえ、それだけだと寂しいのでtimezoneも設定してみます。

cloud-init.yml

1#cloud-config
2
3timezone: "Asia/Tokyo"
4
5mounts:
6  - [/dev/xvdf1, /data, ext4, "rw,noatime", "0", "0"]

このようなyamlファイルを配置してcommitします。

これでterraform cloudからapplyします。するとマシンは作り直しになると思われます。

なおボリュームのデタッチはなんか結構失敗しますんでそういう場合は手動でインスタンスを終了してください。

これで起動しadminとかでsshして以下のコマンドを起動してみると…

1$ date
2Tue Oct 13 15:34:10 JST 2020

JSTになっていますが

1$ df -h
2Filesystem      Size  Used Avail Use% Mounted on
3/dev/xvda2      7.8G  1.1G  6.4G  14% /
4udev             10M     0   10M   0% /dev
5tmpfs           200M  4.2M  196M   3% /run
6tmpfs           500M     0  500M   0% /dev/shm
7tmpfs           5.0M     0  5.0M   0% /run/lock
8tmpfs           500M     0  500M   0% /sys/fs/cgroup

ボリュームはマウントされていません。しかし /etc/fstab をみると

1$ cat /etc/fstab
2UUID=711e1ec2-2a36-4405-bf46-44b43cfee42e / ext4 defaults 1 1
3/dev/xvdf1      /data   ext4    rw,noatime,comment=cloudconfig  0       0

このようなエントリはみえます。手で

1$ sudo mount -a

とかすればマウントできて、ディスクの容量などがdfコマンドで見る事とかできますが。

1$ df -h
2Filesystem      Size  Used Avail Use% Mounted on
3/dev/xvda2      7.8G  1.1G  6.4G  14% /
4udev             10M     0   10M   0% /dev
5tmpfs           200M  4.2M  196M   3% /run
6tmpfs           500M     0  500M   0% /dev/shm
7tmpfs           5.0M     0  5.0M   0% /run/lock
8tmpfs           500M     0  500M   0% /sys/fs/cgroup
9/dev/xvdf1       20G   44M   20G   1% /data

んー、なんかイマイチなので再起動させておきます。この辺もうちょっといい方法があるやもしれません。 いずれにせよ、タイムゾーンなんかを変更した場合は再起動させておくのが無難らしいという話はあります。

再起動する場合power_stateというエントリで実行するからこれを追記します。

1power_state:
2  mode: reboot
3  message: "Rebooting ..."
4  timeout: 30

これを適当なclout-init.ymlの中に書いておきます。なお、clout-init.ymlは書いた順番に実行されるわけではないので注意ください。今回はこの辺掘り下げません。マシンを破壊して戻した時に正しく表示されていればokです。

なお、/var/log/cloud-init.log

1Oct 13 07:02:23 ip-192-168-1-236 [CLOUDINIT] cc_power_state_change.py[DEBUG]: After pid 411 ends, will execute: shutdown -r now Rebooting ...

とか表示されていると思います。興味があればどうぞ。

ちなみに

cloud-initもガッツリ書けばそこそこチューニングできますが、限界もあります。

冒頭

Linux用の構成スクリプトです。今は提供されたAMIイメージを適当に起動していますがこれが起動した後に最低限の構成を行うのがcloud-initであります。

と書きましたが、起動する前に仕掛けておかないといけないものもあるので、これはイメージを作成する事になったりするんですが、そこまでは今回やりません、多分。

apache2 + libapache2-mod-php5 を入れてみる

debian jessieを使ってる場合なんですが、こいつはちょっとクセのあるイメージになっており(なんせ古いすぎる)、パッケージを追加するにはいろいろと面倒くささがあります。仕方がないのでruncmdで構成してみました。

なお、これはYAMLファイルの先頭に書こうがどこに書こうが最後の方に実行されます。何故かはここでは書きませんが

1runcmd:
2  - [ sh, -c, echo "setting up apt" ]
3  - [ rm, "/etc/apt/sources.list.d/backports.list"]
4  - [ apt, "update"]
5  - [ apt, "upgrade", "-y"]
6  - [ apt, "install", "-y", "libapache2-mod-php5"]

さらにwebサーバということなので80番を空けときます。

ただし、単品のテスト用という事で、ロードバランサ経由でhttp/httpsにアクセスさせる時は、まあ考えてみてください。

 1resource "aws_security_group" "web" {
 2  vpc_id      = aws_vpc.vpc.id
 3  name        = "webfront"
 4  description = "Allow http"
 5  ingress {
 6    from_port   = 80
 7    to_port     = 80
 8    protocol    = "tcp"
 9    cidr_blocks = ["0.0.0.0/0"]
10  }
11}
12
13resource "aws_instance" "web" {
14  instance_type = "t2.micro"
15  ami           = "ami-0662319323823ba88" # jessie
16  subnet_id     = aws_subnet.pub.id
17  key_name      = "xxxxxx"
18  user_data     = data.template_cloudinit_config.web.rendered
19
20  # ↓ このへん
21  vpc_security_group_ids = [
22    aws_security_group.web.id,
23    aws_vpc.vpc.default_security_group_id
24  ]
25
26  tags = {
27    Name = local.workspace
28  }
29}

ここまでで

clount-initを使った簡単な構成管理でボリュームをmountできるようにしました。

また、かなり強引にwebサーバを起動できるようにしました。

まあこれで概ね使い出せるんですが、次回はそうっすねえ、、DBサーバですかね?

よろしくお願いします。