Swift Software Group

Launch ECS container using AWS CLI - Step 2 - Launch EC2 Instance

Create an “EC2 Contaner Service” (ECS) cluster with one EC2 instance. This will be used to host ECS tasks / container instances.

This is part of a multi-post thread involving these steps:

  1. Network Setup
  2. Launch EC2 Instance (this post)
  3. Create Docker Image
  4. Create Service
  5. Cleanup

Define names

# Subnets
subnet_1="subnet-ecs-1"
subnet_2="subnet-ecs-2"

# Security Group
security_group="security-ecs"

# cluster
cluster="cluster-ecs"

# IAM
instance_role="instance-role-ecs"
instance_profile="instance-profile-ecs"

# EC2
instance="instance-ecs"

# SSH access key
key="aws-ec2-key"

ECS Cluster

Create ECS Cluster:

# Get IDs
group_id=$(aws ec2 describe-security-groups --filters Name=tag:Name,Values=$security_group | jq -r '.SecurityGroups[0].GroupId')
subnet_1_id=$(aws ec2 describe-subnets --filters Name=tag:Name,Values=$subnet_1 | jq -r '.Subnets[0].SubnetId')

echo "Create ECS cluster $cluster ..."
aws ecs create-cluster --cluster-name $cluster

EC2 Instance Role

Create an “assume role” policy configuration and save it to a file instance-policy.json:

cat << EOT > ./instance-policy.json
{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Effect": "Allow",
      "Principal": {
        "Service": "ec2.amazonaws.com"
      },
      "Action": "sts:AssumeRole"
    }
  ]
}
EOT

Create the EC2 Instance Role:

# EC2 Instance Role
echo "Create EC2 Instance Role ..."
aws iam create-role \
    --role-name $instance_role \
    --assume-role-policy-document file://instance-policy.json

… and attach the AmazonEC2ContainerServiceforEC2Role policy to the instance role:

aws iam attach-role-policy \
    --role-name $instance_role \
    --policy-arn arn:aws:iam::aws:policy/service-role/AmazonEC2ContainerServiceforEC2Role

When you attach a managed policy to a role, the managed policy becomes part of the role’s permission (access) policy.

EC2 Instance Profile

Create EC2 Instance Profile:

# EC2 Instance Profile
echo "Create EC2 Instance Profile ..."
aws iam create-instance-profile --instance-profile-name $instance_profile

aws iam add-role-to-instance-profile \
    --instance-profile-name $instance_profile \
    --role-name $instance_role

aws iam list-instance-profiles

echo "Wait 15 seconds for new instance profile to replicate in AWS ..."
sleep 15

EC2 Instance

Create a “block device mappings” configuration and save it to a file instance-block-device-mappings.json:

cat << EOT > ./instance-block-device-mappings.json
[
    {
        "DeviceName": "/dev/sdf",
        "Ebs": {
            "DeleteOnTermination": true,
            "VolumeSize": 50
        }
    }
]
EOT

Create an “instance startup” script and save it to a file instance-user-data.sh. You can do anything in the startup script. In our case we use it to generate /etc/ecs/ecs.config.

NOTE: This script runs on the EC2 instance after it launches.

cat << "EOT" > ./instance-user-data.sh
#!/bin/bash
cluster="cluster-ecs"

echo "ECS_CLUSTER=$cluster" >> /etc/ecs/ecs.config
echo "ECS_CONTAINER_INSTANCE_TAGS={\"ECS_CLUSTER\": \"$cluster\"}" >> /etc/ecs/ecs.config
echo ECS_AVAILABLE_LOGGING_DRIVERS='["json-file", "awslogs"]' >> /etc/ecs/ecs.config
EOT

Now we have everything that’s needed. Launch the EC2 instance in subnet 1:

# EC2 Instance
echo "Launch EC2 instance in subnet 1: $subnet_1_id ..."

json=$(aws ec2 run-instances \
    --subnet-id $subnet_1_id \
    --security-group-ids $group_id \
    --image-id resolve:ssm:/aws/service/ecs/optimized-ami/amazon-linux-2/recommended/image_id \
    --instance-type t2.micro \
    --count 1 \
    --key-name $key \
    --iam-instance-profile Name=$instance_profile \
    --user-data file://instance-user-data.sh \
    --block-device-mappings file://instance-block-device-mappings.json \
    --tag-specifications 'ResourceType=instance,Tags=[{Key=Name,Value='$instance'}]')

instance_id=$(echo $json | jq -r '.Instances[0].InstanceId')

aws ec2 wait instance-exists --instance-ids $instance_id    
echo "  Instance created ..."

aws ec2 wait instance-running --instance-ids $instance_id    
echo "  Instance is running ..."

aws ec2 wait instance-status-ok --instance-ids $instance_id    
echo "  Instance is ready ..."

Verify

Check that EC2 container instance has checked in to the ECS Cluster:

cluster="cluster-ecs"
aws ecs list-container-instances --cluster $cluster

Also should be reported in registeredContainerInstancesCount when describing the ECS cluster:

cluster="cluster-ecs"
aws ecs describe-clusters --cluster $cluster