-
Notifications
You must be signed in to change notification settings - Fork 13
/
Copy pathmain.tf
298 lines (253 loc) · 11.9 KB
/
main.tf
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
data "aws_lb" "public" {
for_each = var.create_ingress_security_group ? { for idx, target in var.target_groups : idx => lookup(target, "load_balancer_arn", "") } : {}
arn = each.value
}
locals {
ingress_targets = flatten(
[
for idx, target in var.target_groups : flatten(
[
[
{
# allow backend_port traffic
from_port = lookup(target, "backend_port", null)
to_port = lookup(target, "backend_port", null)
protocol = "tcp"
source_security_group_id = tolist(data.aws_lb.public[idx].security_groups)[0]
prefix = "backend_port"
}
],
lookup(target, "health_check", null) != null &&
lookup(target["health_check"], "port", "traffic-port") != lookup(target, "backend_port", null) &&
lookup(target["health_check"], "port", "traffic-port") != "traffic-port"
? [
{
# if health_check_port set and different from backend_port, also allow traffic
from_port = target["health_check"]["port"]
to_port = target["health_check"]["port"]
protocol = "tcp"
source_security_group_id = tolist(data.aws_lb.public[idx].security_groups)[0]
prefix = "health_check_port"
}
] : []
]
) if var.create_ingress_security_group
]
)
additional_sidecars = [for s in var.additional_container_definitions : jsonencode(s)]
container_definitions = "[${join(",", concat(compact([local.app_container, local.envoy_container, local.fluentbit_container, local.otel_container])), compact(local.additional_sidecars))}]"
}
data "aws_subnets" "selected" {
filter {
name = "vpc-id"
values = [var.vpc_id]
}
tags = var.subnet_tags != null ? var.subnet_tags : {
Tier = var.assign_public_ip ? "public" : "private"
}
}
module "sg" {
count = var.create_ingress_security_group && length(local.ingress_targets) > 0 ? 1 : 0
source = "registry.terraform.io/terraform-aws-modules/security-group/aws"
version = "~> 3.0"
name = "${var.service_name}-inbound-from-target-groups"
description = "Allow TCP from target groups to port"
ingress_with_source_security_group_id = local.ingress_targets
use_name_prefix = false
vpc_id = var.vpc_id
}
resource "aws_security_group_rule" "trusted_egress_attachment" {
depends_on = [data.aws_lb.public]
for_each = { for route in local.ingress_targets : "${route["prefix"]}-${route["protocol"]}-${route["from_port"]}-${route["to_port"]}" => route }
type = "egress"
from_port = each.value["from_port"]
to_port = each.value["to_port"]
protocol = "tcp"
description = "Attached from ${module.sg[0].this_security_group_name} (${each.value["prefix"]})"
source_security_group_id = module.sg[0].this_security_group_id
security_group_id = each.value["source_security_group_id"]
}
resource "aws_ecs_service" "this" {
cluster = var.cluster_id
deployment_maximum_percent = var.deployment_maximum_percent
deployment_minimum_healthy_percent = var.deployment_minimum_healthy_percent
desired_count = var.desired_count
enable_execute_command = var.enable_execute_command
force_new_deployment = var.force_new_deployment
health_check_grace_period_seconds = var.health_check_grace_period_seconds
launch_type = var.capacity_provider_strategy != null ? null : "FARGATE"
name = var.service_name
platform_version = var.platform_version
propagate_tags = "SERVICE"
tags = var.tags
task_definition = "${aws_ecs_task_definition.this.family}:${max(aws_ecs_task_definition.this.revision, data.aws_ecs_task_definition.this.revision)}"
dynamic "capacity_provider_strategy" {
for_each = var.capacity_provider_strategy != null ? var.capacity_provider_strategy : []
content {
capacity_provider = capacity_provider_strategy.value.capacity_provider
weight = capacity_provider_strategy.value.weight
base = capacity_provider_strategy.value.base
}
}
dynamic "deployment_circuit_breaker" {
for_each = var.deployment_circuit_breaker != null ? [true] : []
content {
enable = var.deployment_circuit_breaker.enable
rollback = var.deployment_circuit_breaker.rollback
}
}
dynamic "alarms" {
for_each = var.deployment_failure_detection_alarms.enable ? [true] : []
content {
enable = var.deployment_failure_detection_alarms.enable
rollback = var.deployment_failure_detection_alarms.rollback
alarm_names = var.deployment_failure_detection_alarms.alarm_names
}
}
dynamic "load_balancer" {
for_each = aws_alb_target_group.main
content {
container_name = local.container_name
container_port = load_balancer.value.port
target_group_arn = load_balancer.value.arn
}
}
network_configuration {
assign_public_ip = var.assign_public_ip
security_groups = concat(concat(var.security_groups, [for sg in module.sg : sg.this_security_group_id]), [])
subnets = data.aws_subnets.selected.ids
}
dynamic "service_registries" {
for_each = var.service_discovery_dns_namespace != "" ? [true] : []
content {
registry_arn = aws_service_discovery_service.this[0].arn
container_name = var.container_name
}
}
lifecycle {
ignore_changes = [desired_count]
}
}
resource "aws_ecs_task_definition" "this" {
depends_on = [
aws_iam_role.task_execution_role,
aws_iam_role.ecs_task_role
]
container_definitions = local.container_definitions
cpu = var.cpu
execution_role_arn = var.task_execution_role_arn == "" ? aws_iam_role.task_execution_role[0].arn : var.task_execution_role_arn
family = var.service_name
memory = var.memory
network_mode = "awsvpc"
requires_compatibilities = var.requires_compatibilities
tags = var.tags
task_role_arn = var.task_role_arn == "" ? aws_iam_role.ecs_task_role[0].arn : var.task_role_arn
runtime_platform {
cpu_architecture = var.cpu_architecture
operating_system_family = var.operating_system_family
}
dynamic "volume" {
for_each = var.efs_volumes
content {
name = volume.value["name"]
efs_volume_configuration {
file_system_id = volume.value["file_system_id"]
root_directory = try(volume.value["root_directory"], null)
transit_encryption = try(volume.value["transit_encryption"], "DISABLED")
dynamic "authorization_config" {
for_each = try(volume.value["authorization_config"], null) != null ? [true] : []
content {
access_point_id = try(volume.value["authorization_config"].access_point_id, null)
iam = try(volume.value["authorization_config"].iam, null)
}
}
}
}
}
dynamic "proxy_configuration" {
for_each = try(var.app_mesh.enabled, false) ? [true] : []
content {
container_name = var.app_mesh.container_name
type = "APPMESH"
properties = {
AppPorts = var.container_port
EgressIgnoredIPs = "169.254.170.2,169.254.169.254"
IgnoredGID = "1337"
ProxyEgressPort = 15001
ProxyIngressPort = 15000
}
}
}
}
# Simply specify the family to find the latest ACTIVE revision in that family.
data "aws_ecs_task_definition" "this" {
depends_on = [aws_ecs_task_definition.this]
task_definition = aws_ecs_task_definition.this.family
}
locals {
container_name = var.container_name == "" ? var.service_name : var.container_name
}
module "ecr" {
source = "./modules/ecr"
count = var.create_ecr_repository ? 1 : 0
custom_lifecycle_policy = var.ecr_custom_lifecycle_policy
enable_default_lifecycle_policy = var.ecr_enable_default_lifecycle_policy
force_delete = var.ecr_force_delete
image_scanning_configuration = var.ecr_image_scanning_configuration
image_tag_mutability = var.ecr_image_tag_mutability
name = var.ecr_repository_name != "" ? var.ecr_repository_name : var.service_name
tags = var.tags
}
module "code_deploy" {
source = "./modules/deployment"
count = var.create_deployment_pipeline && (var.create_ecr_repository || var.ecr_repository_name != "") ? 1 : 0
cluster_name = var.cluster_id
container_name = local.container_name
code_build_environment_compute_type = var.code_build_environment_compute_type
code_build_environment_image = var.code_build_environment_image
code_build_environment_type = var.code_build_environment_type
codestar_notifications_detail_type = var.codestar_notifications_detail_type
codestar_notifications_event_type_ids = var.codestar_notifications_event_type_ids
codestar_notifications_target_arn = var.codestar_notifications_target_arn
codestar_notification_kms_master_key_id = var.codestar_notifications_kms_master_key_id
ecr_repository_name = var.create_ecr_repository ? module.ecr[count.index].name : var.ecr_repository_name
ecr_image_tag = var.ecr_image_tag
service_name = var.service_name
code_build_role = var.code_build_role_name
code_build_log_retention_in_days = var.code_build_log_retention_in_days
code_pipeline_role = var.code_pipeline_role_name
code_pipeline_type = var.code_pipeline_type
code_pipeline_variables = var.code_pipeline_variables
artifact_bucket = var.code_pipeline_artifact_bucket
artifact_bucket_server_side_encryption = var.code_pipeline_artifact_bucket_sse
tags = var.tags
}
##############
# AUTOSCALING
##############
resource "aws_appautoscaling_target" "ecs" {
count = var.appautoscaling_settings != null ? 1 : 0
max_capacity = lookup(var.appautoscaling_settings, "max_capacity", var.desired_count)
min_capacity = lookup(var.appautoscaling_settings, "min_capacity", var.desired_count)
resource_id = "service/${var.cluster_id}/${aws_ecs_service.this.name}"
scalable_dimension = "ecs:service:DesiredCount"
service_namespace = "ecs"
}
resource "aws_appautoscaling_policy" "ecs" {
count = var.appautoscaling_settings != null ? 1 : 0
name = "${var.service_name}-auto-scaling"
policy_type = "TargetTrackingScaling"
resource_id = aws_appautoscaling_target.ecs[count.index].resource_id
scalable_dimension = aws_appautoscaling_target.ecs[count.index].scalable_dimension
service_namespace = aws_appautoscaling_target.ecs[count.index].service_namespace
target_tracking_scaling_policy_configuration {
target_value = lookup(var.appautoscaling_settings, "target_value", null)
disable_scale_in = lookup(var.appautoscaling_settings, "disable_scale_in", false)
scale_in_cooldown = lookup(var.appautoscaling_settings, "scale_in_cooldown", 300)
scale_out_cooldown = lookup(var.appautoscaling_settings, "scale_out_cooldown", 30)
predefined_metric_specification {
predefined_metric_type = lookup(var.appautoscaling_settings, "predefined_metric_type", "ECSServiceAverageCPUUtilization")
resource_label = lookup(var.appautoscaling_settings, "resource_label", null)
}
}
}