概要
- AWS Cli, Ansible, Jenkins を使ってイメージの作成から AutoScaling の Launch Configuration を自動更新する仕組みを構築
環境
- Vagrant 1.8.1
- CentOS 7
- Python 3.5
- pip 8.1.1
- AWS Cli 1.10.21
- jq 1.5
- Jenkins 2.0
- Ansible 1.9
インストール手順については割愛
流れ
- AMI 作成用 EC2 インスタンスの作成
- 起動した EC2 インスタンスを Ansible でリモートプロビジョニング
- プロビジョニングした EC2 インスタンス から AMI を作成
- EC2 インスタンスを Terminate
- 作成した AMI をセットした起動設定(Launch Configuration)を作成
- 作成した起動設定を AutoScaling Group にアタッチ
- 古い起動設定を削除
下準備
Jenkinsジョブ
- Parameterized Trigger plugin を使って、パラメータをテキストファイルに書き込み、下流ジョブに渡す。(参考記事)
AWS Cli
-
aws configure
コマンドであらかじめ ./aws/config と ./aws/credentials ファイルを作成して、/var/lib/jenkins 配下にコピーしておく。
ジョブコード
- 基本やっていることは下記の3つ。
- aws コマンドをいろいろなオプション付きで実行する。
- レスポンスの JSON を jq コマンドでパースし、必要なパラメータを抽出する。
- パラメータを次のジョブに渡す。
- コマンドのパスを通すため .bashrc をジョブ毎で読み込む。(他の方法で可能なら必要ない)
1. AMI 作成用 EC2 インスタンスの作成
- ec2 run-instances を利用する。
- いくつか重複するオプションがあり(
security-groups
,secruity-group-ids
,placement Groups
など)、同時に宣言するとエラーになる。 - ec2 wait instance-status-ok オプションでインスタンスの起動がステータスOKになるまで待機する。
source ~/.bashrc
SECURITY_GROUP=sg-xxxx
KEY_NAME=xxxx
INSTANCE_TYPE=t2.micro
SUBNET_ID=subnet-xxxx
INSTANCES=`aws ec2 run-instances \
--image-id $AMI_ID \
--security-group-ids $SECURITY_GROUP \
--key-name $KEY_NAME \
--instance-type $INSTANCE_TYPE \
--placement AvailabilityZone=ap-northeast-1a \
--block-device-mappings '[{"DeviceName": "/dev/sda1", "Ebs":{"DeleteOnTermination":true}}]' \
--subnet-id $SUBNET_ID \
--no-associate-public-ip-address`
INSTANCE_ID=`echo $INSTANCES | jq -r '.Instances[].InstanceId'`
aws ec2 wait instance-status-ok --instance-ids $INSTANCE_ID
echo "INSTANCE_ID=$INSTANCE_ID" > $WORKSPACE/params.txt
2. 起動した EC2 インスタンスを Ansible でリモートプロビジョニング
- Ansible Play Book の内容は割愛
- Anisble は Jenkins サーバーにインストールし、EC2 インスタンスに対してリモートプロビジョニングを実行
- EC2 インスタンスのプライベートIPを inventory file に 追記し、
ansible-playbook
を実行
source ~/.bashrc
INSTANCES=`aws ec2 describe-instances --instance-ids $INSTANCE_ID`
PRIVATE_IP=`echo $INSTANCES | jq -r .Reservations[].Instances[].PrivateIpAddress`
cd $WORKSPACE/inventory
echo -e [server] > ami_template
echo -e "${PRIVATE_IP} ansible_ssh_user=centos ansible_ssh_private_key_file=/var/lib/jenkins/.ssh/id_rsa.pem" >> ami_template
cd $WORKSPACE
ansible-playbook -i inventory/ami_template main.yml --tags xxx,xxx,xxx
echo "INSTANCE_ID=$INSTANCE_ID" > $WORKSPACE/params.txt
3. プロビジョニングした EC2 インスタンス から AMI を作成
- ec2 create-image と 起動したインスタンスを使って AMI を作成する。
- AMI 作成時にタグを付けられない、ec2 create-tags を使って AMI にタグを付ける。
- ec2 wait image-available オプションで AMI が利用可能になるまで待機する。
source ~/.bashrc
NOW=`date '+%Y%m%d%H%M%S'`
AMI_NAME=service-ec-image_${NOW}
IMAGE=`aws ec2 create-image \
--instance-id $INSTANCE_ID \
--name $AMI_NAME \
--no-reboot`
NEW_AMI_ID=`echo $IMAGE | jq -r .ImageId`
aws ec2 create-tags --resources $NEW_AMI_ID --tags Key=xxxx,Value=xxxx
aws ec2 wait image-available --image-ids $NEW_AMI_ID
echo "INSTANCE_ID=$INSTANCE_ID\n" > $WORKSPACE/params.txt
echo "NEW_AMI_ID=$NEW_AMI_ID" >> $WORKSPACE/params.txt
4. EC2 インスタンスを Terminate
- ec2 terminate-instances を使って不要になった EC2 インスタンスを削除する。
- ec2 wait instance-terminated を使って EC2 インスタンスが削除されるまで待機する。
source ~/.bashrc
aws ec2 terminate-instances --instance-ids $INSTANCE_ID
aws ec2 wait instance-terminated --instance-ids $INSTANCE_ID
5. 作成した AMI をセットした起動設定(Launch Configuration)を作成
- autoscaling create-launch-configuration を使って、上記で作成した AMI を指定して起動設定を作成する。
source ~/.bashrc
NOW=`date '+%Y%m%d%H%M%S'`
LAUNCH_CONFIGURATION_NAME=service_${NOW}
SECURITY_GROUP=sg-xxxxx
INSTANCE_TYPE=t2.micro
aws autoscaling create-launch-configuration \
--launch-configuration-name $LAUNCH_CONFIGURATION_NAME \
--image-id $NEW_AMI_ID \
--security-groups $SECURITY_GROUP \
--instance-type $INSTANCE_TYPE
echo "LAUNCH_CONFIGURATION_NAME=$LAUNCH_CONFIGURATION_NAME" > $WORKSPACE/params.txt
6. 作成した起動設定を Auto Scaling Group にアタッチ
- autoscaling describe-auto-scaling-groups を使って、指定の Auto Scaling Group にセットされている起動設定情報を取得する。
- autoscaling update-auto-scaling-group を使って、上記で作成した起動設定を指定の Auto Scaling Group にアタッチする。
source ~/.bashrc
AUTO_SCALING_GROUP=`aws autoscaling describe-auto-scaling-groups \
--auto-scaling-group-name service_asg`
OLD_LAUNCH_CONFIGURATION_NAME=`echo $AUTO_SCALING_GROUP | jq -r .AutoScalingGroups[].LaunchConfigurationName`
aws autoscaling update-auto-scaling-group \
--auto-scaling-group-name service_asg \
--launch-configuration-name $LAUNCH_CONFIGURATION_NAME
echo "OLD_LAUNCH_CONFIGURATION_NAME=$OLD_LAUNCH_CONFIGURATION_NAME" > $WORKSPACE/params.txt
7. 古い起動設定を削除
- autoscaling delete-launch-configuration を使って、古い起動設定を削除する。
source ~/.bashrc
aws autoscaling delete-launch-configuration \
--launch-configuration-name $OLD_LAUNCH_CONFIGURATION_NAME
まとめ
- Packer の代用になる仕組みを AWS Cli を使って構築できた。
- Packer で Ansible を利用する場合、AMI に Anisble をインストール する必要があり(EC2 の場合)、動作環境に余計なツールをインストールしたくなかったので断念した。
- 発展系として作成した AMI が正しい状態かどうかを確認するフローを検討したい。