@@ -60,6 +60,26 @@ module "ecs_service" {
6060 # Enables ECS Exec
6161 enable_execute_command = true
6262
63+ # for blue/green deployments
64+ deployment_configuration = {
65+ strategy = " BLUE_GREEN"
66+ bake_time_in_minutes = 2
67+
68+ # example config using lifecycle hooks
69+ # lifecycle_hook = {
70+ # success = {
71+ # hook_target_arn = aws_lambda_function.hook_success.arn
72+ # role_arn = aws_iam_role.global.arn
73+ # lifecycle_stages = ["POST_SCALE_UP", "POST_TEST_TRAFFIC_SHIFT"]
74+ # }
75+ # failure = {
76+ # hook_target_arn = aws_lambda_function.hook_failure.arn
77+ # role_arn = aws_iam_role.global.arn
78+ # lifecycle_stages = ["TEST_TRAFFIC_SHIFT", "POST_PRODUCTION_TRAFFIC_SHIFT"]
79+ # }
80+ # }
81+ }
82+
6383 # Container definition(s)
6484 container_definitions = {
6585
@@ -152,6 +172,14 @@ module "ecs_service" {
152172 target_group_arn = module.alb.target_groups[" ex_ecs" ].arn
153173 container_name = local.container_name
154174 container_port = local.container_port
175+
176+ # for blue/green deployments
177+ advanced_configuration = {
178+ alternate_target_group_arn = module.alb.target_groups[" ex_ecs_alternate" ].arn
179+ production_listener_rule = module.alb.listener_rules[" ex_http/production" ].arn
180+ test_listener_rule = module.alb.listener_rules[" ex_http/test" ].arn
181+ role_arn = aws_iam_role.ecs_elb_permissions.arn
182+ }
155183 }
156184 }
157185
@@ -176,6 +204,12 @@ module "ecs_service" {
176204 }
177205
178206 tags = local. tags
207+
208+ depends_on = [
209+ aws_iam_role . ecs_elb_permissions ,
210+ aws_iam_role_policy_attachment . ecs_service_role ,
211+ aws_iam_role_policy_attachment . ecs_elb_management_role
212+ ]
179213}
180214
181215# ###############################################################################
@@ -278,8 +312,60 @@ module "alb" {
278312 port = 80
279313 protocol = " HTTP"
280314
281- forward = {
282- target_group_key = " ex_ecs"
315+ fixed_response = {
316+ content_type = " text/plain"
317+ message_body = " 404: Page not found"
318+ status_code = " 404"
319+ }
320+
321+ # for blue/green deployments
322+ rules = {
323+ production = {
324+ priority = 1
325+ actions = [
326+ {
327+ type = " weighted-forward"
328+ target_groups = [
329+ {
330+ target_group_key = " ex_ecs"
331+ weight = 100
332+ },
333+ {
334+ target_group_key = " ex_ecs_alternate"
335+ weight = 0
336+ }
337+ ]
338+ }
339+ ]
340+ conditions = [
341+ {
342+ path_pattern = {
343+ values = [" /*" ]
344+ }
345+ }
346+ ]
347+ }
348+ test = {
349+ priority = 2
350+ actions = [
351+ {
352+ type = " weighted-forward"
353+ target_groups = [
354+ {
355+ target_group_key = " ex_ecs_alternate"
356+ weight = 100
357+ }
358+ ]
359+ }
360+ ]
361+ conditions = [
362+ {
363+ path_pattern = {
364+ values = [" /*" ]
365+ }
366+ }
367+ ]
368+ }
283369 }
284370 }
285371 }
@@ -308,6 +394,31 @@ module "alb" {
308394 # ECS will attach the IPs of the tasks to this target group
309395 create_attachment = false
310396 }
397+
398+ # for blue/green deployments
399+ ex_ecs_alternate = {
400+ backend_protocol = " HTTP"
401+ backend_port = local.container_port
402+ target_type = " ip"
403+ deregistration_delay = 5
404+ load_balancing_cross_zone_enabled = true
405+
406+ health_check = {
407+ enabled = true
408+ healthy_threshold = 5
409+ interval = 30
410+ matcher = " 200"
411+ path = " /"
412+ port = " traffic-port"
413+ protocol = " HTTP"
414+ timeout = 5
415+ unhealthy_threshold = 2
416+ }
417+
418+ # There's nothing to attach here in this definition. Instead,
419+ # ECS will attach the IPs of the tasks to this target group
420+ create_attachment = false
421+ }
311422 }
312423
313424 tags = local. tags
@@ -329,3 +440,33 @@ module "vpc" {
329440
330441 tags = local. tags
331442}
443+
444+ resource "aws_iam_role" "ecs_elb_permissions" {
445+ name = " ${ local . name } -ecs-elb-role"
446+ assume_role_policy = jsonencode ({
447+ Version = " 2012-10-17"
448+ Statement = [
449+ {
450+ Action = " sts:AssumeRole"
451+ Effect = " Allow"
452+ Principal = {
453+ Service = [
454+ " ecs-tasks.amazonaws.com" ,
455+ " ecs.amazonaws.com" ,
456+ ]
457+ }
458+ }
459+ ]
460+ })
461+ }
462+
463+ # for example purposes only
464+ resource "aws_iam_role_policy_attachment" "ecs_service_role" {
465+ role = aws_iam_role. ecs_elb_permissions . name
466+ policy_arn = " arn:aws:iam::aws:policy/service-role/AmazonEC2ContainerServiceRole"
467+ }
468+
469+ resource "aws_iam_role_policy_attachment" "ecs_elb_management_role" {
470+ role = aws_iam_role. ecs_elb_permissions . name
471+ policy_arn = " arn:aws:iam::aws:policy/AmazonECSInfrastructureRolePolicyForLoadBalancers"
472+ }
0 commit comments