Skip to main content
v6.0 upgrades the minimum Terraform and AWS provider requirements and introduces several breaking API changes: container definition variables are renamed from snake_case to camelCase, security group rule variables are split, permissive default IAM permissions are removed, and task role inline policies become standalone IAM policies.

What changed

  • Minimum Terraform version raised to v1.5.7
  • Minimum AWS provider version raised to v6.0.0
  • Container definition variable names changed from snake_case to camelCase to match the AWS API
  • security_group_rules split into security_group_ingress_rules and security_group_egress_rules
  • Default permissive IAM permissions for SSM Parameter Store and Secrets Manager ARNs removed
  • Task definition version tracking “hack” removed — use track_latest instead
  • Inline task role policy replaced with a standalone aws_iam_policy resource
  • container_definition_defaults variable removed
  • Default user in container-definition changed from "0" to null
  • cluster_settings renamed to cluster_setting; cluster sub-module variables also renamed

Breaking changes

All container definition variables have been renamed from snake_case to camelCase. This affects every container_definitions block in your service module configuration. See the full rename table below.
security_group_rules has been split into security_group_ingress_rules and security_group_egress_rules. The underlying resources have also changed from aws_security_group_rule to aws_vpc_security_group_ingress_rule / aws_vpc_security_group_egress_rule, which means state cannot be moved — existing rules must be removed and re-imported.
Default permissive permissions for SSM parameter ARNs and Secrets Manager secret ARNs have been removed. You must now explicitly define the IAM permissions your tasks require.
The inline aws_iam_role_policy for the tasks role has been replaced with a standalone aws_iam_policy. Inline policies cannot be moved or imported into a standalone policy — the policy will be re-created.

Variable and output changes

Removed variables

  • default_capacity_provider_use_fargate
  • fargate_capacity_providers (root and cluster sub-module)
  • container_definition_defaults
  • service sub-module: inference_accelerator

Renamed variables

Root module / cluster sub-module

BeforeAfter
cluster_settingscluster_setting
cluster_configurationconfiguration (cluster sub-module)
cluster_settingssetting (cluster sub-module)
cluster_service_connect_defaultsservice_connect_defaults (cluster sub-module)

Container definition sub-module

BeforeAfter
dependenciesdependsOn
disable_networkingdisableNetworking
dns_search_domainsdnsSearchDomains
dns_serversdnsServers
docker_labelsdockerLabels
docker_security_optionsdockerSecurityOptions
environment_filesenvironmentFiles
extra_hostsextraHosts
firelens_configurationfirelensConfiguration
health_checkhealthCheck
linux_parameterslinuxParameters
log_configurationlogConfiguration
memory_reservationmemoryReservation
mount_pointsmountPoints
port_mappingsportMappings
psuedo_terminalpseudoTerminal
readonly_root_filesystemreadonlyRootFilesystem
repository_credentialsrepositoryCredentials
start_timeoutstartTimeout
system_controlssystemControls
volumes_fromvolumesFrom
working_directoryworkingDirectory

Added variables

  • cloudwatch_log_group_class
  • default_capacity_provider_strategy — replaces fargate_capacity_providers and default_capacity_provider_use_fargate
  • Container definition: log_group_class, restartPolicy (defaults to enabled = true), versionConsistency
  • Service sub-module: availability_zone_rebalancing, volume_configuration, vpc_lattice_configurations, enable_fault_injection, track_latest, create_infrastructure_iam_role, infrastructure_iam_role_arn, infrastructure_iam_role_name, and related IAM role variables

Removed outputs

  • Service sub-module: task_definition_family_revision

Added outputs

  • Service sub-module: infrastructure_iam_role_arn, infrastructure_iam_role_name

Migration guide

1

Update the module version

Change the version constraint to ~> 6.0.
module "ecs_cluster" {
  source  = "terraform-aws-modules/ecs/aws//modules/cluster"
  version = "~> 6.0"
}

