概要

drone0.4 の terraform plugin で インフラCI する

  • レポジトリは Github のプライベートレポジトリを作成
  • デプロイ先は AWS

drone 0.4 の環境構築に関しては 以前の記事 参照

terraform plugin の詳細は こちら

前提

  • drone の OAuth applications 登録済み
  • terraform の tfstate は S3 で管理する

準備

レポジトリの作成

Github 上で CI 用の新規レポジトリを作成する

レポジトリを Activate する

Drone にアクセスして、作成したレポジトリを選択して Activate する

Deploy Key は自動で登録されるため、Github, Drone の設定についてはこれで完了

S3 Bucket 作成

tfstate 管理用の S3 Bucket を作成する

$ aws s3 mb s3://quickguard-terraform-config

secret variable 作成

Drone 画面の SECRETS より環境変数を入力して secret variable を作成する

環境変数の内容

  • AWS_ACCESS_KEY_ID
  • AWS_SECRET_ACCESS_KEY
  • AWS_DEFAULT_REGION
  • SSH_KEY_NAME : EC2インスタンスに設定する SSH Key Name
  • TFSTATE_BUCKET : tfstate 管理用の S3 Bucket Name
  • TFSTATE_KEY : tfstate Name

作成された secret variable を .drone.sec ファイルとして保存してコミットしておく

$ git add .drone.sec
$ git commit -m "[CI SKIP]added .drone.sec file"

.drone.yml を作成

build:
  image: docker-registry:5000/terraform
  environment:
    - AWS_ACCESS_KEY_ID=$$AWS_ACCESS_KEY_ID
    - AWS_SECRET_ACCESS_KEY=$$AWS_SECRET_ACCESS_KEY
    - AWS_DEFAULT_REGION=$$AWS_DEFAULT_REGION
    - SSH_KEY_NAME=$$SSH_KEY_NAME
    - TFSTATE_BUCKET=$$TFSTATE_BUCKET
    - TFSTATE_KEY=$$TFSTATE_KEY
  commands:
    - cd $DRONE_DIR
    - rm -rf .terraform
    - terraform remote config -backend=s3 -backend-config=region=${AWS_DEFAULT_REGION} -backend-config=bucket=${TFSTATE_BUCKET} -backend-config=key=${TFSTATE_KEY}
    - terraform remote pull
    - terraform plan -var access_key=${AWS_ACCESS_KEY_ID} -var secret_key=${AWS_SECRET_ACCESS_KEY} -var region=${AWS_DEFAULT_REGION} -var key_name=${SSH_KEY_NAME}
  when:
    branch: "!master"

deploy:
  terraform:
    plan: false
    sensitive: true
    remote:
      backend: S3
      config:
        access_key: $$AWS_ACCESS_KEY_ID
        secret_key: $$AWS_SECRET_ACCESS_KEY
        region: $$AWS_DEFAULT_REGION
        bucket: $$TFSTATE_BUCKET
        key: $$TFSTATE_KEY
    vars:
      access_key: $$AWS_ACCESS_KEY_ID
      secret_key: $$AWS_SECRET_ACCESS_KEY
      region: $$AWS_DEFAULT_REGION
      key_name: $$SSH_KEY_NAME
    when:
      branch: master

※image は alpine をベースに terraterm 0.6.11 をインストールしたコンテナを使用
terraform plan は master branch 以外に commit された際に実行
terraform apply は master branch に commit 時のみ実行

テスト時の terraform コンテナの Dockerfile は以下

FROM alpine:3.2

ENV TERRAFORM_VERSION 0.6.11

RUN apk add --update wget bash git perl libxml2-utils openssh ca-certificates unzip && \
    wget -q "https://circle-artifacts.com/gh/andyshinn/alpine-pkg-glibc/6/artifacts/0/home/ubuntu/alpine-pkg-glibc/packages/x86_64/glibc-2.21-r2.apk" && \
    apk add --allow-untrusted glibc-2.21-r2.apk && \
    wget -q -O /terraform.zip "https://releases.hashicorp.com/terraform/${TERRAFORM_VERSION}/terraform_${TERRAFORM_VERSION}_linux_amd64.zip" && \
    unzip /terraform.zip -d /bin && \
    apk del --purge wget ca-certificates unzip && \
    rm -rf /var/cache/apk/* glibc-2.21-r2.apk /terraform.zip

VOLUME ["/data"]

WORKDIR /data

ENTRYPOINT ["/bin/terraform"]

CMD ["--help"]

.drone.sec ファイルと .drone.yml ファイルをレポジトリに commit しておく
(terraform のコードがまだないため、commit メッセージに [CI SKIP] を入力してスキップしておく)

インフラCIしてみる

terraform のコードはとりあえず example を適当に修正して作成

main.tf

provider "aws" {
    access_key = "${var.access_key}"
    secret_key = "${var.secret_key}"
    region = "${var.region}"
}

resource "aws_eip" "default" {
  instance = "${aws_instance.web.id}"
  vpc = true
}

resource "aws_security_group" "default" {
  name = "eip_example"
  description = "Used in the terraform"

  ingress {
    from_port = 22
    to_port = 22
    protocol = "tcp"
    cidr_blocks = ["0.0.0.0/0"]
  }

  ingress {
    from_port = 80
    to_port = 80
    protocol = "tcp"
    cidr_blocks = ["0.0.0.0/0"]
  }

  egress {
    from_port = 0
    to_port = 0
    protocol = "-1"
    cidr_blocks = ["0.0.0.0/0"]
  }
}

resource "aws_instance" "web" {
  instance_type = "t2.micro"
  ami = "${lookup(var.aws_amis, var.region)}"
  key_name = "${var.key_name}"
  security_groups = ["${aws_security_group.default.name}"]

  user_data = "${file("userdata.sh")}"
  tags {
    Name = "eip-example"
  }
}

outputs.tf

output "address" {
  value = "${aws_instance.web.private_ip}"
}
output "elastic ip" {
  value = "${aws_eip.default.public_ip}"
}

variables.tf

variable "access_key" {
  description = "AWS access key"
}

variable "secret_key" {
  description = "AWS secret key"
}

variable "region" {
  description = "The AWS region to create things in."
}

# ubuntu-trusty-14.04 (x64)
variable "aws_amis" {
  default = {
    "ap-northeast-1" = "ami-a21529cc"
  }
}

variable "key_name" {
  description = "Name of the SSH keypair to use in AWS."
}

userdata.sh

#!/bin/bash -v
apt-get update -y
apt-get install -y nginx > /tmp/nginx.log

適当な branch 作成して terraform のコードを push , Pull Request を作成する

テスト(terraform plan)結果

問題なければ Merge する

terraform apply 結果

terraform の output も確認できる