Sharing Our Passion for Technology
& Continuous Learning
ECS Anywhere First Impressions
AWS ECS Anywhere First Impressions
It isn't often that we read the mass marketing emails that we all get everyday. AWS sends out an email each week (usually on Tuesday) with a list of recent updates and new services. I actually get a lot of value out of reading it over.
A couple weeks ago I saw in that email that "ECS Anywhere" was now in "GA". I had a hunch what it was so I looked into it and I am pleased to report that it is an awesomely useful feature.
At a high level, it allows us to take a Linux machine (bare bone or VM) that is running anywhere outside AWS and hook it into the ECS control plane so that Docker containers can be deployed to it. There are a few key properties of this setup that are worth mentioning:
- The host does not need ingress access from AWS, only egress to AWS
- The initiation of the deployment is triggered from the AWS side so it can be put in Cloudformation like any other task
- The task is pretty much just like any other, it has an IAM role just like other tasks.
The main marketing for the feature focuses on its ability to extend compute capacity. I, however, see it as a way to help migrate systems to the cloud more easily.
Most systems, in my experience, cannot be simply lift-and-shifted to the cloud or rebuilt there greenfield practically. There are usually on-premise databases, mainframes, and other things that cannot move. Organizations are also hesitant to open up their datacenter networks to AWS.
ECS anywhere opens up a couple of key use cases:
First, it can facilitate a conversion to containers and breaking down a monolith. We continue to deploy it on-premise but use AWS and Cloudformation to manage the deployment. This allows the application to run local to the other parts of the system but in a way that is easily moved into ECS(EC2) or Fargate at a later time.
Second, it can be used as a data sync bridge. Deploy a small application that can run on-premise and connect to existing data sources, or listen to existing queues and relay data changes into cloud event streams such as Kinesis, SQS, Kafka, etc. A good example of this would be to deploy Debezium using it. From a security perspective, this is very slick because we don't need to manage IAM keys. Instead, simply leverage a task role that is assumed by the container.
To setup ECS anywhere only a few pieces are needed. First, we need to create an ECS cluster. The following Cloudformation template sets this up:
AWSTemplateFormatVersion: '2010-09-09'
Transform: 'AWS::Serverless-2016-10-31'
Resources:
Cluster:
Type: AWS::ECS::Cluster
Properties: {}
RemoteHostRole:
Type: AWS::IAM::Role
Properties:
AssumeRolePolicyDocument:
Version: '2012-10-17'
Statement:
- Effect: Allow
Action:
- sts:AssumeRole
Principal:
Service:
- ssm.amazonaws.com
ManagedPolicyArns:
- 'arn:aws:iam::aws:policy/service-role/AmazonEC2ContainerServiceforEC2Role'
- 'arn:aws:iam::aws:policy/AmazonSSMManagedInstanceCore'
Outputs:
RemoteHostRoleName:
Value: !Ref RemoteHostRole
Next, we connect the on-premise machine into the cluster. Go to the ECS cluster page and under the "Instances" tab click the register button. Select the role created above and there will be a command that can be run on the VM. The provided script will install all the necessary software and hook the instance into the ECS cluster. You should then see the cluster listed on the instances tab.
Finally, we can deploy an application to our cluster similar to any other ECS task:
AWSTemplateFormatVersion: '2010-09-09'
Parameters:
Cluster:
Type: String
Description: Id of the cluster to target
Resources:
LogGroup:
Type: AWS::Logs::LogGroup
InstanceRole:
Type: AWS::IAM::Role
Properties:
AssumeRolePolicyDocument:
Version: '2012-10-17'
Statement:
- Effect: Allow
Action:
- sts:AssumeRole
Principal:
Service:
- ecs-tasks.amazonaws.com
ManagedPolicyArns:
- 'arn:aws:iam::aws:policy/CloudWatchLogsFullAccess'
TaskDefinition:
Type: AWS::ECS::TaskDefinition
Properties:
RequiresCompatibilities:
- EXTERNAL
ContainerDefinitions:
- Name: "nginx"
Image: "public.ecr.aws/nginx/nginx:latest"
Memory: 256
Cpu: 256
Essential: true
LogConfiguration:
LogDriver: awslogs
Options:
awslogs-region: !Ref AWS::Region
awslogs-group: !Ref LogGroup
PortMappings:
- ContainerPort: 80
HostPort: 8080
Protocol: "tcp"
ExecutionRoleArn: !GetAtt InstanceRole.Arn
NetworkMode: bridge
Family: "nginx"
Service:
Type: AWS::ECS::Service
Properties:
Cluster: !Ref Cluster
DesiredCount: 1
TaskDefinition: !Ref TaskDefinition
LaunchType: EXTERNAL
DeploymentConfiguration:
MaximumPercent: 100
MinimumHealthyPercent: 0
This strategy should make it a lot easier to migrate existing applications to AWS by making on-premise services more consistent with cloud deployed services. I'm excited to try some of the above strategies on one of my next migration projects.
References: