tjinjin's blog

インフラ要素多めの個人メモ

Terraformを使ってblue-greenデプロイメントっぽいことをやってみる

About

Terraformを使ってblue-greenぽいことをしている事例があったので、少しアレンジして試してみました。

参考にしたリポジトリ

phinze/tf-bluegreen-asg-deployment: example of a blue/green deployment with asgs

作成したもの

github.com

お試し方法

事前準備

  • AWSのアクセスキーを発行しておく。
  • ec2の鍵を作っておく。
  • 環境に合わせてterraform.tfvarsの設定を修正する。
  • direnvを導入して環境変数を設定する。
export AWS_ACCESS_KEY_ID="XXX"
export AWS_SECRET_ACCESS_KEY="YYY"
export AWS_DEFAULT_REGION="ap-northeast-1"

実行する

<注意>サンプル用のネットワークなので、お試し以外でのご利用はお控え下さい。

VPCなどの環境を構築する

まず、環境を作っておきたいので、この時点でterraform applyします。するとまっさらな環境ができあがります。まだ、インスタンスは起動しません。

blueインスタンスを作る

インスタンスを作るにはterraform.tfvarsを編集します。

 ## common
...
## blue-green
blue_instances  = "2"
green_instances = "0"

初回はblue環境を構築したいので blue_instances = "2"とします。ここを2とすることでマルチAZなインスタンスが作成されます。

resource "aws_elb" "example" {
  name = "terraform-asg-deployment-example"
  subnets = ["${aws_subnet.example.*.id}"]
  security_groups = ["${aws_security_group.example.id}"]
  cross_zone_load_balancing = true
  listener {
    instance_port = 80
    instance_protocol = "http"
    lb_port = 80
    lb_protocol = "http"
  }
  health_check {
    healthy_threshold = 2
    unhealthy_threshold = 2
    timeout = 2
    target = "HTTP:80/"
    interval = 5
  }
}

resource "aws_launch_configuration" "blue" {
  image_id = "${var.blue_ami}"
  name = "blue-launch_configration"
  instance_type = "${var.blue_instance_type}"
  key_name = "tjinjin-terraform"
  security_groups = ["${aws_security_group.example.id}"]
  user_data = "${file("./boot-blue.sh")}"

  root_block_device {
    delete_on_termination = true
  }

}

resource "aws_autoscaling_group" "blue" {
  name = "blue"
  launch_configuration = "${aws_launch_configuration.blue.id}"
  availability_zones = ["ap-northeast-1a", "ap-northeast-1c"]
  vpc_zone_identifier = ["${aws_subnet.example.*.id}"]
  load_balancers = ["${aws_elb.example.name}"]
  max_size = "${var.blue_instances}"
  min_size = "${var.blue_instances}"
}

resource "aws_launch_configuration" "green" {
  image_id = "${var.green_ami}"
  name = "green-launch_configration"
  instance_type = "${var.green_instance_type}"
  key_name = "tjinjin-terraform"
  security_groups = ["${aws_security_group.example.id}"]
  user_data = "${file("./boot-green.sh")}"

  root_block_device {
    delete_on_termination = true
  }

}

resource "aws_autoscaling_group" "green" {
  name = "green"
  launch_configuration = "${aws_launch_configuration.green.id}"
  availability_zones = ["ap-northeast-1a", "ap-northeast-1c"]
  vpc_zone_identifier = ["${aws_subnet.example.*.id}"]
  load_balancers = ["${aws_elb.example.name}"]
  max_size = "${var.green_instances}"
  min_size = "${var.green_instances}"
}

output "dns_name" {
  value = "${aws_elb.example.dns_name}"
}

ELBの下に2つのblue/greenのautoscaling_groupを所属させておきます。ここがミソです。auto_scaling_groupを利用することで、インスタンス数の管理やlaunch_configurationで起動時の設定を指定できるので、使い勝手がいいですね。

図にすると下記のような状態になります。

f:id:cross_black777:20160126003921p:plain

greenインスタンスを作る

greenインスタンスを作るにはterraform.tfvarsを編集してインスタンスが2台立つようにします。

 ## common
...
## blue-green
blue_instances  = "2"
green_instances = "2"

この設定でterraform applyするとblue/greenどちらもインスタンスが作成された状態になります。

f:id:cross_black777:20160126004147p:plain

blue環境を破壊する

今回のデモではuser_dataを使ってApacheを起動しているので、ELBからのヘルスチェックが通ればgreen環境にリクエストが飛ぶようになります。そうなった段階でblue環境を破壊します。

 ## common
...
## blue-green
blue_instances  = "0"
green_instances = "2"

この設定でterraform applyすると下記のような状態になります。

f:id:cross_black777:20160126004336p:plain

blue環境からgreen環境に切り替えることができました。逆の手順でgreenからblueへの切り替えも可能です。

まとめ

一時的にblue-green環境どちらもが利用できる状態になるので、アプリの動作が変わるような変更での利用は適さないと思います。ただセキュリティのアップデートなどでどうしてもサーバの再起動が必要という場合には、新しく立てたインスタンスに切り替えることができるので使えそうかなと思ってます。