EC2の起動処理で色々やりたいのでUserDataにシェルスクリプトかcloud-configを書いてやってみようと思ったのですが、そもそもどうやって動いているのか起動タイミングや初回起動のみ実行されるのかなど分からなかったので調べてみたり、動作確認してみたメモ
参考
- Linux インスタンスでの起動時のコマンドの実行
- Amazon Linuxのcloud-initの動きについて調べてみた
- Amazon Linuxのcloud-initの実行順番を確認する
- cloud-init を None データソースで動作確認する
- cloud-initでスクリプトが実行されるタイミングを調べてみた
- AWS EC2インスタンス起動時 cloud-initによりホスト名をNameタグ_インスタンスID_IPアドレスに設定する
- cloud-initのper-xxxまとめ
結論
色々確認しましたが、結論としては以下のようでした。
方法 | 実行タイミング | 起動時の実行有無 | ファイルの場所 |
---|---|---|---|
シェルスクリプト | /etc/rc3.d/S98cloud-final | インスタンスIDごとの初回起動 | /var/lib/cloud/instances/インスタンスID/scripts/ |
runcmd(cloud-init) | /etc/rc3.d/S98cloud-final | インスタンスIDごとの初回起動 | /var/lib/cloud/instances/インスタンスID/scripts/ |
/var/lib/cloud/scripts/per-once/* | /etc/rc3.d/S98cloud-final | インスタンスIDに限らず1回のみ | - |
/var/lib/cloud/scripts/per-instances/* | /etc/rc3.d/S98cloud-final | インスタンスIDごとの初回起動 | - |
bootcmd(cloud-init) | /etc/rc3.d/S51cloud-init | 起動都度 | ???(どこにファイルが作成されているのかわからない。。。) |
/var/lib/cloud/scripts/per-boot/* | /etc/rc3.d/S98cloud-final | 起動都度 | - |
なお、/var/lib/cloud/scripts/per-once/配下などへのスクリプトの配置は以下のようにcloud-initのwrite-files(/etc/rc3.d/S51cloud-init)によって行うことでS98cloud-finalでの実行前となり、初回起動時でも実行が可能となります。
#cloud-config
write_files:
- content: |
#!/bin/sh
echo "Per-Once:" `date` >> /var/tmp/test.txt
sleep 3s
owner: root:root
path: /var/lib/cloud/scripts/per-once/once.sh
permissions: '0755'
シェルスクリプト
EC2起動時のUserDataに記述が可能です。
先頭に「#!/bin/bash」を記載し、以降にbashスクリプトを書くことで指定が可能です。
例えば
#!/bin/bash
touch /home/ec2-user/cloud-init
というのを作り、
$aws ec2 run-instances --image-id ami-hogefuga --instance-type t2.micro --subnet-id subnet-xxxx --security-group-ids sg-xxxxx --key-name hogefuga --user-data file://user-data.sh
と実行すると起動時後に/home/ec2-user/cloud-init
というファイルが出来ている事が確認できます。
なお、実行時のログは/var/log/cloud-init.log
に出来ています。
[シェルスクリプト]ファイルの場所
以下に存在しています。なお、i-c834fd3aとなっている部分はインスタンスIDなので起動したものによって異なります。
$sudo cat /var/lib/cloud/instances/i-c834fd3a/scripts/part-001
#!/bin/bash
touch /home/ec2-user/cloud-init
[シェルスクリプト]実行タイミング
一体このスクリプトはいつ実行されるのかという疑問が出ます。
というかそもそもこれってどうやって実行されているのかという話がありますが、cloud-initの中で実行されています。
Amazon Linuxのcloud-initの実行順番を確認する
上記のリンクの下の方に記載されているように**/var/lib/cloud/instances/インスタンスID/scripts/**はcloud-initのscripts-userモジュールによって実行されるようです。
そのscript-userモジュールはいつ実行されるかというのは以下を確認すれば分かります。
# ### DO NOT MODIFY THIS FILE! ###
# This file will be replaced if cloud-init is upgraded.
# Please put your modifications in other files under /etc/cloud/cloud.cfg.d/
#
# Note that cloud-init uses flexible merge strategies for config options
# http://cloudinit.readthedocs.org/en/latest/topics/merging.html
# The top level settings are used as module
# and system configuration.
# A set of users which may be applied and/or used by various modules
# when a 'default' entry is found it will reference the 'default_user'
# from the distro configuration specified below
users:
- default
ssh_pwauth: false
# Example datasource config
# datasource:
# Ec2:
# metadata_urls: [ 'blah.com' ]
# timeout: 5 # (defaults to 50 seconds)
# max_wait: 10 # (defaults to 120 seconds)
locale_configfile: /etc/sysconfig/i18n
mount_default_fields: [~, ~, 'auto', 'defaults,nofail', '0', '2']
resize_rootfs: noblock
resize_rootfs_tmp: /dev
ssh_deletekeys: true
ssh_genkeytypes: [ 'rsa', 'dsa', 'ecdsa' ]
syslog_fix_perms: ~
# The modules that run in the 'init' stage
cloud_init_modules:
- migrator
- rsyslog
- bootcmd
- write-files
- write-metadata
- growpart
- resizefs
- set-hostname
- update-hostname
- update-etc-hosts
- users-groups
- ssh
# The modules that run in the 'config' stage
cloud_config_modules:
- mounts
- locale
- set-passwords
- yum-configure
- yum-add-repo
- package-update-upgrade-install
- timezone
- puppet
- disable-ec2-metadata
- runcmd
# The modules that run in the 'final' stage
cloud_final_modules:
- scripts-per-once
- scripts-per-boot
- scripts-per-instance
- scripts-user
- ssh-authkey-fingerprints
- keys-to-console
- phone-home
- final-message
- power-state-change
# System and/or distro specific settings
# (not accessible to handlers/transforms)
system_info:
# This will affect which distro class gets used
distro: amazon
distro_short: amzn
# Default user name + that default users groups (if added/used)
default_user:
name: ec2-user
lock_passwd: true
gecos: EC2 Default User
groups: [ wheel ]
sudo: [ "ALL=(ALL) NOPASSWD:ALL" ]
shell: /bin/bash
# Other config here will be given to the distro class and/or path classes
paths:
cloud_dir: /var/lib/cloud/
templates_dir: /etc/cloud/templates/
upstart_dir: /etc/init/
package_mirrors:
- arches: [ i386, x86_64 ]
search:
regional:
- repo.%(ec2_region)s.%(services_domain)s
- repo.%(ec2_region)s.amazonaws.com
ssh_svcname: sshd
# vim:syntax=yaml expandtab
上記ではcloud_final_modulesという記載の下にscript-userモジュールが記載されているのが確認できます。また、
# The modules that run in the 'final' stage
というコメントが有り、cloud init のfinalステージのタイミングで実行される事が分かります。
cloud init のfinalステージはいつ実行されるのかというと
$ll /etc/rc3.d/ |grep cloud
lrwxrwxrwx 1 root root 26 Mar 18 15:30 S50cloud-init-local -> ../init.d/cloud-init-local
lrwxrwxrwx 1 root root 20 Mar 18 15:30 S51cloud-init -> ../init.d/cloud-init
lrwxrwxrwx 1 root root 22 Mar 18 15:30 S52cloud-config -> ../init.d/cloud-config
lrwxrwxrwx 1 root root 21 Mar 18 15:30 S98cloud-final -> ../init.d/cloud-final
となっており、S98のタイミングで実行される事がわかります。
上記よりdeamon起動後に実行されることが分かります。
[シェルスクリプト]注意点
- rootユーザーで実行される
- 実行はdeamon起動後(S98cloud-finalで実行される)
- 上記はインスタンスIDごとの初回起動時のみ実行される
cloud-init
- EC2起動時のUserDataに記述が可能
- 先頭に「#cloud-config」と記載し、以降に処理を記載
- シェルスクリプトではなく、独自のYAMLで記載
以下にnginxをインストールして、その後、サービスを起動させる処理を記載します。
#cloud-config
packages:
- nginx
runcmd:
- service nginx start
- chkconfig nginx on
実行時のログは/var/log/cloud-init.log
に出来ています。なお、cloud-initの記述エラーの場合でもインスタンスの起動は実行されますが、処理が実行されず、上記ログにエラーの記載があります。
[cloud-init]再起動時に実行されるもの、されないものを確認する
以下で試されているスクリプトを実行し、初回起動時と2回目の起動のタイミングでどのような差分が出るか確認します。
Amazon Linuxのcloud-initの実行順番を確認する
初回起動時
BootCmd: Mon Jul 6 07:46:55 UTC 2015
Per-Once: Mon Jul 6 07:48:06 UTC 2015
Per-Boot: Mon Jul 6 07:48:09 UTC 2015
Per-Instance: Mon Jul 6 07:48:12 UTC 2015
User-Data: Mon Jul 6 07:48:15 UTC 2015
RunCmd: Mon Jul 6 07:48:18 UTC 2015
再起動後
$cat /var/tmp/test.txt
BootCmd: Mon Jul 6 07:56:19 UTC 2015
Per-Boot: Mon Jul 6 07:57:07 UTC 2015
bootcmdで指定したものと/var/lib/cloud/scripts/per-boot/配下に配置したスクリプト以外は再起動時には実行されないことが分かりました。