Elastic Container Service - Lexicon from CLI

Prerequisites

Firstly install and configure both the AWSCLI and ECSCLI.

These are the steps to use the CLI to generate the Lexicon infrastructure with a Fargate Task. All .json configuration files are available on github.

Cluster

1
2
3
4
5
6
7
8
--- Create ECS cluster using config and profile setup from `Prerequisites`
ecs-cli up --cluster-config carl_configuration_name --ecs-profile carl_ecs_cli_profile

--- Get default security group ID for the VPC. Use the VPC ID from the previous output
aws ec2 describe-security-groups --filters Name=vpc-id,Values=vpc-00000000000000000 --region ap-southeast-2

--- Security group rule to allow inbound access on port 80
aws ec2 authorize-security-group-ingress --group-id sg-0000000000000000 --protocol tcp --port 80 --cidr 0.0.0.0/0 --region ap-southeast-2

Compose File

Here you will need subnet ID 1, subnet ID 2 and security group ID values which would have been displayed when you ran ecs-cli up. If you cleared the console you can use aws ec2 describe-vpcs and look at the Tags to make an educated guess.

References

Elastic Container Service Stack Overview

VPC - Virtual Private Cloud

A virtual private cloud (VPC) is a virtual network dedicated to your AWS account. It is logically isolated from other virtual networks in the AWS Cloud. You can launch your AWS resources, such as Amazon EC2 instances, into your VPC. A VPC spans all the Availability Zones in the region.

When you create a VPC, you must specify a range of IPv4 addresses for the VPC in the form of a Classless Inter-Domain Routing (CIDR) block; for example, 10.0.0.0/16. This is the primary CIDR block for your VPC.

Amazon Elastic Container Service Stack Overview

Subnets

After creating a VPC, you can add one or more subnets in each Availability Zone. When you create a subnet, you specify the CIDR block for the subnet, which is a subset of the VPC CIDR block.

EC2 - Elastic Compute Cloud

Amazon Elastic Compute Cloud (EC2) gives you a platform for your infrastructure to live in. The below is a high level diagram showing the structure and relationships. For access you will need to create an account at https://aws.amazon.com/

ECS - Elastic Container Service

This is the AWS container orchestration service that supports Docker.

Cluster

Service

Start from task definition and keep it running.

Task

You can manually run a task from a task definition but its best to use a Service to keep it running. A Task is a running collection of docker containers.

Container

Docker container spun up from its image.

Elastic Container Service Simple Demo

This runs on top of Amazon Elastic Compute Cloud (Amazon EC2) and the steps below follow the AWS GUI (graphical user interface). I learnt most of the content below by following Arthur Ulfeldt‘s tutorial Deploying Docker to AWS.

This demo will simply write the current datetime to a volume using the busybox image, the container is called data-source. Another container running nginx will then display this data, this container is called data-server.

Simple Demo Infrastructure Overview

Calling data-server on its public IP will then display as follows:

nginx data-server

Setup

Create your account at https://aws.amazon.com/ login and under AWS Management Console type or look for ECS, this will take you to the ECS Dashboard

Cluster

Create cluster type of launch type FARGATE, it may be called something like Networking only and mention Powered by AWS Fagate - things in IT change daily :)

  • Cluster name: simple-demo2
  • Check Create VPC
  • Tag: Description|simple-demo2 (this is the key|value)
  • Check Enable container insights for CloudWatch
  • From the CLI you can view all clusters:

Task Definition

Select Task Definitions -> Create new Task Definition

  • Select the FARGATE template
  • Task Definition Name: task-definition-data-server
  • Requires Compatibilities: FARGATE
  • Task Role: escTaskExecutionRole
  • Network Mode: awsvpc
  • Task execution role: ecsTaskExecutionRole
  • Task memory (GB): 0.5GB
  • Task CPU (vCPU): 0.25 vCPU

Volumes:

  • create one called shared-data

