Search code examples
djangoelasticsearchamazon-ecs

Django unable to connect to elasticsearch cluster within the same task in ECS


I deployed an application into a ECS task using the following container definitions

[
 {
   "name": "api",
   "image": "${app_image}",
   "essential": true,
   "memoryReservation": 256,
   "environment": [
     {"name": "DJANGO_SECRET_KEY", "value": "${django_secret_key}"},
     {"name": "DB_HOST", "value": "${db_host}"},
     {"name": "DB_NAME", "value": "${db_name}"},
     {"name": "DB_USER", "value": "${db_user}"},
     {"name": "DB_PASS", "value": "${db_pass}"},
     {"name": "DEBUG", "value": "false"},
     {"name": "STORAGE_HOST", "value": "${bucket_host}"},
     {"name": "ALLOWED_HOSTS", "value": "${allowed_hosts}"},
     {"name": "DJANGO_SETTINGS_MODULE_STAGING", "value": "${django_settings_module}"},
     {"name": "S3_STORAGE_BUCKET_NAME", "value": "${s3_storage_bucket_name}"},
     {"name": "S3_STORAGE_BUCKET_REGION", "value": "${s3_storage_bucket_region}"}
   ],
   "logConfiguration": {
     "logDriver": "awslogs",
     "options": {
       "awslogs-group": "${log_group_name}",
       "awslogs-region": "${log_group_region}",
       "awslogs-stream-prefix": "api"
     }
   },
   "portMappings": [
     {
       "containerPort": 9000,
       "hostPort": 9000
     }
   ],
   "mountPoints": [
     {
       "readOnly": false,
       "containerPath": "/vol/web",
       "sourceVolume": "static"
     }
   ]
 },
 {
   "name": "proxy",
   "image": "${proxy_image}",
   "essential": true,
   "portMappings": [
     {
       "containerPort": 8000,
       "hostPort": 8000
     }
   ],
   "memoryReservation": 256,
   "environment": [
     {"name": "APP_HOST", "value": "127.0.0.1"},
     {"name": "APP_PORT", "value": "9000"},
     {"name": "LISTEN_PORT", "value": "8000"}
   ],
   "logConfiguration": {
     "logDriver": "awslogs",
     "options": {
       "awslogs-group": "${log_group_name}",
       "awslogs-region": "${log_group_region}",
       "awslogs-stream-prefix": "proxy"
     }
   },
   "mountPoints": [
     {
       "readOnly": true,
       "containerPath": "/vol/static",
       "sourceVolume": "static"
     }
   ]
 },
 {
   "name": "elasticsearch",
   "image": "${elasticsearch_image}",
   "essential": true,
   "memoryReservation": 256,
   "portMappings": [
     {
       "containerPort": 9200,
       "hostPort": 9200
     }
   ],
   "logConfiguration": {
     "logDriver": "awslogs",
     "options": {
       "awslogs-group": "${log_group_name}",
       "awslogs-region": "${log_group_region}",
       "awslogs-stream-prefix": "elasticsearch"
     }
   }
 }
]

in django settings, I configure the connection to the elasticsearch using:

ELASTICSEARCH_DSL = {
   "default": {"hosts": "elasticsearch:9200"},
}

I also configure the egress and ingress rules for the service security group using terraform:

resource "aws_security_group" "ecs_service_api" {
  description = "Access for the ECS service"
  name        = "${local.prefix}-ecs-service-api"
  vpc_id      = data.terraform_remote_state.core.outputs.vpc_id

  egress {
    from_port   = 443
    to_port     = 443
    protocol    = "tcp"
    cidr_blocks = ["0.0.0.0/0"]
  }

  egress {
    from_port = 5432
    to_port   = 5432
    protocol  = "tcp"
    cidr_blocks = [
      data.terraform_remote_state.core.outputs.subnet_public_a_cidr_block,
      data.terraform_remote_state.core.outputs.subnet_public_b_cidr_block,
    ]
  }

  ingress {
    from_port       = 8000
    to_port         = 8000
    protocol        = "tcp"
    security_groups = [aws_security_group.lb_api.id]

  }

  ingress {
    from_port       = 9200
    to_port         = 9200
    protocol        = "tcp"
    security_groups = [aws_security_group.lb_api.id]
  }

  tags = local.common_tags
}

The application was deployed correctly and the elasticsearch container is running normally. But the connection from django to elasticsearch is not working. Do someone know what might be happening? Any help will be appreciated.


Solution

  • ECS does not provide DNS name resolution for the containers in a task. You may be expecting it to work that way because you are used to how Docker Compose works.

    With ECS tasks running on Fargate, each container is accessible by the other containers in the same task at 127.0.0.1 on their respective port(s). So in your case you need to change the Elasticsearch connection settings in Django to the following:

    ELASTICSEARCH_DSL = {
       "default": {"hosts": "127.0.0.1:9200"},
    }