Fastah Deployment on ECS

Fastah Application Deployment using ECS (with Fargate)

This guide provides step-by-step instructions to deploy the Fastah application on AWS ECS (Elastic Container Service) using Fargate. The process involves setting up a VPC, configuring networking, creating necessary IAM roles, and deploying the application.

Prerequisites

Before starting, ensure you have the following:

  • Fastah Subscription at AWS Marketplace
  • AWS Account ID
  • AWS Access Key ID and Secret Access Key
  • AWS Session Token (if applicable)
    Set up your environment variables:
# Change the AWS Region, Account ID, related Keys & Token values below
export AWS_REGION="ap-south-1"
export AWS_ACCOUNT_ID=956272822528
export AWS_ACCESS_KEY_ID="Your_Access_Key_ID"
export AWS_SECRET_ACCESS_KEY="Your_Secret_Access_Key"
export AWS_SESSION_TOKEN="Your_AWS_Session_Token"

# Name of the Fastah CLuster. Changes in the below line is Optional
export FASTAH_ECS_CLUSTER="fastah-ip-location"
export FASTAH_IMAGE_VERSION="2025.2.5"



Step 1: Create a VPC

VPC_ID=$(aws ec2 create-vpc --cidr-block 10.0.0.0/16 --region ${AWS_REGION} --query Vpc.VpcId --output text)
aws ec2 create-tags --resources $VPC_ID --tags Key=Name,Value=FastahVPC --region ${AWS_REGION}

Step 2: Create Public and Private Subnets

Create a Public Subnet:

PUBLIC_SUBNET_ID=$(aws ec2 create-subnet --vpc-id $VPC_ID --cidr-block 10.0.1.0/24 --availability-zone ${AWS_REGION}a --region ${AWS_REGION} --query Subnet.SubnetId --output text)
aws ec2 create-tags --resources $PUBLIC_SUBNET_ID --tags Key=Name,Value=FastahPublicSubnet --region ${AWS_REGION}

Create a Private Subnet:

PRIVATE_SUBNET_ID=$(aws ec2 create-subnet --vpc-id $VPC_ID --cidr-block 10.0.2.0/24 --availability-zone ${AWS_REGION}a --region ${AWS_REGION} --query Subnet.SubnetId --output text)
aws ec2 create-tags --resources $PRIVATE_SUBNET_ID --tags Key=Name,Value=FastahPrivateSubnet --region ${AWS_REGION}

Step 3: Create an Internet Gateway & Attach the Internet Gateway to Your VPC

IGW_ID=$(aws ec2 create-internet-gateway --region ${AWS_REGION} --query InternetGateway.InternetGatewayId --output text)
aws ec2 attach-internet-gateway --internet-gateway-id $IGW_ID --vpc-id $VPC_ID --region ${AWS_REGION}

Step 4: Create a Route Table for the Public Subnet and Create a Route to the Internet Gateway

ROUTE_TABLE_ID=$(aws ec2 create-route-table --vpc-id $VPC_ID --region ${AWS_REGION} --query RouteTable.RouteTableId --output text)
aws ec2 create-route --route-table-id $ROUTE_TABLE_ID --destination-cidr-block 0.0.0.0/0 --gateway-id $IGW_ID --region ${AWS_REGION}

Step 5: Associate the Route Table with Public Subnet

aws ec2 associate-route-table --subnet-id $PUBLIC_SUBNET_ID --route-table-id $ROUTE_TABLE_ID --region ${AWS_REGION}

Step 6: Create a Security Group

SG_ID=$(aws ec2 create-security-group --group-name FastahSecurityGroup --description "Security group for ECS application" --vpc-id $VPC_ID --region ${AWS_REGION} --query GroupId --output text)

Step 7: Add Inbound Rules to Allow Traffic on Port 8080 (HTTP)


# Uncomment and Run the following only if you want to allow access to the application from the internet.
# Allowing the acccess from internet is not recommdned. You are requsted to alter the security group to selectly allow from your VPCs
# aws ec2 authorize-security-group-ingress --group-id $SG_ID --protocol tcp --port 8080 --cidr 0.0.0.0/0 --region ${AWS_REGION}

Step 8: Install ECS CLI (if not already installed)

Note: You will require to change the url below, in case your machine is not amd64. More Details: https://github.com/aws/amazon-ecs-cli

# For MacOS: sudo curl -sLo /usr/local/bin/ecs-cli https://amazon-ecs-cli.s3.amazonaws.com/ecs-cli-darwin-amd64-latest
sudo curl -sLo /usr/local/bin/ecs-cli https://amazon-ecs-cli.s3.amazonaws.com/ecs-cli-linux-amd64-latest
sudo chmod +x /usr/local/bin/ecs-cli

