ブログ

ryuzeeによるブログ記事。不定期更新

Amazon EC2のインスタンス起動時に自動でChef Serverと連携する方法

Amazon EC2に新たなインスタンスを追加した時に、いちいち手作業でインスタンスにSSHで接続してごにょごにょするとか面倒ですよね。こういう時はコマンドでさくっとやってしまうのが簡単です。 いくつかアプローチがありますので、今回はそれを紹介しましょう。

knife bootstrapを使う

たとえばAmazon Linuxのインスタンスを起動して、Chef Clientを導入し、指定したロールの状態にするためには、クライアント(自分の作業端末)から以下のように実行します。

knife bootstrap ec2-XXX-XXX-XXX-XXX.ap-southeast-1.compute.amazonaws.com \
--run-list 'role[web]' \
--environment development \
--no-host-key-verify \
--node-name knife-bootstrap-sample \
--ssh-user ec2-user \
--sudo \
-i ~/.ssh/mykey.pem

これはこれで簡単です。クライアント側の設定をしっかりおこなっておけば、すぐに指定した状態にできるでしょう。 詳しくは http://docs.opscode.com/knife_bootstrap.html を参照してください。 ただ、台数が増えると面倒な気もしますね。

Amazon EC2のUser DataとCloud-initの組み合わせ技

Amazon EC2ではインスタンスの起動時にUser Dataと呼ばれるテキストまたはファイルを引き渡すことができます。 ここで引き渡されたデータはインスタンスの中で解釈されます。そして先頭が#!で始まっているものはスクリプトとみなし(Linuxの場合)て起動直後に実行してくれます(AMIによってCloud-initの導入有無は異なります)。

例えばEC2のインスタンスを起動する際にスクリプトを引き渡すawscliのコマンドラインは以下のようになります。

aws ec2 run-instances \
--image-id ami-4296c310 \
--region ap-southeast-1 \
--count 1 \
--instance-type t1.micro \
--security-groups Web \
--key mykey \
--iam-instance-profile Name=s3-read-only \
--user-data file://init.sh

最初の引数から順に、起動するAMIのID、起動するリージョン、起動するインスタンスの数、起動するインスタンスタイプ、割り当てるセキュリティグループ、インスタンスに接続するのに使うキーペアの名前、このインスタンスに割り当てるIAM Roleの名前、そして、この最後の引数の箇所が、インスタンス起動直後に実行されるスクリプトになります。 Classic-EC2かVPCかによってオプションが変わってきますので、詳細なオプションについては、http://docs.aws.amazon.com/cli/latest/reference/ec2/run-instances.html を参照してください。

なお、awscliではなく、マネジメントコンソールでもUser Dataを渡すことはできますので、コマンドラインが面倒な場合は画面上から実行可能です。

以下がスクリプトの内容になります。 特徴的なのは、Chef用のvalidation.pemをAMIの中に直接埋め込まずに、S3のバケットに配置しておき、それを取得するようにしている点です。S3からファイルを取得するために、起動時にこのインスタンスに対してS3からファイルを取得可能なIAM Roleを割り当てています(IAM Roleは自分で作った名前を指定してください)。

あとは、インスタンスがTerminateされた際に自分の手で、Chef Serverからノードやクライアントの情報を削除するのはあまりにも面倒なので、シャットダウンスクリプトを使って自動で登録を解除するようなスクリプトを用意しています。これをサービスとして登録しておけば楽になります。このスクリプトをランレベル0の時に、stopが呼ばれるようにしておけばOKです。(実行順序についてはケアが必要なので、chkconfig: のあとの数字を確認してください)

#!/bin/sh

# enabling sudo without tty
sed -i 's/^.*requiretty/#Defaults requiretty/' /etc/sudoers

# installing chef-client
curl -L https://www.opscode.com/chef/install.sh | sudo bash

# chef configuration directory
mkdir /etc/chef

(
cat < < 'EOP'
{"run_list": ["role[web]"]}
EOP
) > /etc/chef/first-boot.json

# preparing validation.pem for connecting chef-server
# IAM role is required
aws s3api get-object --bucket chef-server-configuration --key validation.pem /etc/chef/validation.pem 

# createing client.rb for chef-client
NODE_NAME=`curl http://169.254.169.254/latest/meta-data/instance-id`
(
cat < < EOP
log_level :info
log_location STDOUT
node_name "$NODE_NAME"
chef_server_url 'https://chef.meguro.ryuzee.com'
validation_client_name 'chef-validator'
environment "development"
EOP
) > /etc/chef/client.rb

# running chef client
chef-client -j /etc/chef/first-boot.json

# preparing init script for unregistering from chef-server when destroying
(
cat < < 'EOP'
#!/bin/sh
#
# chef_node     delete client and node
#
# chkconfig: 2345 08 20 

VAR_SUBSYS_CHEF_NODE="/var/lock/subsys/chef-node"

# Source function library.
. /etc/rc.d/init.d/functions
case "$1" in
    start)
        [ -f "$VAR_SUBSYS_CHEF_NODE" ] && exit 0
        touch $VAR_SUBSYS_CHEF_NODE
        RETVAL=$?
        ;;
    stop)
        NODE_NAME=`curl http://169.254.169.254/latest/meta-data/instance-id`
        knife node delete $NODE_NAME -y -c /etc/chef/client.rb -u $NODE_NAME
        knife client delete $NODE_NAME -y -c /etc/chef/client.rb -u $NODE_NAME
        \rm $VAR_SUBSYS_CHEF_NODE
        RETVAL=$?
        ;;
esac
exit $RETVAL
EOP
) > /etc/rc.d/init.d/chef-node
chmod 755 /etc/rc.d/init.d/chef-node
/sbin/chkconfig --level 2345 chef-node on
/sbin/chkconfig --level 0 chef-node off
/etc/rc.d/init.d/chef-node start

上記のファイルのダウンロードはこちら

AutoScalingへの応用

この仕掛けを使って、EC2のインスタンスを自動で増やしたり減らしたりするAutoScalingでもインスタンス起動時に自動で指定した状態にセットアップを行うことが可能です。

AutoScalingの設定では、Launch Configuration、AutoScaling Groupそして、Scaling Policyの作成が必要になりますが、指定する箇所はLaunch Configurationになります。 例えばコマンドは以下のようになります。

aws autoscaling create-launch-configuration \
--launch-configuration-name lc-web \
--region ap-southeast-1 \
--image-id ami-4296c310 \
--key-name mykey \
--security-group Web \
--instance-type t1.micro \
--iam-instance-profile s3-read-only \
--user-data file://init.sh

こちらも自分の環境にあわせて変更する必要がありますが、このように–user-dataを使ってスクリプトを引き渡せますので、起動時によきに計らってインスタンスをBootstrappingできます。

Happy Provisioning!

アジャイルコーチングやトレーニングを提供しています

株式会社アトラクタでは、アジャイル開発に取り組むチーム向けのコーチングや、認定スクラムマスター研修などの各種トレーニングを提供しています。ぜひお気軽にご相談ください。

詳細はこちら