January 31, 2023

AWS Fargate: Detailed Guide

Why do we love and use AWS Fargate at Cloudvisor?

In 2022 most of our customers were using different solutions for containerization to run REST APIs or full-stack web applications. In fact, most of them were running on a plain EC2 using docker-compose to manage and run the containers. However, this solution came with a problem – it took a lot of work to scale the containerized web services and set up integrations between other AWS services.

At Cloudvisor, we choose AWS ECS with Fargate capacity provider (Fargate for future reference) as a go-to solution to run Dockerized applications. Even though this service has some limitations that we will discuss in this article, Fargate is suitable for most Dockerized applications that smaller or bigger startups use or develop. From Crypto to Real Estate, a wide range of customers decide to run their infrastructure on Fargate, as it provides them with high availability in multiple AWS Availability Zones, auto-scaling using the AWS Auto Scaling service, and many AWS integrations with other services. For example, at Cloudvisor, we use Fargate for our internal services.

In this guide
Container Registries | Provisioning an ECS cluster | Service Discovery (AWS Cloud Map) | Service Auto Scaling | Service Load Balancing | Working with secrets (AWS Secrets Manager) | Monitoring | Fargate Limitations | Learn More About Using AWS Fargate

Container Registries

Private Registries

One of my favorite features of Fargate is the ability to use images from all kinds of private registries, like a private docker hub image repository or just using AWS ECR. Taking advantage of AWS Secrets Manager integration, repository credentials can be specified as a secret. In the Task Definition, the secret reference can be used in order for the ECS daemon to use the credentials to log in to the private registry (as below).

"containerDefinitions": [
    {
        "image": "private-repo/private-image",
        "repositoryCredentials": {
            "credentialsParameter": "arn:aws:secretsmanager:region:aws_account_id:secret:secret_name"
        }
    }
]

The Task Execution Role should also be extended with the following IAM Policy (as below).

{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Effect": "Allow",
      "Action": [
        "kms:Decrypt",
        "ssm:GetParameters",
        "secretsmanager:GetSecretValue"
      ],
      "Resource": [
        "arn:aws:secretsmanager:<region>:<aws_account_id>:secret:secret_name",
        "arn:aws:kms:<region>:<aws_account_id>:key/key_id"     
      ]
    }
  ]
}

AWS ECR Integration

Fargate also has an integration with AWS ECR by default. For using ECR images, the Task Execution Role can be extended to the managed AmazonECSTaskExecutionRolePolicy IAM policy. To get permission to pull Docker Images from AWS ECR, no additional AWS Secrets Manager and repository credentials setup is needed.

Provisioning an ECS cluster (for Fargate)

Provisioning an AWS ECS Cluster with Networking only mode is super easy – it can be done within 10 clicks, and a minute from the AWS Console by selecting the Networking only option after hitting the Create Cluster button from the ECS Console of AWS.

Creating an AWS ECS Cluster with Terraform is also done with a couple of lines of code; we should enable, by default, the Container Insights settings (which we will talk about later).

resource "aws_ecs_cluster" "best" { 
  name = "best-cluster" 
  setting { 
    name = "containerInsights" 
    value = "enabled" 
  } 
}

Service Discovery (AWS Cloud Map)

Having services communicating with each other in the ECS cluster should not be a problem. There are multiple ways to achieve it using a messaging or queue system, but if the services need to address each other directly, there should be a static address to use.

Relying on the IP address of the services is not an option because it fluctuates when the orchestrator creates or deletes a container. AWS Cloud Map offers a very easy way to solve this problem, integrating with AWS ECS services smoothly. We can take advantage of this integration by creating an AWS Cloud Map namespace and also creating the service by enabling the service discovery integration.

Using the AWS Console is straightforward; I will show you how to use Terraform resources to achieve the service discovery integration.

resource "aws_service_discovery_private_dns_namespace" "bestnamespace" {
  name = "best.domain.com"  
  description = "best private dns namespace" 
  vpc = aws_vpc.example.id 
}

The next step regarding Terraform is to create a service discovery resource (“aws_service_discovery_service”), in which we specify the private namespace we have already created and the DNS records.

resource "aws_service_discovery_service" "best" {
  name = "best"
  dns_config {
    namespace_id = "${aws_service_discovery_private_dns_namespace.bestnamespace.id}"
    routing_policy = "MULTIVALUE"
    dns_records {
      ttl = 10
      type = "A"
    }

    dns_records {
      ttl  = 10
      type = "SRV"
    }
  }
  health_check_custom_config {
    failure_threshold = 5
  }
}

Finally, we can configure the ECS Service’s service discovery option using the service_registries argument as the following.

resource "aws_ecs_service" "app" {
  name            = "best-service"



  service_registries {
    registry_arn = "${aws_service_discovery_service.best.arn}"
    port = "5001"
  }
}
Get The Latest Articles And News About Aws

Service Auto Scaling

