ECS Canary deoloyをterraformで作成
TL;DR
ecsで構築したアプリケーションをCanary deployする構成を作ってterraformで構築します。
目的
ecsで構築するEC2起動タイプのアプリケーションをaws-sampleを参考にCanary deployできるよう設計を試みました。 それをterraformで構築したのでメモを兼ねて紹介します。 もっとよい方法があったら教えてほしいです。
前提
- ecsはEC2起動タイプを使う
- ECSについては用語等最低限知っているものとする
- route53の設定は済んでいるものとする
- vpc, subnet, security group, はすでにあるものを使う(ここで作成しない)
構成
概略
説明
ecsのcluster内に2つのserviceを作成し、Route53の荷重ルーティングを使ってCanary deployを実現します。
各serviceの前段にLoadBalancerをおいてRoute53はそこを指すようにします。
コード
sample
sampleコードはgithubにあります。
service2つとそれぞれのloadbalancerを作ります。
clusterとtaskは同じresourceを使えるので、service_resourceだけ利用します。 デプロイの際はtaskを切り替えるなど適宜に修正が必要です。
# cluster resource "aws_ecs_cluster" "sample_app_canary_deploy" { name = "sample-app_canary-deploy" } # task resource "aws_ecs_task_definition" "task_example" { family = "sample_app" cpu = "256" memory = "512" requires_compatibilities = ["EC2"] container_definitions = "${file("./task_definition.json")}" } # servie_blue resource "aws_ecs_service" "service_blue" { name = "example" cluster = "${aws_ecs_cluster.sample_app_canary_deploy.arn}" task_definition = "${aws_ecs_task_definition.task_example.arn}" desired_count = 1 launch_type = "EC2" // default: EC2 health_check_grace_period_seconds = 1 // defautl:0 task起動に時間がかかると引っかるので0以上にしておく load_balancer { target_group_arn = "${aws_lb_target_group.green_target}" container_name = "example" container_port = 80 } lifecycle { ignore_changes = [] } } # serivice_green # servie_blueと同様
serviceごとにtarget groupを作成し、向き先をaws_ecs_serviceで指定します。 listener groupとtarget groupだけblue, green環境用に2つ必要です。
resource "aws_lb" "alb_sample" { name = "ecs-sample-alb" load_balancer_type = "application" internal = false idle_timeout = 60 enable_deletion_protection = false subnets = [ "subnet-a", "subnet-b", "subnet-c" ] security_groups = [ "sg-1" ] } resource "aws_lb_listener" "http" { load_balancer_arn = "${aws_lb.alb_sample.arn}" port = "80" protocol = "HTTP" default_action { type = "fixed-response" fixed_response { content_type = "text/plain" message_body = "test" status_code = "200" } } } resource "aws_lb_target_group" "blue_target" { name = "ecs-sample_blue-lb-target" vpc_id = "vpc-a" target_type = "instance" port = 80 protocol = "HTTP" depends_on = ["${aws_lb.example}"] } # green用も同様に作る resource "aws_lb_listener_rule" "listener_blue" { listener_arn = "${aws_lb_listener.http.arn}" action { type = "forward" target_group_arn = "${aws_lb_target_group.blue_target.arn}" } condition { field = "path-pattern" values = ["/*"] } } # green用も同様に作る