Step 9: Configure ECS CLI with AWS Credentials

ecs-cli configure profile --profile-name fastah --access-key ${AWS_ACCESS_KEY_ID} --secret-key ${AWS_SECRET_ACCESS_KEY}

ecs-cli configure --cluster ${FASTAH_ECS_CLUSTER} --region ${AWS_REGION} --default-launch-type FARGATE 

Step 10: Create an IAM Policy for the Service Account

Create a JSON file named FastahECSIAMPolicy.json with the required permissions:

{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Effect": "Allow",
            "Action": [
                "ecs:*",
                "logs:*"
            ],
            "Resource": "*"
        }
    ]
}

Then, create the IAM policy:

# Service account for Fastah Application with required IAM policies (for licensing)
aws iam create-policy --policy-name FastahECSIAMPolicy --policy-document file://FastahECSIAMPolicy.json

Step 11: Create a Service Account with IAM Policy Attached

Create the service account:

ECS_SERVICE_ACCOUNT_NAME="fastah-task-execution-role"
aws iam create-role \
    --role-name ${ECS_SERVICE_ACCOUNT_NAME} \
    --assume-role-policy-document '{
        "Version": "2012-10-17",
        "Statement": [{
            "Effect": "Allow",
            "Principal": {
                "Service": "ecs-tasks.amazonaws.com"
            },
            "Action": "sts:AssumeRole"
        }]
    }'

aws iam attach-role-policy \
    --role-name ${ECS_SERVICE_ACCOUNT_NAME} \
    --policy-arn arn:aws:iam::${AWS_ACCOUNT_ID}:policy/FastahECSIAMPolicy

aws iam attach-role-policy \
    --role-name ${ECS_SERVICE_ACCOUNT_NAME} \
    --policy-arn arn:aws:iam::aws:policy/AmazonEC2ContainerRegistryReadOnly
    

# Verify that there is FastahECSIAMPolicy and AmazonEC2ContainerRegistryReadOnly attached to the ECS execution service account
aws iam list-attached-role-policies --role-name ${ECS_SERVICE_ACCOUNT_NAME}



Step 12: Create an IAM Policy for the Service Account for Fastah License

Create a JSON file named FastahLicenseIAMPolicy.json with the required permissions:

{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Effect": "Allow",
            "Action": [
                "aws-marketplace:MeterUsage",
                "aws-marketplace:RegisterUsage",
                "license-manager:CheckoutLicense",
                "license-manager:CheckInLicense",
                "license-manager:ExtendLicenseConsumption",
                "license-manager:GetLicense"
            ],
            "Resource": "*"
        }
    ]
}

# Service account for Fastah Application with required IAM policies (for licensing)
aws iam create-policy --policy-name FastahLicenseIAMPolicy --policy-document file://FastahLicenseIAMPolicy.json

Step 13: Create a Service Account with IAM Policy Attached

Create the service account:

FASTAH_SERVICE_ACCOUNT_NAME="fastah-ip-location-sa"
aws iam create-role \
    --role-name ${FASTAH_SERVICE_ACCOUNT_NAME} \
    --assume-role-policy-document '{
        "Version": "2012-10-17",
        "Statement": [{
            "Effect": "Allow",
            "Principal": {
                "Service": "ecs-tasks.amazonaws.com"
            },
            "Action": "sts:AssumeRole"
        }]
    }'

aws iam attach-role-policy \
    --role-name ${FASTAH_SERVICE_ACCOUNT_NAME} \
    --policy-arn arn:aws:iam::${AWS_ACCOUNT_ID}:policy/FastahLicenseIAMPolicy


# Verify that there is FastahLicenseIAMPolicy  attached to the ECS execution service account
aws iam list-attached-role-policies --role-name ${FASTAH_SERVICE_ACCOUNT_NAME}


Step 14: Create required Cloudwatch resources

# Create the required resources in the Cloudwatch
aws logs create-log-group \
  --log-group-name "/ecs/fastah-ip-location" \
  --region ${AWS_REGION}

Step 15: Create a Task Definition File (task-definition.json)

Create/Update your task definition (task-definition.json) to include the service account:

