share facebook facebook2 twitter menu hatena pocket slack

2016.01.25 MON

Terraform + CodeDeploy[Ansible]って使い物になるのか

佐藤 裕行

WRITTEN BY佐藤 裕行

よく大宇宙状態(謎)になっている先輩が、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です。

b2_download_file_by_id

AWS環境構築

CodeDeploy Agent

CodeDeployを使用するには、サーバー側でCodeDeployAgentを起動しておく必要があります。

http://docs.aws.amazon.com/ja_jp/codedeploy/latest/userguide/how-to-run-agent.html

しかしAgentを入れるのに、わざわざBaseAMIを用意するのは面倒なので

インスタンス起動時のuser_dataに以下のスクリプトを入れれば
codedeployのAgentが入ります。

http://docs.aws.amazon.com/ja_jp/codedeploy/latest/userguide/how-to-set-up-new-instance.html

#!/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を作成。

http://docs.aws.amazon.com/ja_jp/codedeploy/latest/userguide/how-to-create-service-role.html

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の書き方がわかれば大丈夫です。

ディレクトリ階層はこちらを参考にしてます。

https://github.com/awslabs/aws-codedeploy-samples/tree/master/conf-mgmt/ansible/local-only

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するもよしとなります。

b657d735-403f-e955-23a9-2175a86a7160

使ってみて

Terraformは便利です。

CodeDeployはAnsibleを作る手間と、一々pushするのが面倒でした。
また、pushした後のDeployも面倒。

現状だと、ローカルからAnsibleを普通に実行したほうが便利じゃないか?っと思いましたが、
バージョン管理等はCodeDeployが優れているかなと思いました。

Ansibleの資産があっても、修正する手間は多少あるのでその分の価値が見いだせるかというと微妙。

Auto Scaling 等の組み合わせがCodeDeployにはよさそうですので、もう少し触ってから結論を出したいと思います。

元記事はこちら

Terraform+CodeDeploy[Ansible]って使い物になるのか

佐藤 裕行

佐藤 裕行

元NIerの通称砂糖です。AWSのネットワークまわりには詳しいです。現在は構築チームに所属し、多忙な日々を過ごしています。