
Starting FARGATE
For the past year at Medium we’ve been using ECS to deploy containers to AWS. When Amazon announced FARGATE earlier this week, we were really excited. It promises to solve a bunch of issues we experience with the current stack. This is the story of getting a FARGATE service up and running using our internal deployment system, BBFD. BBFD is an internal CLI and continuous deployment tool that we use to build, package, test and deploy our Docker services. Hopefully this post can save anyone else trying to retrofit FARGATE some time and headache.
BBFD uses CloudFormation, but if you aren’t and just using the AWS API, the AWS API calls match CloudFormation documents pretty accurately, so it should be easy to adapt the code snippets to the API.
Looking at the updated API docs, it seemed pretty straight forward. Update the ECS Service’s LaunchType
to FARGATE
and away we go.
Service(LaunchType="FARGATE", ...)
Not Quite. 💩
AWSVPC
FARGATE requires ECS Task network mode “awsvpc”. We haven’t adopted awsvpc yet. It allows each container to have it’s own networking configuration instead of sharing the ec2 container instance’s. We will have to adopt it along the way. This requires adding a NetworkConfiguration
to the Service object.
Service(
NetworkConfiguration=AwsvpcConfiguration(
AssignPublicIp=("ENABLED"|"DISABLED"),
SecurityGroups=[basestr...],
Subnets=[basestr...]), ...)
Ok. Cool, ready to rock! … 💩
Service Role
The “awsvpc” mode doesn’t allow service roles. Since we are using ELBs to load balance our container services, we have a “Role” defined in the Service description. We had to remove it when using awsvpc.

Maybe now it will … 💩
Task Definition
It turns out we will also need to make some modifications to our Task Definition. Tasks need to be “FARGATE” compatible. This is done by adding RequiresCompatibilities
to your definition. There isn’t a lot of documentation about what this means, but I think it’s a macro to setup the right “Compatibilities” for the task /shrugs.
We’ll also need to change NetworkMode
to “awsvpc”.
TaskDefinition(
RequiresCompatibilities=["FARGATE"],
NetworkMode="awsvpc", ...)
Let me just … 💩
OK, so with FARGATE, we’ll need to define our memory and cpu requirements at the TaskDefinition
layer and not (just) the ContainerDefinition
layer. It’s pretty strict about what combinations are allowed. The documentation is a little unclear about what type of values are expected, but strings containing integers is what worked for me.
We also need to define an ExecutionRoleArn
. I’m assuming this is in place of the old Service Role we removed earlier.
TaskDefinition(
ExecutionRoleArn="arn:aws:iam::xxx:role/myEcsTaskExecutionRole",
Memory="4096",
Cpu="2048", ...)
The ExecutionRole
contains one policy, the default AmazonECSTaskExecutionRolePolicy
policy.
It’s gotta work now … 💩
Target Group Type
The “awsvpc” mode can’t register an a “instance” type target group, so we had to modify our target group to be of type “ip”.
TargetGroup(TargetType="ip", ...)
And…. 🎉🍾

In retrospect, it would have been nice if Amazon had made a little guide for all the knobs that need to be turned (pun intended), but alas, it only took an afternoon to get something working. There’s still a bunch of Ops-y concerns we have about FARGATE before it’s ready for prime time, but I’ll leave that for another day.
We’re Hiring in San Francisco!
3/30/2018
We are in the early stages of modernizing our build/deploy pipeline and rebuilding our container infrastructure on k8s. Visit https://jobs.lever.co/medium to apply.
Bonus Material
Troposphere
BBFD uses troposphere to generate cloudformation documents and deploy them to various environments. Troposphere is a little behind on the API, so we had to roll some resources of our own to use the new API. This isn’t exhaustive. We only added the properties that we are using. If you want something less experimental and more “correct”, you could use the generator scripts in the troposphere repository. I haven’t tried them.