Posted at

Terraform + CircleCI 2.0 + Ansible で作る CD (Continuous Delivery) 環境

More than 1 year has passed since last update.


初めに

これは 第2のドワンゴ Advent Calendar 2017 24日目の記事です。

この記事では、Terraform + CircleCI 2.0 + Ansible を使ったCD(Continuous Delivery) 環境構築方法について解説します。


CD(Continuous Delivery) とは

CDと略されますが、Continuous Delivery と Continuous Deployment と2つの意味で使われることが多いです。

https://puppet.com/blog/continuous-delivery-vs-continuous-deployment-what-s-diff

両者の違いについては、上記のURLで解説されているため、説明は割愛しますが、以下継続的デリバリーの略語としてCDを使用します。


CD を行うために必要なモノ


  • インフラストラクチャー

  • CI/CDツール

  • デプロイツール

以上のものが必要です。

今回の事例では、インフラストラクチャーは AWS上にTerraformで構築しました。

AWSの場合、他にもCloudFormationなどが選択肢としてありますが、

- HCLが CloudFormationのJson/Yamlに比べて読みやすい

- インフラの状態管理がしやすい

- 後々クラウドプロバイダーを変更した時にツールを変えてなくて良い

ということから今回は Terraform を採用しています。

CircleCI 2.0 では Workflow機能が使え、testの実行、ビルド、デプロイなどをワークフローとして定義できるため、今回はCircleCI 2.0 を使用しています。

デプロイについては、Ansibleを使用しました。

また対象となるアプリケーションは今回のサンプルでは Play 2.6(Scala)を使用しています。


ワークフロー


  • テストの実行

  • アプリケーションのビルド

  • S3へのビルド成果物アップロード

  • ansibleスクリプトの実行


    • ビルド成果物の配置

    • アプリケーションサーバーの再起動




Terraform でのプロビジョニング

provider "aws" {

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

resource "aws_vpc" "backbeard_vpc" {
cidr_block = "10.0.0.0/16"
tags { Name = "backbeard" }
}
resource "aws_key_pair" "backbeard" {
key_name = "${var.key_name}"
public_key = "${var.ssh_public_key}"
}

resource "aws_subnet" "backbeard_subnet" {
vpc_id = "${aws_vpc.backbeard_vpc.id}"
cidr_block = "10.0.0.0/24"
availability_zone = "${var.region}a"
tags {
Name = "backbeard"
}
}

resource "aws_network_interface" "backbeard" {
subnet_id = "${aws_subnet.backbeard_subnet.id}"
private_ips = ["10.0.0.100"]
tags {
Name = "backbeard"
}
}

resource "aws_internet_gateway" "backbeard" {
vpc_id = "${aws_vpc.backbeard_vpc.id}"
}

resource "aws_instance" "backbeard" {
ami = "ami-0a00ce72"
instance_type = "t2.micro"
key_name = "${var.key_name}"

network_interface {
network_interface_id = "${aws_network_interface.backbeard.id}"
device_index = 0
}
tags {
Name = "backbeard"
}
}

resource "aws_eip" "lb" {
instance = "${aws_instance.backbeard.id}"
vpc = true
}

resource "aws_security_group" "backbeard" {
name = "backbeard"
description = "backbeard security group"
vpc_id = "${aws_vpc.backbeard_vpc.id}"

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

ingress {
from_port = 22
to_port = 22
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_route_table" "backbeard" {
vpc_id = "${aws_vpc.backbeard_vpc.id}"

route {
cidr_block = "10.0.0.0/0"
gateway_id = "${aws_internet_gateway.backbeard.id}"
}

tags {
Name = "backbeard"
}
}

以上のテンプレートでインフラを作成しました。

backbeardという名前は、現在個人で作っているサービスのコードネームなので適当に無視してください。


Ansibleでのデプロイ

今回Ansibleを以下の用途で使っています。

- Terraformで作成したEC2インスタンスについて必要なアプリケーションのインストール・設定ファイルの配置

- アプリケーションのデプロイ・再起動

Ansibleの設定ファイルは以下のとおりです。

https://github.com/ymizushi/cd-sample/tree/master/ansible


CircleCI での ビルド成果物のアップロード、deployの実行

https://github.com/ymizushi/cd-sample/blob/master/.circleci/config.yml

.circleci/config.yml に定義しています。


リポジトリ

https://github.com/ymizushi/cd-sample

今回作成した環境について、以上のリポジトリで公開しています。


最後に

今回は Terraform + CircleCI + ANsibleでの CD環境構築について説明させていただきました。

個人の開発においてCD環境構築は後回しになりがちな部分であると思いますが、このあたりを先に構築しておくと、リリースと確認に煩雑な手間をかけなくて良くなるため、アプリケーションの開発に集中しやすくなると感じました。