CircleCI
Ansible
Terraform
CircleCI2.0

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