How do I pull the public IP address assigned to a container of an AWS ECS cluster/service?
For testing purposes I do not want to spin up an ALB, so I just added service to a public subnet. The best I was able to come up with so far is to use aws cli to pull the IP address. I am wondering if there's a way to pull this somehow using Terraform attributes.
resource "aws_ecs_cluster" "this" {
name = "${lower(var.app_name)}-${lower(var.app_environment)}-cluster"
}
resource "aws_ecs_task_definition" "this" {
family = "${lower(var.app_name)}-${lower(var.app_environment)}-task"
execution_role_arn = aws_iam_role.ecs_task_execution_role.arn
container_definitions = jsonencode([{
name = "${lower(var.app_name)}-${lower(var.app_environment)}-container"
image = "nginx:latest"
portMappings = [{ containerPort = 80 }]
}])
memory = 3072
cpu = 1024
requires_compatibilities = ["FARGATE"]
network_mode = "awsvpc"
runtime_platform {
operating_system_family = "LINUX"
cpu_architecture = "X86_64"
}
}
resource "aws_ecs_service" "this" {
name = "${lower(var.app_name)}-${lower(var.app_environment)}-service"
cluster = aws_ecs_cluster.this.id
task_definition = aws_ecs_task_definition.this.arn
desired_count = 1
# Assign an Elastic IP address to the task
network_configuration {
assign_public_ip = true
subnets = [module.vpc100.public_subnet1_id,module.vpc100.public_subnet2_id]
security_groups = [aws_security_group.this.id]
}
# Configure the service to use Fargate
launch_type = "FARGATE"
tags = {
Name = "${lower(var.app_name)}-${lower(var.app_environment)}-container"
}
}
# My hack to pull the public IP address
resource "terraform_data" "publicip" {
provisioner "local-exec" {
command = <<EOF
clustername=${lower(var.app_name)}-${lower(var.app_environment)}-cluster
taskid=$(aws ecs list-tasks --cluster $clustername --query "taskArns[0]" --output text)
eni=$(aws ecs describe-tasks --tasks $taskid --cluster example6-dev-cluster --query "tasks[0].attachments[0].details[?name=='networkInterfaceId'].value" --output text)
publicip=$(aws ec2 describe-network-interfaces --query "NetworkInterfaces[?NetworkInterfaceId=='$eni'].Association.PublicIp" --output text)
echo "$publicip"
EOF
}
depends_on = [
aws_ecs_service.this
]
}
You can retrieve the public IP address assigned to a container in an AWS ECS cluster/service by following these steps:
enable_ecs_managed_tags
to true
in your aws_ecs_service. This configures ECS to tag the network interface with essential information:aws:ecs:serviceName = <aws_ecs_service.yourservice.name>
aws:ecs:clusterName = <aws_ecs_service.yourservice.cluster>
resource "aws_ecs_service" "this" {
# Your other configuration goes here
task_definition = aws_ecs_task_definition.this.arn
desired_count = 1
enable_ecs_managed_tags = true # It will tag the network interface with service name
wait_for_steady_state = true # Terraform will wait for the service to reach a steady state
# Assign an Elastic IP address to the task
network_configuration {
# Rest of the configuration goes here
}
data "aws_network_interface" "interface_tags" {
filter {
name = "tag:aws:ecs:serviceName"
values = ["${lower(var.app_name)}-${lower(var.app_environment)}-service"]
}
}
output "public_ip" {
value = data.aws_network_interface.interface_tags.association[0].public_ip
}
For further context, you can refer to the GitHub issue How can I access IP from aws_ecs_service using assign_public_ip
You can't do that with Terraform. Terraform just knows that it told AWS to create a service. It doesn't know anything about any current tasks that are being managed by the service. You'll need to run something like an AWS CLI command after your terraform apply
is complete.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With