Terraformを使ってblue-greenデプロイメントっぽいことをやってみる
About
Terraformを使ってblue-greenぽいことをしている事例があったので、少しアレンジして試してみました。
参考にしたリポジトリ
phinze/tf-bluegreen-asg-deployment: example of a blue/green deployment with asgs
作成したもの
お試し方法
事前準備
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で起動時の設定を指定できるので、使い勝手がいいですね。
図にすると下記のような状態になります。
greenインスタンスを作る
greenインスタンスを作るにはterraform.tfvars
を編集してインスタンスが2台立つようにします。
## common ... ## blue-green blue_instances = "2" green_instances = "2"
この設定でterraform apply
するとblue/greenどちらもインスタンスが作成された状態になります。
blue環境を破壊する
今回のデモではuser_dataを使ってApacheを起動しているので、ELBからのヘルスチェックが通ればgreen環境にリクエストが飛ぶようになります。そうなった段階でblue環境を破壊します。
## common ... ## blue-green blue_instances = "0" green_instances = "2"
この設定でterraform apply
すると下記のような状態になります。
blue環境からgreen環境に切り替えることができました。逆の手順でgreenからblueへの切り替えも可能です。
まとめ
一時的にblue-green環境どちらもが利用できる状態になるので、アプリの動作が変わるような変更での利用は適さないと思います。ただセキュリティのアップデートなどでどうしてもサーバの再起動が必要という場合には、新しく立てたインスタンスに切り替えることができるので使えそうかなと思ってます。