{
    "family": "fastah",
    "containerDefinitions": [
        {
            "name": "fastah-ip-location",
            "image": "709825985650.dkr.ecr.us-east-1.amazonaws.com/fastah/ip-location-container-p1:v${FASTAH_IMAGE_VERSION}-amd64",
            "memory": 512,
            "cpu": 256,
            "essential": true,
            "portMappings": [
                {
                    "containerPort": 8080,
                    "protocol": "tcp"
                }
            ],
            "logConfiguration": {
                "logDriver": "awslogs",
                "options": {
                    "awslogs-region": "${AWS_REGION}",
                    "awslogs-group": "/ecs/fastah-ip-location",
                    "awslogs-stream-prefix": "fastah-ip-location"
                }
            }
        }
    ],
    "requiresCompatibilities": [
        "FARGATE"
    ],
    "networkMode": "awsvpc",
    "memory": "512",
    "cpu": "256",
    "executionRoleArn": "arn:aws:iam::${AWS_ACCOUNT_ID}:role/fastah-task-execution-role",
    "taskRoleArn": "arn:aws:iam::${AWS_ACCOUNT_ID}:role/fastah-ip-location-sa"
}

Step 16: Create the Cluster

ecs-cli up \
    --cluster-config default \
    --region ${AWS_REGION} 

Step 17: Deploy Your Application Using ECS CLI with Service Account Reference

Make sure to specify the service account in your deployment command if applicable.

envsubst < task-definition.json > fastah-task-definition.json 
aws ecs register-task-definition --cli-input-json file://fastah-task-definition.json  --region ${AWS_REGION}

aws ecs run-task --cluster ${FASTAH_ECS_CLUSTER} --task-definition fastah --launch-type FARGATE --network-configuration "awsvpcConfiguration={subnets=${PUBLIC_SUBNET_ID},securityGroups=${SG_ID},assignPublicIp=ENABLED}"

Step 18: Verify Your Deployment


# Check the status of task
TASK_ARN=$(aws ecs list-tasks --cluster ${FASTAH_ECS_CLUSTER} --region ${AWS_REGION} --query "taskArns[0]" --output text)
aws ecs describe-tasks --cluster ${FASTAH_ECS_CLUSTER} --tasks ${TASK_ARN}

ecs-cli ps \
    --cluster-config default \
    --region ${AWS_REGION} 

# Wait for 5 mins to ensure all services are up
# Get all Cloudwatch startup logs for past 60 mins.  Ensure "INFO AWS Marketplace Metering licensing check OK id=fastah" line comes up
aws logs filter-log-events --log-group-name "/ecs/fastah-ip-location" \
  --start-time $(($(date +%s) * 1000 - 600000)) --region ${AWS_REGION}

Optional: Clean Up Resources


TASK_ARN=$(aws ecs list-tasks --cluster ${FASTAH_ECS_CLUSTER} --region ${AWS_REGION} --query "taskArns[0]" --output text)
aws ecs stop-task --cluster ${FASTAH_ECS_CLUSTER} --task $TASK_ARN --region ${AWS_REGION}
aws ecs deregister-task-definition --task-definition fastah --region ${AWS_REGION}

ecs-cli down -f  --cluster-config default --region ${AWS_REGION}
aws ecs delete-cluster --cluster ${FASTAH_ECS_CLUSTER} --region ${AWS_REGION}


aws iam detach-role-policy --role-name fastah-task-execution-role --policy-arn arn:aws:iam::${AWS_ACCOUNT_ID}:policy/FastahECSIAMPolicy
aws iam detach-role-policy --role-name fastah-task-execution-role --policy-arn arn:aws:iam::aws:policy/AmazonEC2ContainerRegistryReadOnly
aws iam detach-role-policy --role-name fastah-ip-location-sa --policy-arn arn:aws:iam::${AWS_ACCOUNT_ID}:policy/FastahLicenseIAMPolicy
aws iam delete-policy --policy-arn arn:aws:iam::${AWS_ACCOUNT_ID}:policy/FastahECSIAMPolicy
aws iam delete-policy --policy-arn arn:aws:iam::${AWS_ACCOUNT_ID}:policy/FastahLicenseIAMPolicy

aws ec2 delete-security-group --group-id $SG_ID --region ${AWS_REGION}
aws ec2 delete-subnet --subnet-id $PUBLIC_SUBNET_ID --region ${AWS_REGION}
aws ec2 delete-subnet --subnet-id $PRIVATE_SUBNET_ID --region ${AWS_REGION}
aws ec2 delete-route-table --route-table-id $ROUTE_TABLE_ID --region ${AWS_REGION}
aws ec2 detach-internet-gateway --internet-gateway-id $IGW_ID --vpc-id $VPC_ID --region ${AWS_REGION}
aws ec2 delete-internet-gateway --internet-gateway-id $IGW_ID --region ${AWS_REGION}
aws ec2 delete-vpc --vpc-id $VPC_ID --region ${AWS_REGION}
aws logs delete-log-group --log-group-name "/ecs/fastah-ip-location" --region ${AWS_REGION}