Skip to content

Commit

Permalink
FEAT: Add placement constraints (#22)
Browse files Browse the repository at this point in the history
* FEAT: Adds placement constraint as an optional parameter.

* CHORE: terraform fmt repo

* Add lifecycle precondition for service
  • Loading branch information
henningwold authored Sep 26, 2024
1 parent 9298c55 commit 644dbf8
Show file tree
Hide file tree
Showing 7 changed files with 73 additions and 20 deletions.
5 changes: 5 additions & 0 deletions README.adoc
Original file line number Diff line number Diff line change
Expand Up @@ -105,6 +105,11 @@ Both use the same format, but `application_container` will automatically be set
|Configure any other options for container definitions
|no
|None (Though log_configuration is automatically configured for CloudWatch)

|`placement_constraints`
|A list of placement constraints for the service. Not valid for FARGATE launch_type. SEE: https://docs.aws.amazon.com/AmazonECS/latest/developerguide/cluster-query-language.html and https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/ecs_service#placement_constraints
|no
|[]
|===


Expand Down
4 changes: 2 additions & 2 deletions examples/autoscaling-with-custom-metrics/main.tf
Original file line number Diff line number Diff line change
Expand Up @@ -71,7 +71,7 @@ module "service" {
{
listener_arn = data.aws_lb_listener.http.arn
security_group_id = one(data.aws_lb.main.security_groups)
conditions = [
conditions = [
{
path_pattern = "/${local.application_name}/*"
}
Expand All @@ -94,7 +94,7 @@ module "service" {
metric = {
metric_name = "ApproximateNumberOfMessagesVisible"
namespace = "AWS/SQS"
dimensions = [
dimensions = [
{
name = "QueueName"
value = "my-queue"
Expand Down
6 changes: 3 additions & 3 deletions examples/autoscaling/main.tf
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ data "aws_vpc" "main" {
data "aws_subnets" "private" {
# Reference your existing subnets which usually is created centrally in -aws repo
filter {
name = "vpc-id"
name = "vpc-id"
values = [data.aws_vpc.main.id]
}

Expand Down Expand Up @@ -69,7 +69,7 @@ module "service" {
lb_listeners = [{
listener_arn = data.aws_lb_listener.http.arn
security_group_id = one(data.aws_lb.main.security_groups)
conditions = [{
conditions = [{
path_pattern = "/${local.application_name}/*"
}]
}]
Expand All @@ -82,7 +82,7 @@ module "service" {
}

autoscaling_schedule = {
timezone = "Europe/Oslo"
timezone = "Europe/Oslo"
# Increase capacity in weekdays
schedules = [
{
Expand Down
15 changes: 11 additions & 4 deletions examples/on-prem/main.tf
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ provider "aws" {
}

locals {
name_prefix = "infrademo"
name_prefix = "infrademo"
application_name = "my-webapp"
}

Expand All @@ -30,9 +30,16 @@ module "service" {
launch_type = "EXTERNAL"

application_container = {
name = "main"
image = "nginx:latest"
port = 80
name = "main"
image = "nginx:latest"
port = 80
protocol = "HTTP"
}

placement_constraints = [
{
type = "memberOf"
expression = "attribute:your_custom_attribute in [your_first_value, your_second_value]"
}
]
}
12 changes: 6 additions & 6 deletions examples/simple/main.tf
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ provider "aws" {
}

locals {
name_prefix = "infrademo"
name_prefix = "infrademo"
application_name = "my-webapp"
}

Expand All @@ -19,7 +19,7 @@ data "aws_vpc" "main" {

data "aws_subnets" "private" {
filter {
name = "vpc-id"
name = "vpc-id"
values = [data.aws_vpc.main.id]
}

Expand All @@ -38,7 +38,7 @@ data "aws_lb" "main" {

data "aws_lb_listener" "http" {
load_balancer_arn = data.aws_lb.main.arn
port = 80
port = 80
}

/*
Expand All @@ -50,9 +50,9 @@ module "service" {

application_name = local.application_name

vpc_id = data.aws_vpc.main.id
private_subnet_ids = data.aws_subnets.private.ids
cluster_id = data.aws_ecs_cluster.main.id
vpc_id = data.aws_vpc.main.id
private_subnet_ids = data.aws_subnets.private.ids
cluster_id = data.aws_ecs_cluster.main.id

application_container = {
name = "main"
Expand Down
36 changes: 34 additions & 2 deletions main.tf
Original file line number Diff line number Diff line change
Expand Up @@ -487,11 +487,28 @@ resource "aws_ecs_service" "service" {
}
}

# Placement constraints for EC2 and EXTERNAL launch types. Can be used to ensure that services are placed on specific instances.
dynamic "placement_constraints" {
for_each = var.placement_constraints

content {
type = placement_constraints.value.type
expression = placement_constraints.value.expression
}
}

timeouts {
create = var.ecs_service_timeouts.create
update = var.ecs_service_timeouts.update
delete = var.ecs_service_timeouts.delete
}

lifecycle {
precondition {
condition = !(length(var.placement_constraints) > 0 && var.launch_type == "FARGATE")
error_message = "Placement constraints are not valid for FARGATE launch type"
}
}
}

resource "aws_ecs_service" "service_with_autoscaling" {
Expand Down Expand Up @@ -544,9 +561,24 @@ resource "aws_ecs_service" "service_with_autoscaling" {
}
}

# Placement constraints for EC2 and EXTERNAL launch types. Can be used to ensure that services are placed on specific instances.
dynamic "placement_constraints" {
for_each = var.placement_constraints

content {
type = placement_constraints.value.type
expression = placement_constraints.value.expression
}
}


lifecycle {
ignore_changes = [desired_count]

precondition {
condition = !(length(var.placement_constraints) > 0 && var.launch_type == "FARGATE")
error_message = "Placement constraints are not valid for FARGATE launch type"
}
}

timeouts {
Expand Down Expand Up @@ -611,7 +643,7 @@ resource "aws_appautoscaling_policy" "ecs_service" {
content {
label = metrics.value.label
id = metrics.value.id
dynamic metric_stat {
dynamic "metric_stat" {
for_each = metrics.value.metric_stat[*]
content {
metric {
Expand All @@ -628,7 +660,7 @@ resource "aws_appautoscaling_policy" "ecs_service" {
stat = metric_stat.value.stat
}
}
expression = metrics.value.expression
expression = metrics.value.expression
return_data = metrics.value.return_data
}
}
Expand Down
15 changes: 12 additions & 3 deletions variables.tf
Original file line number Diff line number Diff line change
Expand Up @@ -90,6 +90,15 @@ variable "lb_listeners" {
default = []
}

variable "placement_constraints" {
description = "Placement constraints for the service. Note: A maximum of 10 placement constraints may be added to a service. Used to force deployment to specific instances. Not valid for FARGATE launch type."
type = list(object({
type = string
expression = optional(string)
}))
default = []
}

variable "lb_deregistration_delay" {
description = "The amount time for Elastic Load Balancing to wait before changing the state of a deregistering target from draining to unused."
type = number
Expand Down Expand Up @@ -237,9 +246,9 @@ variable "xray_daemon_config_path" {
variable "custom_metrics" {
description = "The custom metrics for autoscaling. Check https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/appautoscaling_policy#create-target-tracking-scaling-policy-using-metric-math for more information."
type = list(object({
label = string
id = string
expression = optional(string)
label = string
id = string
expression = optional(string)
metric_stat = optional(object({
metric = object({
metric_name = string
Expand Down

0 comments on commit 644dbf8

Please sign in to comment.