module "ecs_service" {
  source  = "terraform-aws-modules/ecs/aws//modules/service"
  version = "~> 6.0"
}
2

Migrate cluster capacity provider configuration

Replace fargate_capacity_providers with default_capacity_provider_strategy.
module "ecs_cluster" {
  source  = "terraform-aws-modules/ecs/aws//modules/cluster"
  version = "~> 7.0"

  fargate_capacity_providers = {
    FARGATE = {
      default_capacity_provider_strategy = {
        weight = 50
        base   = 20
      }
    }
    FARGATE_SPOT = {
      default_capacity_provider_strategy = {
        weight = 50
      }
    }
  }
}
3

Rename container definition variables to camelCase

Update every key in your container_definitions blocks that previously used snake_case to use camelCase. Use the rename table above as a reference.
container_definitions = {
  fluent-bit = {
    firelens_configuration = {
      type = "fluentbit"
    }
    memory_reservation = 50
  }

  ecsdemo-frontend = {
    port_mappings = [{
      name          = ecsdemo-frontend
      containerPort = 3000
      hostPort      = 3000
      protocol      = "tcp"
    }]

    readonly_root_filesystem = false

    dependencies = [{
      containerName = "fluent-bit"
      condition     = "START"
    }]

    log_configuration = {
      logDriver = "awsfirelens"
      options   = { /* ... */ }
    }

    linux_parameters = {
      capabilities = {
        drop = ["NET_RAW"]
      }
    }

    volumes_from = [{
      sourceContainer = "fluent-bit"
      readOnly        = false
    }]

    memory_reservation = 100
  }
}
4

Split security_group_rules into ingress and egress

Replace the single security_group_rules map with separate security_group_ingress_rules and security_group_egress_rules maps. The attribute names have also changed to align with the new resource types.
security_group_rules = {
  alb_ingress_3000 = {
    type                     = "ingress"
    from_port                = 3000
    description              = "Service port"
    source_security_group_id = module.alb.security_group_id
  }
  egress_all = {
    type        = "egress"
    from_port   = 0
    to_port     = 0
    protocol    = "-1"
    cidr_blocks = ["0.0.0.0/0"]
  }
}
5

Update Terraform state for security group rules

Because the underlying resources changed from aws_security_group_rule to aws_vpc_security_group_ingress_rule / aws_vpc_security_group_egress_rule, state cannot be moved with terraform state mv. You must remove the old state entries and import the new resources.
# Remove old security group rule state
terraform state rm 'module.ecs_service.aws_security_group_rule.this["alb_ingress_3000"]'
terraform state rm 'module.ecs_service.aws_security_group_rule.this["egress_all"]'

# Import into new resource types (replace sg-xxx with your security group ID)
terraform state import \
  'module.ecs_service.aws_vpc_security_group_ingress_rule.this["alb_3000"]' \
  'sg-xxx'

terraform state import \
  'module.ecs_service.aws_vpc_security_group_egress_rule.this["all"]' \
  'sg-xxx'
The inline aws_iam_role_policy for the tasks role cannot be moved or imported into the new standalone aws_iam_policy. It will be re-created automatically — no manual state changes are needed for the policy, but expect it to be destroyed and recreated during terraform apply.
6

Add explicit IAM permissions for SSM and Secrets Manager

Default permissive IAM permissions for SSM Parameter Store and Secrets Manager have been removed. Add explicit IAM policy statements for any parameters or secrets your tasks access.
Review your task definitions for any secrets or environment entries that reference SSM or Secrets Manager ARNs, and ensure the task execution role has the appropriate permissions granted explicitly.
7

Replace task definition version tracking with track_latest

The workaround for tracking task definition versions updated outside the module has been removed. Use the new track_latest variable in the service sub-module to ensure the latest task definition revision is always used.
module "ecs_service" {
  # ...
  track_latest = true
}

Build docs developers (and LLMs) love