We love the integrated auto-scaling capability of the Fargate services, so we don’t have to worry about writing all kinds of crazy scripts to handle auto-scaling for us. AWS ECS Service utilizing the AWS Application Auto Scaling service to scale using Target Tracking Scaling policy or Step Scaling policy or Scheduled Scaling. The easiest way to get started is to use the Target Tracking Scaling policy. Based on a single metric, the auto-scaling handles scaling up and down the service’s tasks. What does it look like using Terraform? Let’s look at it.

# ECS Service Resource -> Scaling Configuration property
scaling_configuration {
    role_arn               = "<ECSService Role - arn:aws:iam::000000000000:role/ecsAutoscaleRole>"
    minimum_scaling_step_size = 1
    maximum_scaling_step_size = 2
    target_tracking_configuration {
      predefined_metric_specification {
        predefined_metric_type = "ECSServiceAverageCPUUtilization"
      }
      target_value = 70.0
    }
  }

Service Load Balancing

We take care of the entry point of our Fargate-hosted applications using AWS Application Load Balancers (ALB). Great integration, not just with services using Fargate, but also using the EC2 capacity provider. It terminates TLS and can use the managed ACM certificates, so providing security in transit to our Fargate service has never been easier. The only thing we need to adjust here is the health check grace period and health checks themselves. We want to avoid terminating ECS Task when it is still trying to become available. Also, ALB can be placed into public/DMZ subnets, and we can hide the Fargate tasks into private subnets providing a more secure and isolated environment.

# ECS Service Resource -> Load Balancer propery
load_balancer {
  target_group_arn = aws_alb_target_group.example.arn
  container_name   = "example"
  container_port   = 80
}

Working with secrets (AWS Secrets Manager)

What we like about the AWS Secrets Manager and ECS integration is that we don’t need to hardcode any secrets in plaintext form. For external third-party services, connections, and databases, we can specify the secret or key as a secret value in the Secrets Manager Service and use this secret reference in the container definition. When the container is initializing, the daemon utilizes the IAM Task Execution Role to fetch the secret value and add the secret value into the container as an environment variable.

# ECS Task Definition Secret property

...
{
  "containerDefinitions": [{
    "secrets": [{
      "name": "environment_variable_name",
      "valueFrom": "arn:aws:secretsmanager:<region>:<account_id>:secret:<secret-id>:<secret-key>::"
    }]
  }]
}
...

Monitoring

This might be controversial, but we don’t need third-party services to monitor our Fargate services. We are perfectly fine with AWS CloudWatch Container Insights and AWS CloudWatch Logs which we query using AWS CloudWatch Logs insights.

Container Insights provides advanced metrics related to the ECS Service and ECS Tasks and Containers running inside the tasks. Container Insights also provides us with a visualization of the Services/Tasks, and we can easily navigate and select the service we are interested in. Enabling AWS Container Insights is done through the ECS Cluster as an option when creating or updating the ECS Cluster. (We have already provided the Terraform equivalent above the section Provisioning an ECS cluster (for Fargate)).

Logs Insight uses the CloudWatch query syntax, which is different from using SQL but fun and, after a while, seems more intuitive. Also, Container Insights metrics can be queried using AWS CloudWatch Logs insights. We can set up the CloudWatch Logs delivery from the containers by extending the task definition with the logConfiguration property, like the following lines below.

{
    "containerDefinitions": [
        {
            "name": "best-app",
            …….
            "logConfiguration": {
                "logDriver": "awslogs",
                "options": {
                    "awslogs-create-group": "true",
                    "awslogs-group": "ecs",
                    "awslogs-region": "eu-central-1",
                    "awslogs-stream-prefix": "best"
                }
            },
            ….
        },

Also, don’t forget to extend the ECS Task Execution IAM Role with the required permissions (suggested AmazonECSTaskExecutionRolePolicy IAM policy can be used).

Fargate Limitations

  • As of January 2013, the compute limitation of Fargate is 16 vCPU and max 120GB of RAM
    • For most Web Services use cases, it should be more than enough
  • Containers per task definition are max 10
    • Again, for most Web Services, it should be more than enough
  • Task per Service is 5000
    • For most of the use cases really hard to reach this limit
    • It is a soft limit and can be increased through quota request

Learn More About Using AWS Fargate With Cloudvisor 

In this article, we have gone through how ECS natively integrates with other AWS Services. We discussed the advantages of using AWS Fargate and some of its limitations that you need to be aware of. As you have learned, based on AWS Fargate infrastructure, robust services can be built.

Aws Fargate: Detailed Guide 2

Written by Sándor Bakos

AWS Cloud Engineer/Architect at Cloudvisor

Subscribe to Our Proactive Support Service!
Our engineers will recommend the latest AWS best practices to implement and administer monthly reviews to ensure your infrastructure complies with these best practices.

Other Articles

Get the latest articles and news about AWS