CONTAINER 1

  • Container name: data-source
  • Image: busybox
  • Memory Limits (MiB): 128
  • Entry point: sh, -c, while true; do echo $(date) > /shared-data/index.html; sleep 5; done
  • Mount points: select source volume, and set the path /shared-data to match the shell script
  • Log configuration: check Auto-configure CloudWatch Logs

CONTAINER 2

  • Container name: data-server
  • Image: nginx
  • Memory Limits (MiB): 128
  • Port mappings: 0 -> 80
  • Mount points: select source volume, and set the path /usr/share/nginx/html

Run Task

Now manually run the above task definition from Tasks tab, Run new Task.

Once it starts up select the running task, copy its Public IP into a browsers and you should see the current time update every 5 seconds. Per the image above this IP was 3.104.47.134

References

AWS Install & Configure CLI

Prerequisites

To configure the below you will need the required access key id and secret access key which you can get from the AWS AMI Console (Identity and Access Management) you will need to be logged in. Any commands that point to a .json configuration file are available on github.

AWSCLI

  1. Download and install using the MSI installer for windows.

This will live in C:\Program Files\Amazon\AWSCLI and should then work from any terminal.

  1. Check version
1
aws --version
  1. Configure with the keys you got from the IAM in the amazon console.
1
2
3
4
5
C:\> aws configure
AWS Access Key ID [None]: HOEHOEHOEHOHEOHEOHE
AWS Secret Access Key [None]: HO/hehOehoHEOHEhohEOHeohEOH+EohOEe
Default region name [None]: ap-southeast-2
Default output format [None]:

This creates these files which you can edit with any text editor.

1
2
3
4
5
6
7
8
~ C:\Users\[USERNAME]\.aws\credentials
[default]
aws_access_key_id = HOEHOEHOEHOHEOHEOHE
aws_secret_access_key = HO/hehOehoHEOHEhohEOHeohEOH+EohOEe

~ C:\Users\[USERNAME]\.aws\config
[default]
region = ap-southeast-2
  1. Then you can test it works
1
aws iam list-roles
  1. Create the task execution IAM role
1
2
3
4
5
6
--- Create the task execution role
C:\dev\aws\ami>
aws iam --region ap-southeast-2 create-role --role-name ecsTaskExecutionRole --assume-role-policy-document file://task-execution-assume-role.json

--- Attach the task execution role policy
aws iam --region ap-southeast-2 attach-role-policy --role-name ecsTaskExecutionRole --policy-arn arn:aws:iam::aws:policy/service-role/AmazonECSTaskExecutionRolePolicy

ECSCLI

This will live in C:\Program Files\Amazon\ECSCLI

  1. Run windows powersell as administrator
1
2
3
4
5
--- create folder
New-Item C:\Program Files\Amazon\ECSCLI -type directory

--- install
Invoke-WebRequest -OutFile ‘C:\Program Files\Amazon\ECSCLI\ecs-cli.exe’ https://amazon-ecs-cli.s3.amazonaws.com/ecs-cli-windows-amd64-latest.exe
  1. Edit the environment variables and add C:\Program Files\Amazon\ECSCLI to the PATH variable field

  2. Restart powersell and check version

1
ecs-cli --version
  1. Configure with the same keys used above

I used the profile names carl_ecs_cli_profile and carl_configuration_name below when setting up ECS for the Lexicon via the AWS CLI.

1
2
3
ecs-cli configure profile --profile-name carl_ecs_cli_profile --access-key HOEHOEHOEHOHEOHEOHE --secret-key HO/hehOehoHEOHEhohEOHeohEOH+EohOEe

ecs-cli configure --cluster ClusterName1 --default-launch-type FARGATE --region ap-southeast-2 --config-name carl_configuration_name

Note that --cluster needs to satisfy regular expression pattern: [a-zA-Z][-a-zA-Z0-9]*

