本当は書きたくない低レイヤーネタ。が、知ったことは記録しておきたいので。
表題の件、今さら? なんだけどね…、実は最近までcloud-initの存在すら知りませんでした。AWSは個人的に利用しているとはいえ、検証目的なんで低レイヤーな部分は放置だし、一旦作ったAMIを使いまわしているだけなので、知らないことも沢山ある。
cloud-initは一言でいうと、Amazon Linux(それ以外もあると思うがよくわからない)インスタンス起動時にガリガリ、ゴリゴリと勝手にカスタマイズしてくれるヤツ。便利といえば便利で、おせっかいといえばおせっかい。
本題。Amazon Linuxにおける以下のような一般的な対処があるとする。このようなcloud-initへの対応を、cloud-initで制御したい。最後のパスワードログイン以外はありがちな対応と想定する。
- ストレージサイズをデフォルトの8GBから大きいサイズに指定してインスタンスを起動した場合、インスタンスログイン後にresize2fsしてやる必要がある。
- タイムゾーンはデフォルトでUTCだがJSTに変えたい。
- ロケールをja_JP.UTF-8としたい。
- 自動アップデートを抑止したい。
- パスワードログインはデフォルトで無効になる。これを有効にして、かつ複製したAMIから起動したインスタンスでもcloud-initによる上書きを抑止したい。
これを、起動時に渡すUserDataに記述するとこうなる。すまんが早く寝たいので細かい説明は…
#cloud-config ssh_pwauth: true repo_upgrade: none locale: ja_JP.UTF-8 runcmd: - [ cp, /usr/share/zoneinfo/Asia/Tokyo, /etc/localtime] - [ resize2fs, /dev/xvda1]
マネジメントコンソールでUserDataを記載するところは、「ステップ3: インスタンスの詳細の設定」。「高度な詳細」に隠れているので、広げる。UserDataはaws cliやAPIから直接起動するときにもセットできるはずだが、記述方法はすまんが早く…
試しにストレージサイズを9GBに指定して起動してみる。起動後、ログインして確認した結果。
指定した通りになってる。よしよし。
$ df -h
ファイルシス サイズ 使用 残り 使用% マウント位置
/dev/xvda1 8.8G 1.5G 7.2G 17% /
devtmpfs 490M 56K 490M 1% /dev
tmpfs 499M 0 499M 0% /dev/shm
ロケールも指定した通り。
$ sudo cat /etc/sysconfig/i18n
LANG=ja_JP.UTF-8
タイムゾーンは確かにJSTになっているが…
$ date
2015年 7月 15日 水曜日 21:08:04 JST
/etc/sysconfig/clockはUTCのまま。
$ cat /etc/sysconfig/clock
ZONE="UTC"
UTC=true
“cp /usr/share/zoneinfo/Asia/Tokyo /etc/localtime”は実行された様子だが、/etc/sysconfig/clockはいじってないよということか。確かに。
なので以下、別途やっとおく必要がある。
$ sudo vim /etc/sysconfig/clock
ZONE="Asia/Tokyo"
UTC=False
パスワード認証。有効になってる。
$ grep Pass /etc/ssh/sshd_config
PasswordAuthentication yes
#PermitEmptyPasswords no
# PasswordAuthentication no
(略)
うむ、これは楽だ。ついでにSwap領域作成もcloud-initでできないものかと軽く調べてみると、こんな風に書いてできる様子。これはストレージの追加時にInstance Storeを/dev/sdbとして割り当てて、Instance Store(ephemeralディスク)をSwap領域にするという前提。しかしすべてのインスタンスタイプにephemeralディスクがアタッチ可能ではないので、適用できないケースもある。
mounts: - [ ephemeral0, swap, swap ,"defaults", "0", "0" ] bootcmd: - mkswap /dev/xvdb - swapon /dev/xvdb
ちなみに自動アップデート抑止の対応はOS側(yumの設定だったか)でも別途必要だと思うが、ここでは割愛。
先ほどのUserDataに書いた設定を/etc/cloud/cloud.cfgに書いておけば、このインスタンスを元にしたAMIを起動するときにはUserDataは必要ない、と考えていいのかな。cloud.cfgの中身はこんな風。
$ cat /etc/cloud/cloud.cfg
# WARNING: Modifications to this file may be overridden by files in # /etc/cloud/cloud.cfg.d # If this is set, 'root' will not be able to ssh in and they # will get a message to login instead as the default user (ec2-user) disable_root: true # This will cause the set+update hostname module to not operate (if true) preserve_hostname: true datasource_list: [ Ec2, None ] repo_upgrade: security repo_upgrade_exclude: - kernel - nvidia* - cudatoolkit mounts: - [ ephemeral0, /media/ephemeral0 ] - [ swap, none, swap, sw, "0", "0" ] # vim:syntax=yaml
以下ディレクトリにカスタムcfgを放り込んでおいても、よしなにやってくれるらしい。
$ ls -l /etc/cloud/cloud.cfg.d
合計 16
-rw-r–r– 1 root root 2594 3月 5 05:39 00_defaults.cfg
-rw-r–r– 1 root root 1963 3月 5 05:40 05_logging.cfg
-rw-r–r– 1 root root 586 2月 12 08:32 10_aws_yumvars.cfg
-rw-r–r– 1 root root 141 10月 11 2014 README
READMEにはこう書いてあるので、実行順序はファイル先頭の数値で制御されるっぽい。
# All files in this directory will be read by cloud-init # They are read in lexical order. Later files overwrite values in # earlier files.
ではやってみるか、と/etc/cloud/cloud.cfg.d/06_custom.cfgファイルを作成して、先ほどのUsarDataを貼り付けておく。ログに記録されるようにコメントを追加。
/etc/cloud/cloud.cfg.d/06_custom.cfg
ssh_pwauth: true repo_upgrade: none locale: ja_JP.UTF-8 runcmd: - [ echo, 'Set time zone' ] - [ cp, /usr/share/zoneinfo/Asia/Tokyo, /etc/localtime] - [ echo, 'Extend disk size' ] - [ resize2fs, /dev/xvda1]
この状態でAMIを取得。そのAMIを元に、新たにインスタンスを起動してみる。今度はUserDataには何も入れない。ストレージサイズを11GBに指定してみた。結果、期待値通りだった。
$ df -h
ファイルシス サイズ 使用 残り 使用% マウント位置
/dev/xvda1 11G 2.5G 8.2G 24% /
devtmpfs 490M 56K 490M 1% /dev
tmpfs 499M 0 499M 0% /dev/shm
パスワード認証も上書きされることがなく、他の要素もOK。
ログをみてみると、コメントが記録されているので06_custom.cfgが実行されたはず。最後になんか言われているが気にしない…
/var/log/cloud-init-output.log
: : Set time zone Extend disk size resize2fs 1.42.12 (29-Aug-2014) The filesystem is already 2883067 (4k) blocks long. Nothing to do!
cloud-init、使いこなせれば結構便利そう。
AWSの場合、低レイヤーな部分はAnsible等ではなくcloud-initにやらせた方がよさげである。というか、そうするべきなんだろう。
参考
Amazon EC2(Linux)システム管理で知らないとハマる5つの環境設定
AmazonLinux起動時にタイムゾーン、ホスト名、ディスク拡張、アップデートを実施する方法(cloud init、user data)
追記:2014/07/19
CentOSのイメージでやってみたら、こっちも同様にできた。/etc/cloud/cloud.cfgの中身はAmazon Linuxとは異なっていた。プラットフォームによってどのように適用されるのか、詳しいことはわからない。