11# #######################
2- # # ALB TG
2+ # # ALB Blue/Green Deployment Configuration
33# #######################
4+ #
5+ # This configuration follows AWS documentation for blue/green deployments:
6+ # https://docs.aws.amazon.com/AmazonECS/latest/developerguide/alb-resources-for-blue-green.html
7+ #
8+ # Key components:
9+ # - Two target groups: blue (primary) and green (alternate)
10+ # - Production listener on port 80
11+ # - Test listener on port 8080 for validation
12+ # - Listener rules for traffic routing
413
5- # Listener
6- # https://www.terraform.io/docs/providers/aws/r/lb_listener.html
7- resource "aws_lb_listener" "main" {
8- port = " 80"
9- protocol = " HTTP"
14+ # Primary (Blue) Target Group
15+ resource "aws_lb_target_group" "blue" {
16+ name = " ${ local . name } -blue-tg"
17+ vpc_id = aws_vpc. main . id
18+ port = 80
19+ protocol = " HTTP"
20+ target_type = " ip"
1021
22+ health_check {
23+ enabled = true
24+ healthy_threshold = 2
25+ interval = 30
26+ matcher = " 200"
27+ path = " /"
28+ port = " traffic-port"
29+ protocol = " HTTP"
30+ timeout = 5
31+ unhealthy_threshold = 2
32+ }
33+
34+ tags = {
35+ Name = " ${ local . name } -blue-target-group"
36+ }
37+ }
38+
39+ # Alternate (Green) Target Group
40+ resource "aws_lb_target_group" "green" {
41+ name = " ${ local . name } -green-tg"
42+ vpc_id = aws_vpc. main . id
43+ port = 80
44+ protocol = " HTTP"
45+ target_type = " ip"
46+
47+ health_check {
48+ enabled = true
49+ healthy_threshold = 2
50+ interval = 30
51+ matcher = " 200"
52+ path = " /"
53+ port = " traffic-port"
54+ protocol = " HTTP"
55+ timeout = 5
56+ unhealthy_threshold = 2
57+ }
58+
59+ tags = {
60+ Name = " ${ local . name } -green-target-group"
61+ }
62+ }
63+
64+ # Production Listener (Port 80)
65+ # Initially forwards traffic to blue target group
66+ resource "aws_lb_listener" "production" {
67+ port = " 80"
68+ protocol = " HTTP"
69+ load_balancer_arn = aws_lb. main . arn
70+
71+ default_action {
72+ type = " forward"
73+ target_group_arn = aws_lb_target_group. blue . arn
74+ }
75+ }
76+
77+ # Test Listener (Port 8080)
78+ # Forwards traffic to green target group for validation
79+ resource "aws_lb_listener" "test" {
80+ port = " 8080"
81+ protocol = " HTTP"
1182 load_balancer_arn = aws_lb. main . arn
1283
1384 default_action {
14- type = " fixed-response"
85+ type = " forward"
86+ target_group_arn = aws_lb_target_group. green . arn
87+ }
88+ }
89+
90+ # Production Listener Rule for blue/green routing
91+ resource "aws_lb_listener_rule" "production" {
92+ listener_arn = aws_lb_listener. production . arn
93+ priority = 100
94+
95+ action {
96+ type = " forward"
97+ target_group_arn = aws_lb_target_group. blue . arn
98+ }
99+
100+ condition {
101+ path_pattern {
102+ values = [" *" ]
103+ }
104+ }
105+ }
15106
16- fixed_response {
17- content_type = " text/plain"
18- status_code = " 200"
19- message_body = " ok"
107+ # Test Listener Rule for path-based testing
108+ resource "aws_lb_listener_rule" "test_path" {
109+ listener_arn = aws_lb_listener. production . arn
110+ priority = 200
111+
112+ action {
113+ type = " forward"
114+ target_group_arn = aws_lb_target_group. green . arn
115+ }
116+
117+ condition {
118+ path_pattern {
119+ values = [" /test/*" ]
120+ }
121+ }
122+ }
123+
124+ # Test Listener Rule for header-based testing
125+ resource "aws_lb_listener_rule" "test_header" {
126+ listener_arn = aws_lb_listener. production . arn
127+ priority = 300
128+
129+ action {
130+ type = " forward"
131+ target_group_arn = aws_lb_target_group. green . arn
132+ }
133+
134+ condition {
135+ http_header {
136+ http_header_name = " X-Environment"
137+ values = [" test" ]
20138 }
21139 }
22140}
@@ -31,8 +149,7 @@ resource "aws_lb" "main" {
31149 subnets = aws_subnet. public [* ]. id
32150}
33151
34- # SecurityGroup Rule
35- # https://www.terraform.io/docs/providers/aws/r/security_group.html
152+ # SecurityGroup Rule for HTTP (Port 80)
36153resource "aws_security_group_rule" "alb_http" {
37154 security_group_id = aws_security_group. alb . id
38155 type = " ingress"
@@ -42,6 +159,16 @@ resource "aws_security_group_rule" "alb_http" {
42159 cidr_blocks = [" 0.0.0.0/0" ]
43160}
44161
162+ # SecurityGroup Rule for Test Port (Port 8080)
163+ resource "aws_security_group_rule" "alb_test" {
164+ security_group_id = aws_security_group. alb . id
165+ type = " ingress"
166+ from_port = 8080
167+ to_port = 8080
168+ protocol = " tcp"
169+ cidr_blocks = [" 0.0.0.0/0" ]
170+ }
171+
45172resource "aws_security_group" "alb" {
46173 name = " ${ local . name } -alb-sg"
47174 vpc_id = aws_vpc. main . id
@@ -53,3 +180,57 @@ resource "aws_security_group" "alb" {
53180 cidr_blocks = [" 0.0.0.0/0" ]
54181 }
55182}
183+
184+ # Amazon ECS infrastructure IAM role for load balancers
185+ # This role allows Amazon ECS to manage load balancer resources for blue/green deployments
186+ resource "aws_iam_role" "ecs_infrastructure_role" {
187+ name = " ${ local . name } -ecs-infrastructure-role"
188+
189+ assume_role_policy = jsonencode ({
190+ Version = " 2012-10-17"
191+ Statement = [
192+ {
193+ Sid = " AllowAccessToECSForInfrastructureManagement"
194+ Effect = " Allow"
195+ Principal = {
196+ Service = " ecs.amazonaws.com"
197+ }
198+ Action = " sts:AssumeRole"
199+ }
200+ ]
201+ })
202+
203+ tags = {
204+ Name = " ${ local . name } -ecs-infrastructure-role"
205+ Description = " ECS infrastructure role for load balancer management"
206+ }
207+ }
208+
209+ # Attach the AWS managed policy for ECS infrastructure role
210+ resource "aws_iam_role_policy_attachment" "ecs_infrastructure_policy" {
211+ role = aws_iam_role. ecs_infrastructure_role . name
212+ policy_arn = " arn:aws:iam::aws:policy/AmazonECSInfrastructureRolePolicyForLoadBalancers"
213+ }
214+
215+ # IAM policy to allow passing the infrastructure role to ECS
216+ # This should be attached to the user/role that creates ECS services
217+ resource "aws_iam_policy" "pass_ecs_infrastructure_role" {
218+ name = " ${ local . name } -pass-ecs-infrastructure-role"
219+ description = " Allow passing ECS infrastructure role to ECS service"
220+
221+ policy = jsonencode ({
222+ Version = " 2012-10-17"
223+ Statement = [
224+ {
225+ Action = " iam:PassRole"
226+ Effect = " Allow"
227+ Resource = aws_iam_role.ecs_infrastructure_role.arn
228+ Condition = {
229+ StringEquals = {
230+ " iam:PassedToService" = " ecs.amazonaws.com"
231+ }
232+ }
233+ }
234+ ]
235+ })
236+ }
0 commit comments