AWS Code Deploy で EC2 インスタンスにコードを雑にデプロイしてみた。
IAM ロールの準備
Code Deploy がインスタンスとかを操作するために必要なロール(サービスロール)を作成します。
# ロールを作成 aws iam create-role --role-name CodeDeployServiceRole --assume-role-policy-document '{ "Version": "2012-10-17", "Statement": [ { "Sid": "", "Effect": "Allow", "Principal": { "Service": [ "codedeploy.amazonaws.com" ] }, "Action": "sts:AssumeRole" } ] }' # ロールに Code Deploy のためのポリシーをアタッチ aws iam attach-role-policy --role-name CodeDeployServiceRole \ --policy-arn arn:aws:iam::aws:policy/service-role/AWSCodeDeployRole
EC2 インスタンスに付与するインスタンスプロファイルを作成します。
# ロールを作成 aws iam create-role --role-name CodeDeployDemo-EC2-Instance-Profile --assume-role-policy-document '{ "Version": "2012-10-17", "Statement": [ { "Sid": "", "Effect": "Allow", "Principal": { "Service": "ec2.amazonaws.com" }, "Action": "sts:AssumeRole" } ] }' # ロールにインラインポリシーを設定 aws iam put-role-policy --role-name CodeDeployDemo-EC2-Instance-Profile \ --policy-name CodeDeployDemo-EC2-Permissions --policy-document '{ "Version": "2012-10-17", "Statement": [ { "Action": [ "s3:Get*", "s3:List*" ], "Effect": "Allow", "Resource": "*" } ] }' # インスタンスプロファイルを作成 aws iam create-instance-profile --instance-profile-name CodeDeployDemo-EC2-Instance-Profile # インスタンスプロファイルにロールを追加 aws iam add-role-to-instance-profile --instance-profile-name CodeDeployDemo-EC2-Instance-Profile \ --role-name CodeDeployDemo-EC2-Instance-Profile
Code Deploy の設定とインスタンスの作成
Code Deploy のアプリケーションを作成します。 これは後述のデプロイグループをまとめるだけのものっぽいです。
aws deploy create-application --application-name myapp
次にデプロイグループを作成します。どのインスタンスにどのようにデプロイするかの設定です。
他にもいろいろ指定できて、インプレースではなく Blue/Green にしたり、ロードバランサへのデタッチ/アタッチを自動化したりもできます。今回は何も指定していないので一番シンプルなインプレースでロードバランサ無しです。
--service-role-arn
で指定しているのは↑で作成したサービスロールです。--ec2-tag-filters
で対象となる EC2 インスタンスのタグを指定します。
aws deploy create-deployment-group \ --application-name myapp \ --deployment-group-name mydep \ --service-role-arn arn:aws:iam::999999999999:role/CodeDeployServiceRole \ --ec2-tag-filters Key=Name,Value=mydep,Type=KEY_AND_VALUE
インスタンスを作成します。↑で作成したインスタンスプロファイルを指定したり、↑で指定した通りにタグを付与したりします。ついでにユーザーデータで Code Deploy のエージェントをインストールしたり Apache をインストールしたりします。
aws ec2 run-instances \ --image-id "ami-91c4d3ed" \ --key-name "oreore" \ --instance-type "t2.nano" \ --block-device-mappings "DeviceName=/dev/sda1,Ebs={DeleteOnTermination=true,VolumeType=gp2}" \ --associate-public-ip-address \ --iam-instance-profile "Name=CodeDeployDemo-EC2-Instance-Profile" \ --tag-specifications "ResourceType=instance,Tags=[{Key=Name,Value=mydep}]" \ --user-data '#!/bin/bash set -eu yum -y install ruby yum -y install wget wget https://aws-codedeploy-ap-northeast-1.s3.amazonaws.com/latest/install chmod +x ./install ./install auto yum -y install httpd systemctl start httpd systemctl enable httpd ' aws ec2 describe-instances --filters Name=instance-state-name,Values=pending \ --query "Reservations[].Instances[].PublicIpAddress" \ --output text #=> 192.0.2.123
デプロイ
appspec.yml
ファイルでインスタンス内にコードをどのようにデプロイするか指定します。
この例だと index.html
をドキュメントルートにおいて、デプロイ後に after.sh
を実行します。
version: 0.0 os: linux files: - source: /index.html destination: /var/www/html/ hooks: AfterInstall: - location: /after.sh timeout: 300 runas: root
index.html
や after.sh
も適当に作ってアーカイブにまとめて S3 にアップします。
tar czvf app.tar.gz appspec.yml index.html after.sh aws s3 cp app.tar.gz s3://oreore-deploy/v1.tar.gz
デプロイを開始します。
aws deploy create-deployment --application-name myapp --deployment-group-name mydep \ --s3-location bucket=oreore-deploy,bundleType=tgz,key=v1.tar.gz #=> d-111111111
終わるのを待って、結果を確認します。
aws deploy wait deployment-successful --deployment-id d-111111111 aws deploy get-deployment --deployment-id d-111111111
ブラウザで見ると・・・ index.html
の内容が見えます、デプロイ成功です。
適当にファイルを編集してもう一度デプロイすると・・・
tar czvf app.tar.gz appspec.yml index.html after.sh aws s3 cp app.tar.gz s3://oreore-deploy/v2.tar.gz aws deploy create-deployment --application-name myapp --deployment-group-name mydep \ --s3-location bucket=oreore-deploy,bundleType=tgz,key=v2.tar.gz #=> d-222222222 aws deploy wait deployment-successful --deployment-id d-222222222 aws deploy get-deployment --deployment-id d-222222222
ブラウザで見ると index.html
への編集内容が反映されています。
さいごに
(試していないけど)Blue/Green デプロイがわりと簡単にできるのが良さそう。自前でやろうとするとわりと面倒だろうので。
ただ、インプレースでデプロイする分にはどうかな・・サーバでスクリプト1本走らせればいいだけなので、わざわざ Code Deploy を使うまでも無いような気もする。
例えば AWS Systems Manager の Run Command で次のようにしても似たようなことはできそう。
aws ssm send-command \ --region ap-northeast-1 \ --document-name AWS-RunShellScript \ --targets Key=tag:Name,Values=mydep \ --timeout-seconds 30 \ --max-concurrency 1 \ --max-errors 1 \ --parameters '{ "commands":[ "aws s3 cp s3://oreore-deploy/v2.tar.gz /tmp", "sudo tar xvzf v2.tar.gz -C /var/www/html/", "rm -f v2.tar.gz" ], "workingDirectory":["/tmp"], "executionTimeout":["3600"] }'
ただ、Code Deploy ならどのバージョンがデプロイされているか分かるし、ロールバックもマネジメントコンソールから簡単にできたりと、メリットは多い。