The goal of the article is to have a locally running VM, which is enrolled into an Amazon ECS cluster using ECS Anywhere. On the local VM two containers will be running: a dummy web service listening on a port and a load balancer, which discovers the web service and exposes it based on some predefined rules.
For deployment we will use the AWS Copilot CLI. AWS Copilot doesn't support ECS Anywhere as of writing this, however, its flexible extensibility allows us to flip some CloudFormation properties and to have our containers running on 'external container instances'.
The load balancer cannot be an Application Load Balancer in this case, as the goal is to have the load balancer inside the VM. A great cloud-native alternative is Traefik, which thanks to its combination of static and dynamic configuration is a perfect fit for the task.
Thanks to the building blocks the following features are available for the local cluster:
- It runs on-prem (which can be a requirement due to external constraints)
- The container orchestration is fully cloud-native (you can use all features of ECS and SSM)
- Rolling updates are available for the backend services due to Traffik's dynamic discovery capabilities
- Circuit-breaker is enabled and performs automated rollbacks, if the services fail to stabilize during deployment
- You can make use of the expressive Copilot manifests to configure your application
- Install Vagrant
- Install VirtualBox
- Install AWS Copilot CLI
- Install and configure the AWS CLI
-
Initialize Copilot app
copilot init
-
Initialize & deploy Copilot
test
environmentcopilot env init -n test copilot env deploy -n test
-
Start Vagrant machine
vagrant up
-
Get registration command for the local VM as an external machine:
- Navigate to the ECS cluster in the ECS Service
- Choose the right region
- Click the Infrastructure tab, then the Register external instances button
- In the popup set the Number of instances to 1, and for Instance role select Create new.
- Copy the registration command for Linux in the last step
-
Register the local VM as an external machine:
vagrant ssh sudo -s # And then execute command copied from step 4 # curl ...
-
Make sure that the registration completes and that the instance shows up in the Infrastructure tab of the cluster.
-
Initialize & deploy the workloads
copilot svc init -e test -n whoami copilot svc deploy -e test -n whoami copilot svc init -e test -n traefik copilot svc deploy -e test -n traefik
-
Now you can navigate to the Traefik dashboard to check if the Docker provider is enabled and the services are discovered:
http://localhost:8080/
-
You can get a response from the whoami service by making the following request:
curl -H 'Host: whoami.domain.com' http://localhost:8081/whoami
Note: the port forwarding for the host port 80 with VirtualBox didn't work for me, so I redirected the VM's port 80 to port 8081 on the host.
-
De-register the external instance
- Navigate to the ECS cluster in the ECS Service
- Choose the right region
- Click the Infrastructure tab
- Under Container Instances select your VM, then Actions and Drain
- Wait until the instance disappears (this can take a while)
-
Delete the Copilot application:
copilot app delete
-
Delete the managed node from SSM
- Open SSM Fleet Manager
- Select your VM
- Press Node actions, then Node settings, then Deregister this managed node
-
Delete the IAM role
ecsExternalInstanceRole
-
Destroy the local machine
vagrant destroy
- The article Implementing application load balancing of Amazon ECS Anywhere workloads using Traefik Proxy demonstrates a similar use case, however it suggests using the ECS discovery with Traefik, which enables putting the Traefik load balancer on one external machine and placing the backend service on a different host. It's not exactly what I was looking for, additionally, it has a major drawback: it requires the exposure of the port of the backend containers on the host, which can be a security risk, additionally it prevents rolling updates and horizontal scaling, as the port can only be bound to one container at a time.
- AWS Copilot CLI docs
- Traefik docs