This creates these files which you can edit with any text editor.

1
2
3
4
5
~ C:\Users\[USERNAME]\AppData\Local\ecs\config
: carl_configuration_name

~ C:\Users\[USERNAME]\AppData\Local\ecs\credentials
: carl_ecs_cli_profile

References

Elastic Container Service - Lexicon from AWS Console

The Lexicon is an open source project available on GitHub, the steps below setup the infrastructure in AWS using the AWS Console for launch type EC2. There is a stack overview here that shows how the infrastructure works together. Alternatively this can also be done from the CLI where I used the launch type fargate.

Cluster

Login to the Console and search for ECS and select create new cluster.

Instance configuration

AWS Fargate type is a compute engine that allows you to run containers without having to manage servers or clusters. For the steps below I used EC2 Linux + Networking. (for reasons :D)

1
Type:                            EC2 Linux + Networking

This will also create the following resources:

  • Cluster
  • VPC
  • Subnets
  • Auto Scaling group with Linux AMI
1
2
Cluster name:                    lexicon-cluster
Provisioning Model: On-Demand Instance

With On-Demand Instances, you pay for compute capacity by the hour, with no long-term commitments or upfront payments.

1
2
3
4
5
6
EC2 instance type:               m5.large
Instances: 1
EC2 Ami Id: Amazon Linux 2 AMI [ami-0e18747114eff8bce]
(ECS-optimized AMI)
EBS storage (GiB): 22
Key pair: *select if setup on EC2

ami-0e18747114eff8bce is the Amazon Linux AMI 2.0.20190913 x86_64 ECS HVM GP2 Linux Image used for the virtual machine. AMI stands for Amazon Machine Image.

Networking

Configure the VPC for your container instances to use. A VPC is an isolated portion of the AWS cloud populated by AWS objects, such as Amazon EC2 instances. You can choose an existing VPC, or create a new one with this wizard.

1
2
3
4
5
6
VPC:                             *create new
CIDR block: 10.0.0.0/16
Subnet 1: 10.0.0.0/24
Subnet 2: 10.0.1.0/24
Security group: *create new
Security group inbound rules: 0.0.0.0/0:80

Container instance IAM role

The Amazon ECS container agent makes calls to the Amazon ECS API actions on your behalf, so container instances that run the agent require the ecsInstanceRole IAM policy and role for the service to know that the agent belongs to you. If you do not have the ecsInstanceRole already, we can create one for you.

1
Container instance IAM role:     ecsInstanceRole

Tags

These are key value

1
Description:lexicon

CloudWatch Container Insights

CloudWatch Container Insights is a monitoring and troubleshooting solution for containerized applications and microservices. It collects, aggregates, and summarizes compute utilization such as CPU, memory, disk, and network; and diagnostic information such as container restart failures to help you isolate issues with your clusters and resolve them quickly.

1
CloudWatch Container Insights:    [X] Enable Container Insights

Clicking create will then create all of the following resources

  • ECS cluster as lexicon-cluster
  • ECS Instance IAM Policy - IAM Policy for the role ecsInstanceRole is attached
  • CloudFormation Stack - EC2ContainerService-lexicon-cluster

Cluster resources

1
2
3
4
5
6
7
8
9
10
11
12
13
14
ECS AMI ID                           ami-0e18747114eff8bce
VPC vpc-0c0c0c0000c00c0cc
Subnet 1 subnet-0c0c0c0000c00c0cc
Subnet 1 route table association rtbassoc-0c0c0c0000c00c0cc
Subnet 2 subnet-0c0c0c0000c00c0cc
Subnet 2 route table association rtbassoc-0c0c0c0000c00c0cc
VPC Availability Zones ap-southeast-2a, ap-southeast-2b, ap-southeast-2c
Security group sg-0c0c0c0000c00c0cc
Internet gateway igw-0c0c0c0000c00c0cc
Route table rtb-0c0c0c0000c00c0cc
Amazon EC2 route EC2Co-Publi-000000000000
Virtual private gateway attachment EC2Co-Attac-00000000000
Launch configuration EC2ContainerService-lexicon-cluster-EcsInstanceLc-0c0c0c0000c00c0cc
Auto Scaling group EC2ContainerService-lexicon-cluster-EcsInstanceAsg-0c0c0c0000c00c0cc

