Starting FARGATE – Medium Engineering


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.

roles are only needed for non-awsvpc services WITH a loadBalancer

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…. 🎉🍾

clapping elf

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.

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.

some hacky code to experiment with



Source link