よく大宇宙状態(謎)になっている先輩が、terraform+codedeploy+ansibleを試していたので
本当に使えるかどうか実践してみました。
AWS CodeDeployを使ってAnsible or itamae + Serverspec
http://qiita.com/gamisan9999/items/c4e26bf99189bed82748
全体像
先輩の記事だけ見ていると何しているかよくわかんなかったので、わかりやすくしてみました。
ちなみに、TerraformとCodeDeploy+Ansibleは完全に別物です。
連携はまったくありませんのであしからず。
TerraformでAWS環境を構築、EC2とかCodeDeployとかもろもろ作成。
AnsibleレシピをCodedeployでS3にアップ。
CodeDeployからS3のファイルをデプロイ。
後は、対象のローカルで指定のものが動きます。
今回はAnsibleです。
AWS環境構築
CodeDeploy Agent
CodeDeployを使用するには、サーバー側でCodeDeployAgentを起動しておく必要があります。
しかしAgentを入れるのに、わざわざBaseAMIを用意するのは面倒なので
インスタンス起動時のuser_dataに以下のスクリプトを入れれば
codedeployのAgentが入ります。
#!/bin/bash
yum -y update
yum install -y ruby
yum install -y aws-cli
cd /home/ec2-user
aws s3 cp s3://bucket-name/latest/install . --region region-name
chmod +x ./install
./install auto
yum updateとか不要であれば外せます。
AWS-CLIで上げるならこんな感じ。
aws ec2 run-instances \
--image-id amiID \
--key-name keyName \
--user-data file://instance-setup.sh \
--count 1 \
--instance-type instanceType \
--iam-instance-profile Name=CodeDeployDemo-EC2-Instance-Profile
AWS環境構築
例に習ってTerraformで環境構築。
AutoScaleとかしてないで、1インスタンス上げるだけ。
TerraFormの使い方は別途グーグル先生と公式ドキュメントを参考にしていただきたく。
別にTerraform使わなくても大丈夫です。
EC2
気にするところは、user_dataとタグ名。
user_dataはCodeDeployAgent用、
タグはDeploy対象の時のフィルターに使います。
resource "aws_instance" "web-1" {
instance_type = "${var.web_instance_type}"
ami = "${var.ami_id}"
subnet_id = "${aws_subnet.public-1c-subnet.id}"
security_groups = ["${aws_security_group.common.id}"]
associate_public_ip_address = true
key_name = "${var.key_name}"
iam_instance_profile = "${aws_iam_instance_profile.public-profile.name}"
user_data = "${file("./shells/user_data.sh")}" ※ここにuser_data指定
tags = {
Name = "web-1"
Role = "web" ※codedeployに用にタグ指定
}
root_block_device = {
volume_type = "gp2"
volume_size = "100"
}
}
S3
CodeDeployで使用するS3バケットを作る。
バージョニングを有効にする。
resource "aws_s3_bucket" "deploy_bucket" {
bucket = "hogehoge-deploy-bucket"
acl= "private"
region = "ap-northeast-1"
tags {
Name = "hogehoge-deploy-bucket"
}
versioning {
enabled = true
}
}
Codedeploy
IAM
CodeDeploy自体が使用するIAMRoleを作成。
resource "aws_iam_role" "codedeploy_role" {
name = "codedeploy_role"
assume_role_policy = <<EOF
{
"Version": "2012-10-17",
"Statement": [
{
"Sid": "",
"Effect": "Allow",
"Principal": {
"Service": [
"codedeploy.amazonaws.com"
]
},
"Action": "sts:AssumeRole"
}
]
}
EOF
}
resource "aws_iam_role_policy" "codedeploy_policy" {
name = "codedeploy_policy"
role = "${aws_iam_role.codedeploy_role.id}"
policy = <<EOF
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Action": [
"autoscaling:CompleteLifecycleAction",
"autoscaling:DeleteLifecycleHook",
"autoscaling:DescribeAutoScalingGroups",
"autoscaling:DescribeLifecycleHooks",
"autoscaling:PutLifecycleHook",
"autoscaling:RecordLifecycleActionHeartbeat",
"ec2:DescribeInstances",
"ec2:DescribeInstanceStatus",
"tag:GetTags",
"tag:GetResources"
],
"Resource": "*"
}
]
}
EOF
}
CodeDeployの定義を作成
対象インスタンスのフィルターはタグ名で行ってます。
先輩の記事には、タグが2つ指定されてますが、CodeDeployのタグはAND条件ではないので、
2つ付けても対象が増えるだけです。
resource "aws_codedeploy_app" "web-provisioning"
{
name = "web-provisioning"
}
resource "aws_codedeploy_deployment_group" "web-provisioning-group"
{
app_name = "${aws_codedeploy_app.web-provisioning.name}"
deployment_group_name = "web-group"
service_role_arn = "${aws_iam_role.codedeploy_role.arn}"
ec2_tag_filter {
key = "Role"
value = "web"
type = "KEY_AND_VALUE"
}
deployment_config_name = "CodeDeployDefault.AllAtOnce"
}
これでAWS構築は終わり。
Ansible + CodeDeploy
Ansible作成
動作としては、S3に配置しているAnsibleを配布、各サーバ自身でLocalHost宛に実行します。
appspec.ymlの書き方さえわかれば、後はAnsibleの書き方がわかれば大丈夫です。
ディレクトリ階層はこちらを参考にしてます。
appspec.yml
version: 0.0
os: linux
files:
- source: /
destination: /etc/ansible/codedeploy
hooks:
BeforeInstall:
- location: before_install.sh
timeout: 300
runas: root
ApplicationStart:
- location: application_start.sh
timeout: 300
runas: root
ValidateService:
- location: verify_service.sh
timeout: 300
runas: root
CodeDeployにpush
webというフォルダに、先ほどのファイル構成のものを準備してpushする。
aws deploy push \
--application-name web-provisioning \
--s3-location s3://hogehoge-deploy-bucket/web-ansible.zip \
--source ./web/ \
--ignore-hidden-files \
--profile hoehoge \
--region ap-northeast-1
Deploy
後はCLIでpushするもよし、ConsoleからDeployするもよしとなります。
#使ってみて
Terraformは便利です。
CodeDeployはAnsibleを作る手間と、一々pushするのが面倒でした。
また、pushした後のDeployも面倒。
現状だと、ローカルからAnsibleを普通に実行したほうが便利じゃないか?っと思いましたが、
バージョン管理等はCodeDeployが優れているかなと思いました。
Ansibleの資産があっても、修正する手間は多少あるのでその分の価値が見いだせるかというと微妙。
Auto Scaling 等の組み合わせがCodeDeployにはよさそうですので、もう少し触ってから結論を出したいと思います。