Task Definitions

From Task Definitions select Create new Task Definition

1
2
3
4
5
Launch type: EC2 
Task Definition Name: lexicon-definition:6
Requires Compatibilities: EC2
Task Role: ecsTaskExecutionRole
Network Mode: default

If you choose , ECS will start your container using Docker’s default networking mode, which is Bridge on Linux and NAT on Windows. is the only supported mode on Windows.

  • For bridge (FARGATE will only have awsvpc)

Task execution IAM role

This role is required by tasks to pull container images and publish container logs to Amazon CloudWatch on your behalf. If you do not have the ecsTaskExecutionRole already, we can create one for you.

1
Task execution role:              ecsTaskExecutionRole

Task size

The task size allows you to specify a fixed size for your task. Task size is required for tasks using the Fargate launch type and is optional for the EC2 launch type. Container level memory settings are optional when task size is set. Task size is not supported for Windows containers.

1
Task memory (GB):                 4096

The amount of memory (in MiB) used by the task. It can be expressed as an integer using MiB, for example 1024, or as a string using GB, for example ‘1GB’ or ‘1 gb’.

1
Task CPU (vCPU):                  2048   (512 = 0.5 vCPU, 1024 = 1 vCPU, 2048 = 2 vCPU)

The number of CPU units used by the task. It can be expressed as an integer using CPU units, for example 1024, or as a string using vCPUs, for example ‘1 vCPU’ or ‘1 vcpu’.

Add Container (WEB)

This is the ASP.NET MVC web application.

Standard
1
2
3
4
Container name:          lexicon-web
Image: 000000000000.dkr.ecr.ap-southeast-2.amazonaws.com/lexicon-test
Memory Limits (MiB): soft 512
Port mappings: 80 -> 80

Port mappings: 0 -> 80 means any from the host to the container on 80. This will however then assign a random port like 32722 which would probably not be open in the security group.

1
2
3
4
5
6
7
Environment variables:   

LEXICON_SQL_CONNECTION=Server=@@MACHINE_NAME@@,1433;Database=lexicon;User Id=sa;Password=Password123;

~ these just check for null, so just set the one you want it to use to `yes`
SUBSTITUTE_LOCAL_IP=
SUBSTITUTE_PUBLIC_IP=yes
Advanced container configuration
1
2
Essential:               un-check 
Log configuration: [x] Auto-configure CloudWatch Logs

Essential, if you check this and your process exits, then the entire task is shut down as well. At least one of your containers HAS to have this checked.

Add Container (SQL)

1
2
3
4
Container name:          lexicon-sql
Image: microsoft/mssql-server-linux:2017-CU13
Memory Limits (MiB): soft 2048
Port mappings: 1433 -> 1433
1
2
3
4
Environment variables:   

ACCEPT_EULA=Y
SA_PASSWORD=Password123

You may also designate AWS Systems Manager Parameter Store keys or ARNs using the ‘valueFrom’ field. ECS will inject the value into containers at run-time.

1
2
Essential:               check
Log configuration: [x] Auto-configure CloudWatch Logs

Task (run once off)

  • Clusters -> lexicon-cluster -> tasks -> run new task
1
2
3
4
Launch type:             EC2
Task Definition: lexicon-definition:6
Cluster: lexicon-cluster
Number of tasks: 1

Then hit Run Task and wait for the status to change to RUNNING

  • Clusters -> select task -> expand container -> Click external link

Service

You can start from task definition and keep it running as apposed to running the task as once off.

References