AWS Fargate is a new compute engine that works with Amazon Elastic Container Service (ECS) to run containers without having to manage servers or clusters. What does this mean? With Fargate, you no longer need to provision or manage a single virtual machine; you can just create tasks and run them directly!
Fargate uses the same API actions as ECS, so you can use the ECS console, the AWS CLI, or the ECS CLI. I recommend running through the first-run experience for Fargate even if you’re familiar with ECS. It creates all of the one-time setup requirements, such as the necessary IAM roles. If you’re using a CLI, make sure to upgrade to the latest version.
In this blog, you will see how to migrate ECS containers from running on Amazon EC2 to Fargate.
Getting started
Note: Anything with code blocks is a change in the task definition file. Screen captures are from the console. Additionally, Fargate is currently available in the us-east-1 (N. Virginia) region.
Launch type
When you create tasks (grouping of containers) and clusters (grouping of tasks), you now have two launch type options: EC2 and Fargate. The default launch type, EC2, is ECS as you knew it before the announcement of Fargate. You need to specify Fargate as the launch type when running a Fargate task.
Even though Fargate abstracts away virtual machines, tasks still must be launched into a cluster. With Fargate, clusters are a logical infrastructure and permissions boundary that allow you to isolate and manage groups of tasks. ECS also supports heterogeneous clusters that are made up of tasks running on both EC2 and Fargate launch types.
The optional, new requiresCompatibilities
parameter with FARGATE
in the field ensures that your task definition only passes validation if you include Fargate-compatible parameters. Tasks can be flagged as compatible with EC2, Fargate, or both.
1 2 3 |
"requiresCompatibilities": [ "FARGATE" ] |
Networking
1 |
"networkMode": "awsvpc" |
In November, we announced the addition of task networking with the network mode awsvpc. By default, ECS uses the bridge
network mode. Fargate requires using the awsvpc
network mode.
In bridge
mode, all of your tasks running on the same instance share the instance’s elastic network interface, which is a virtual network interface, IP address, and security groups.
The awsvpc
mode provides this networking support to your tasks natively. You now get the same VPC networking and security controls at the task level that were previously only available with EC2 instances. Each task gets its own elastic networking interface and IP address so that multiple applications or copies of a single application can run on the same port number without any conflicts.
The awsvpc
mode also provides a separation of responsibility for tasks. You can get complete control of task placement within your own VPCs, subnets, and the security policies associated with them, even though the underlying infrastructure is managed by Fargate. Also, you can assign different security groups to each task, which gives you more fine-grained security. You can give an application only the permissions it needs.
1 2 3 4 5 |
"portMappings": [ { "containerPort": "3000" } ] |
What else has to change? First, you only specify a containerPort
value, not a hostPort
value, as there is no host to manage. Your container port is the port that you access on your elastic network interface IP address. Therefore, your container ports in a single task definition file need to be unique.
1 2 3 4 5 6 |
"environment": [ { "name": "WORDPRESS_DB_HOST", "value": "127.0.0.1:3306" } ] |
Additionally, links
are not allowed as they are a property of the “bridge” network mode (and are now a legacy feature of Docker). Instead, containers share a network namespace and communicate with each other over the localhost interface. They can be referenced using the following:
1 |
localhost/127.0.0.1:<em><some_port_number></em> |
CPU and memory
1 2 3 4 5 |
"memory": "1024", "cpu": "256" "memory": "1gb", "cpu": ".25vcpu" |
When launching a task with the EC2 launch type, task performance is influenced by the instance types that you select for your cluster combined with your task definition. If you pick larger instances, your applications make use of the extra resources if there is no contention.
In Fargate, you needed a way to get additional resource information so we created task-level resources. Task-level resources define the maximum amount of memory
and cpu
that your task can consume.
memory
can be defined in MB with just the number, or in GB, for example, “1024” or “1gb”.cpu
can be defined as the number or in vCPUs, for example, “256” or “.25vcpu”.- vCPUs are virtual CPUs. You can look at the memory and vCPUs for instance types to get an idea of what you may have used before.
The memory and CPU options available with Fargate are:
CPU | Memory |
256 (.25 vCPU) | 0.5GB, 1GB, 2GB |
512 (.5 vCPU) | 1GB, 2GB, 3GB, 4GB |
1024 (1 vCPU) | 2GB, 3GB, 4GB, 5GB, 6GB, 7GB, 8GB |
2048 (2 vCPU) | Between 4GB and 16GB in 1GB increments |
4096 (4 vCPU) | Between 8GB and 30GB in 1GB increments |
IAM roles
Because Fargate uses awsvpc
mode, you need an Amazon ECS service-linked IAM role named AWSServiceRoleForECS
. It provides Fargate with the needed permissions, such as the permission to attach an elastic network interface to your task. After you create your service-linked IAM role, you can delete the remaining roles in your services.
1 |
"executionRoleArn": "arn:aws:iam::<<em>your_</em><em>account_id></em>:role/ecsTaskExecutionRole" |
With the EC2 launch type, an instance role gives the agent the ability to pull, publish, talk to ECS, and so on. With Fargate, the task execution IAM role is only needed if you’re pulling from Amazon ECR or publishing data to Amazon CloudWatch Logs.
The Fargate first-run experience tutorial in the console automatically creates these roles for you.
Volumes
Fargate currently supports non-persistent, empty data volumes for containers. When you define your container, you no longer use the host field and only specify a name.
Load balancers
For awsvpc
mode, and therefore for Fargate, use the IP target type instead of the instance target type. You define this in the Amazon EC2 service when creating a load balancer.
If you’re using a Classic Load Balancer, change it to an Application Load Balancer or a Network Load Balancer.
Tip: If you are using an Application Load Balancer, make sure that your tasks are launched in the same VPC and Availability Zones as your load balancer.
Let’s migrate a task definition!
Here is an example NGINX task definition. This type of task definition is what you’re used to if you created one before Fargate was announced. It’s what you would run now with the EC2 launch type.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 |
{ "containerDefinitions": [ { "name": "nginx", "image": "nginx", "memory": "512", "cpu": "100", "essential": true, "portMappings": [ { "hostPort": "80", "containerPort": "80", "protocol": "tcp" } ], "logConfiguration": { "logDriver": "awslogs", "options": { "awslogs-group": "/ecs/", "awslogs-region": "us-east-1", "awslogs-stream-prefix": "ecs" } } } ], "family": "nginx-ec2" } |
OK, so now what do you need to do to change it to run with the Fargate launch type?
- Add
FARGATE
forrequiredCompatibilities
(not required, but a good safety check for your task definition). - Use
awsvpc
as the network mode. - Just specify the
containerPort
(thehostPort
value is the same). - Add a task
executionRoleARN
value to allow logging to CloudWatch. - Provide
cpu
andmemory
limits for the task.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 |
{ "requiresCompatibilities": [ "FARGATE" ], "containerDefinitions": [ { "name": "nginx", "image": "nginx", "memory": "512", "cpu": "100", "essential": true, "portMappings": [ { "containerPort": "80", "protocol": "tcp" } ], "logConfiguration": { "logDriver": "awslogs", "options": { "awslogs-group": "/ecs/", "awslogs-region": "us-east-1", "awslogs-stream-prefix": "ecs" } } } ], "networkMode": "awsvpc", "executionRoleArn": "arn:aws:iam::<em><your_account_id></em>:role/ecsTaskExecutionRole", "family": "nginx-fargate", "memory": "512", "cpu": "256" } |
Are there more examples?
Yep! Head to the AWS Samples GitHub repo. We have several sample task definitions you can try for both the EC2 and Fargate launch types. Contributions are very welcome too :).