This is a multi-step configuration -- easy mistakes are likely. Be patient! The pay-off will be worth it. Rudimentary knowledge and awareness of the AWS landscape is not necessarily required, but will make it easier to set things up.
Enable fantastic Blue-Green deployments with npm scripts for AWS ECS.
Some of the instructions make references to package.json for npm script for AWS ECS users. You may safely ignore these steps.
- Go to Amazon ECS
- Clusters -> Create Cluster
- Name: prod-ecs-cluster
- On-Demand Instance
- 2 m4.large instances across two AZs for highly available config
- Create new prod-vpc
- Create new prod-security-group
- Allow port 80 and 443 for HTTP and HTTPS inbound
- Allow port range 32768-61000 so that ECS can dynamically scale instances and run healh checks
- Container instance IAM role: ecsIntanceRole 11.Create
This is a big deal.
- Go EC2 -> Network & Security -> Security Groups
- Verify there ports are open:
| Type | Protocol | Port Range | Source |
|---|---|---|---|
| HTTP (80) | TCP (6) | 80 | 0.0.0.0/0 |
| HTTP (80) | TCP (6) | 80 | ::/0 |
| Custom TCP Rule | TCP (6) | 32768-61000 | 0.0.0.0/0 |
| HTTPS (443) | TCP (6) | 443 | 0.0.0.0/0 |
| HTTPS (443) | TCP (6) | 443 | ::/0 |
- Go to Amazon ECS
- Repositories -> Create Repository
- Enter your app-name
- Copy repository URI, add to package.json “imageRepo”: “000000000000.dkr.ecr.us-east-1.amazonaws.com/app-name"
- Create
- Go to Amazon ECS
- Task Definitions -> Create new Task Definition
- Name: app-name-task, role: none, network: bridge
- Add container, name: app-name from before, image: URI from before, but append ":latest"
- Soft limit, 256 MB for Node.js
- Port mappings, Container port: 3000
- Log configuration: awslogs; app-name-logs, region, app-name-prod
- Go to Amazon EC2
- Load Balancers -> Create Load Balancer
- Application Load Balancer
- Name: app-name-prod-elb
- Add listener: HTTPS, 443
- AZs, select prod-vpc, select all
- Tags -> Domain, app-name.yourdomain.com
- Next
- Choose or create SSL cert (star is recommended: add *.yourdomain.com and yourdomain.com separately on the cert)
- Select default ELB security policy
- Next
- Create prod-cluster specific security group only allowing port 80 and 443 inbound
- Next
- New target group, name: app-name
- Health-checks: Keep default "/" if serving a website on HTTP, but if deploying an API and/or redirecting all HTTP calls to HTTPS, ensure your app defines a custom route that is not redirected to HTTPS. On HTTP server GET "/healthCheck" return simple 200 message saying "I'm healthy" -- verify that this does not redirect to HTTPS, otherwise lot's of pain and suffering will occur. Health checks on AWS will fail.
- Next:Review, then Create
- Go to Amazon ECS
- Clusters -> Select "prod-ecs-cluster"
- Task Definition: app-name-task from before
- Service name: app-name
- No of tasks: 2, min healthy: 100, max healthy: 200 for highly available blue/green deployment setup
- Configure ELB 6.1. Application Load Balancer 6.2. ecsServiceRole 6.3. Select app-name-prod-elb from before 6.4. Select app-name:0:3000 container from before 6.5. Add to ELB 6.6. Target Group Name: app-name from before 6.7. Save
- Create Service
- View Service
- Verify information
- Build image with npm run image:build
- Publish and release image with npm run aws:publish
- On the Service Events tabs keep an eye on health check errors
"awsRegion": "us-east-1",
"awsEcsCluster": "prod-ecs-cluster",
"awsService": "app-name"
- cloudwatch -> logs
- Create Log group
- app-name-logs
If you don't use Route 53, don't panic. Just create an A record to the ELB's DNS address and you're done.
- hosted zone
- select domain
- create record set
- alias 'yes'
- Select ELB App load balancer from the list
- Create
Now you need to deploy an application on your newly-minted cloud infrastructure. Enable fantastic Blue-Green deployments with [npm scripts for AWS ECS](https://gist.github.com/duluca/2b67eb6c2c85f3d75be8c183ab15266e#file-npm-scripts-for-aws-ecs-md).
Go to the ELB DNS address and see if your app works. If you used Route 53 to connect your domain with your ELB or through your own DNS provider, then go to the URL and see if things work.
- ELB DNS works, but URL doesn't? Your DNS configuration is wrong.
- ELB DNS doesn't work. Then check the health of your ECS Service, see step 3 below.
- Go to ECS -> Your Cluster -> click on Your Service and switch to the events tab:
If you don't see
service your-app has reached a steady state.then your container is having trouble starting or AWS is failing to perform a health check. - To see what's wrong with your container, go to the Cloudwatch Logs you setup earlier and you'll be able to see the console logs of your application.
- Service is healthy, logs look fine. Things still don't work? Then re-check security group port rules and target group port rules and any AWS IAM security role you may have setup or may be overriding some default behavior that hasn't been covered.
- Call someone who knows better :)