Having a fast and reliable way to update your deployment environments is a game changer in
terms of team velocity and confidence.
ecs-ship is a simple yet powerful tool that can
help your team ship faster.
10 minute read
Most of our teams at NextRoll leverage the power of AWS ECS for container
orchestration. Each team manages their AWS resources, providing them with
ultimate freedom when choosing technologies or what or when to deploy. In this article,
we want to share
ecs-ship, a small tool the likes of
we wrote to solve some of our common workflows and will soon be open source.
Some typical workflows
Let’s see by example which workflows you might want to use
ecs-ship for by looking at
two typical tasks we can accomplish with it:
- Deploying a new version of an application.
- Changing the resource allocation of an application (aka right-sizing).
When deploying a new version of a containerized application to AWS ECS, there
are three resources you need to account for: container images, ECS task definitions, and
ECS services. Container images are a pretty common artifact these
days. They represent a “unit” containing your application and all the
dependencies it might need to run correctly. ECS Task definitions
represent a containerized workload; essentially, they let ECS know what’s required to run
your tasks. For example, I need three containers running my application image and 1 running
a database image. You express these requirements via container definitions inside the task
definition. Finally, ECS services reference a version of a task
definition and are responsible for letting AWS know “we do need these containers running
In this framework, to deploy a new version of your application, you need to follow these
- Create and push a new version of your application’s image to a registry.
- Create a new version of your task definition that references the freshly uploaded image.
- Finally, update your service to the newly created task definition.
Let’s go through them step by step.
Building and pushing your images to a registry would usually look like this:
export VERSION=`git rev-parse HEAD` docker build -t your.registry.io/yourusername/yourapp:$VERSION . docker push your.registry.io/yourusername/yourapp:$VERSION
Once you have your new image (or images) up on the registry and ready to use,
comes in to help you with the rest:
cat << EOF | ecs-ship your-cluster yourapp-service containerDefinitions: yourapp-definition: image: your.registry.io/yourusername/yourapp:$VERSION environment: VERSION: $VERSION SHIPPED_BY: ecs-ship EOF
As you can see,
ecs-ship takes the cluster you want to update and the service you want
to update in that cluster. Furthermore, it takes a configuration file to
non-destructively modify some aspects of the chosen service, including the container
definitions. Here inside the container definition, we have decided to update the image to
refer to the new
VERSION and upserted a couple of environment variables to later check on
the task definition. You can check the README on ecs-ship’s repo to get
familiar with which aspects of ecs services you can change.
Running this command will perform these steps for you:
- Pull the task definition of the specified cluster and service.
- Create a copy of this task definition performing the updates you requested on the input
file (only if anything is updated).
- Update the specified service to point to the newly created version of the task
- Wait for your service to reflect the changes you requested correctly.
If for some reason, your service doesn’t reach stability with your new configuration,
ecs-ship will automatically:
- Revert to the last task definition (if it was stable).
- De-register the new bugged task definition.
Right-sizing your services
We just saw how
ecs-ship would help you in deploying new versions of ECS services. Now
let’s explore another simple yet powerful
ecs-ship that can help you change the
number of resources a particular service requests from your ECS cluster.
One essential part of your ECS service configuration is the amount of resources a given
container or a given service requires. These resources are controlled by the
cpu represents the amount of “shares” of a
virtual CPU your service needs. Simultaneously,
memoryReservation are hard and
soft caps to the amount of memory your service can use, respectively. These variables
cost you money in the following sense: if the sum of either the memory or the cpu
required by the services running in your cluster surpasses the number of actual
resources in the cluster, you need to spin up a new instance incurring in some
However, not always do your services use as many resources as you reserve for them, and
since you’re charged for the amount of resources you do request, it is a good idea to
keep those as close as possible to the actual usage values. To work out the
amount of resources your ECS services need, you can enable and monitor CloudWatch
metrics, and once you have worked out the number of resources you need,
you can update the configuration using
cat << EOF | ecs-ship your-cluster yourapp-service containerDefinitions: yourapp-definition: cpu: 123 memoryReservation: 123 EOF
As a side note, if you specify
memory, you need to make sure the value is
comfortably higher than
ecs-ship came to be
Those familiar with fabfuel’s ecs-deploy will notice that there’s no much
difference between it and
ecs-ship can be seen as a new take on the
already popular project, with just a few different opinions.
ecs-ship focuses only on
updating a given service with a new version of its task definition, leaving out other
add-on features like slack reporting or newrelic metrics for deployments.
In terms of new features,
ecs-ship can change resource allocations and
could be extended to change other aspects of a task definition. Furthermore, and we will
see an application of this on a further post,
ecs-ship’s input file-based API makes it
easier to interoperate with other third-party or homebrewed tools.
Besides these minor differences, one of the primary motivations for building
was our bi-annual HackWeek events. These events give us some time to explore
technologies, work on a little side-project or solve issues in our workflow that are not
directly related to our backlog. In our case, with
ecs-ship, we experimented with
need to update resource allocations for our services.
ecs-ship is a little tool you can use either as a static linked binary or as a
containerized tool to manage your
ECS deployments from your local machine or your
continuous delivery pipelines.