初めに
これは 第2のドワンゴ Advent Calendar 2017 24日目の記事です。
この記事では、Terraform + CircleCI 2.0 + Ansible を使ったCD(Continuous Delivery) 環境構築方法について解説します。
CD(Continuous Delivery) とは
CDと略されますが、Continuous Delivery と Continuous Deployment と2つの意味で使われることが多いです。
両者の違いについては、上記の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の設定ファイルは以下のとおりです。
CircleCI での ビルド成果物のアップロード、deployの実行
.circleci/config.yml
に定義しています。
リポジトリ
https://github.com/ymizushi/cd-sample
今回作成した環境について、以上のリポジトリで公開しています。
最後に
今回は Terraform + CircleCI + ANsibleでの CD環境構築について説明させていただきました。
個人の開発においてCD環境構築は後回しになりがちな部分であると思いますが、このあたりを先に構築しておくと、リリースと確認に煩雑な手間をかけなくて良くなるため、アプリケーションの開発に集中しやすくなると感じました。