Skip to content

Latest commit

 

History

History
601 lines (386 loc) · 21.4 KB

API.md

File metadata and controls

601 lines (386 loc) · 21.4 KB

NPM version PyPI version Release

Low-Cost ECS

A CDK construct that provides an easy and low-cost ECS on EC2 server setup without a load balancer.

Why

ECS may often seem expensive when used for personal development purposes, due to the cost of the load balancer. The application load balancer is a great service that is easy to set up managed ACM certificates, easy scaling, and has dynamic port mappings..., but it is over-featured for running 1 ECS task.

However, to run an ECS server without a load balancer, you need to associate an Elastic IP to the host instance and install your certificate to your service every time you start up the server. This construct aims to automate these works and make it easy to deploy resources to run a low-cost ECS server.

Try it out!

The easiest way to try the construct is to clone this repository and deploy the sample Nginx server. Edit settings in examples/minimum.ts and deploy the cdk construct. Public hosted zone is required.

  1. Clone and install packages
git clone https://github.com/rajyan/low-cost-ecs.git
yarn install
  1. Edit email and domain in example.ts

    import { App, Stack } from 'aws-cdk-lib';
    import { LowCostECS } from '../src';
    const app = new App();
    const stack = new Stack(app, 'TestStack', {
    env: {
    account: process.env.CDK_DEFAULT_ACCOUNT,
    region: process.env.CDK_DEFAULT_REGION,
    },
    });
    export const minimum = new LowCostECS(stack, 'LowCostECS', {
    hostedZoneDomain: 'example.com',
    email: 'test@example.com',
    });

  2. Deploy!

cdk deploy

Access the configured hostedZoneDomain and see that the sample Nginx server has been deployed.

Installation

To use this construct in your cdk stack as a library,

npm install low-cost-ecs
import { Stack, StackProps } from 'aws-cdk-lib';
import { Construct } from 'constructs';
import { LowCostECS } from 'low-cost-ecs';

class SampleStack extends Stack {
    constructor(scope: Construct, id: string, props?: StackProps) {
        super(scope, id, props);

        const vpc = { /** Your VPC */ };
        const securityGroup = { /** Your security group */ };
        const serverTaskDefinition = { /** Your task definition */ };

        new LowCostECS(this, 'LowCostECS', {
            hostedZoneDomain: "example.com",
            email: "test@example.com",
            vpc: vpc,
            securityGroup: securityGroup,
            serverTaskDefinition: serverTaskDefinition
        });
    }
}

The required fields are hostedZoneDomain and email. You can configure your server task definition and other props. Read LowCostECSProps documentation for details.

Overview

Resources generated in this stack

  • Route53 A record
    • Forwarding to host instance Elastic IP
  • Certificate State Machine
    • Install and renew certificates to EFS using certbot-dns-route53
    • Scheduled automated renewal every 60 days
    • Email notification on certbot task failure
  • ECS on EC2 host instance
    • ECS-optimized Amazon Linux 2 AMI instance auto-scaling group
    • Automatically associated with Elastic IP on instance initialization
  • ECS Service
    • TLS/SSL certificate installation before default container startup
    • Certificate EFS mounted on default container as /etc/letsencrypt
  • Others
    • VPC with only public subnets (no NAT Gateways to decrease cost)
    • Security groups with minimum inbounds
    • IAM roles with minimum privileges

Cost

All resources except Route53 HostedZone should be included in AWS Free Tier if you are in the 12 Months Free period. After your 12 Months Free period, setting hostInstanceSpotPrice to use spot instances is recommended.

  • EC2
    • t2.micro 750 instance hours (12 Months Free Tier)
    • 30GB EBS volume (12 Months Free Tier)
  • ECS
    • No additional charge because using ECS on EC2
  • EFS
    • Usage is very small, it should be free
  • Cloud Watch
    • Usage is very small, and it should be included in the free tier
    • Enabling containerInsights will charge for custom metrics

Debugging

  • SSM Session Manager

SSM manager is pre-installed in the host instance (by ECS-optimized Amazon Linux 2 AMI) and AmazonSSMManagedInstanceCore is added to the host instance role to access and debug in your host instance.

aws ssm start-session --target $INSTANCE_ID
  • ECS Exec

Service ECS Exec is enabled, so execute commands can be used to debug your server task container.

aws ecs execute-command \
--cluster $CLUSTER_ID \
--task $TASK_ID \
--container nginx \
--command bash \
--interactive

Limitations

Because the ECS service occupies a host port, only one task can be executed at a time. The old task must be terminated before the new task launches, and this causes downtime on release.

Also, if you make changes that require recreating the service, you may need to manually terminate the task of the old service.

API Reference

Constructs

LowCostECS

Initializers

import { LowCostECS } from 'low-cost-ecs'

new LowCostECS(scope: Construct, id: string, props: LowCostECSProps)
Name Type Description
scope constructs.Construct No description.
id string No description.
props LowCostECSProps No description.

scopeRequired
  • Type: constructs.Construct

idRequired
  • Type: string

propsRequired

Methods

Name Description
toString Returns a string representation of this construct.

toString
public toString(): string

Returns a string representation of this construct.

Static Functions

Name Description
isConstruct Checks if x is a construct.

isConstruct
import { LowCostECS } from 'low-cost-ecs'

LowCostECS.isConstruct(x: any)

Checks if x is a construct.

xRequired
  • Type: any

Any object.


Properties

Name Type Description
node constructs.Node The tree node.
certFileSystem aws-cdk-lib.aws_efs.FileSystem EFS file system that the SSL/TLS certificates are installed.
cluster aws-cdk-lib.aws_ecs.Cluster ECS cluster created in configured VPC.
hostAutoScalingGroup aws-cdk-lib.aws_autoscaling.AutoScalingGroup ECS on EC2 service host instance autoscaling group.
serverTaskDefinition aws-cdk-lib.aws_ecs.Ec2TaskDefinition Server task definition generated from LowCostECSTaskDefinitionOptions.
service aws-cdk-lib.aws_ecs.Ec2Service ECS service of the server with desiredCount: 1, minHealthyPercent: 0, maxHealthyPercent: 100.
topic aws-cdk-lib.aws_sns.Topic SNS topic used to notify certbot renewal failure.

nodeRequired
public readonly node: Node;
  • Type: constructs.Node

The tree node.


certFileSystemRequired
public readonly certFileSystem: FileSystem;
  • Type: aws-cdk-lib.aws_efs.FileSystem

EFS file system that the SSL/TLS certificates are installed.


clusterRequired
public readonly cluster: Cluster;
  • Type: aws-cdk-lib.aws_ecs.Cluster

ECS cluster created in configured VPC.


hostAutoScalingGroupRequired
public readonly hostAutoScalingGroup: AutoScalingGroup;
  • Type: aws-cdk-lib.aws_autoscaling.AutoScalingGroup

ECS on EC2 service host instance autoscaling group.


serverTaskDefinitionRequired
public readonly serverTaskDefinition: Ec2TaskDefinition;
  • Type: aws-cdk-lib.aws_ecs.Ec2TaskDefinition

Server task definition generated from LowCostECSTaskDefinitionOptions.


serviceRequired
public readonly service: Ec2Service;
  • Type: aws-cdk-lib.aws_ecs.Ec2Service

ECS service of the server with desiredCount: 1, minHealthyPercent: 0, maxHealthyPercent: 100.

https://github.com/rajyan/low-cost-ecs#limitations


topicRequired
public readonly topic: Topic;
  • Type: aws-cdk-lib.aws_sns.Topic

SNS topic used to notify certbot renewal failure.


Structs

LowCostECSProps

Initializer

import { LowCostECSProps } from 'low-cost-ecs'

const lowCostECSProps: LowCostECSProps = { ... }

Properties

Name Type Description
email string Email for expiration emails to register to your let's encrypt account.
hostedZoneDomain string Domain name of the hosted zone.
awsCliDockerTag string Docker image tag of amazon/aws-cli.
certbotDockerTag string Docker image tag of certbot/dns-route53 to create certificates.
certbotScheduleInterval number Certbot task schedule interval in days to renew the certificate.
containerInsights boolean Enable container insights or not.
hostInstanceSpotPrice string The maximum hourly price (in USD) to be paid for any Spot Instance launched to fulfill the request.
hostInstanceType string Instance type of the ECS host instance.
logGroup aws-cdk-lib.aws_logs.ILogGroup Log group of the certbot task and the aws-cli task.
recordDomainNames string[] Domain names for A records to elastic ip of ECS host instance.
removalPolicy aws-cdk-lib.RemovalPolicy Removal policy for the file system and log group (if using default).
securityGroups aws-cdk-lib.aws_ec2.ISecurityGroup[] Security group of the ECS host instance.
serverTaskDefinition LowCostECSTaskDefinitionOptions Task definition for the server ecs task.
vpc aws-cdk-lib.aws_ec2.IVpc VPC of the ECS cluster and EFS file system.

emailRequired
public readonly email: string;
  • Type: string

Email for expiration emails to register to your let's encrypt account.

https://docs.aws.amazon.com/sns/latest/dg/sns-email-notifications.html


hostedZoneDomainRequired
public readonly hostedZoneDomain: string;
  • Type: string

Domain name of the hosted zone.


awsCliDockerTagOptional
public readonly awsCliDockerTag: string;
  • Type: string
  • Default: latest

Docker image tag of amazon/aws-cli.

This image is used to associate elastic ip on host instance startup, and run certbot cfn on ecs container startup.


certbotDockerTagOptional
public readonly certbotDockerTag: string;
  • Type: string
  • Default: v1.29.0

Docker image tag of certbot/dns-route53 to create certificates.

https://hub.docker.com/r/certbot/dns-route53/tags


certbotScheduleIntervalOptional
public readonly certbotScheduleInterval: number;
  • Type: number
  • Default: 60

Certbot task schedule interval in days to renew the certificate.


containerInsightsOptional
public readonly containerInsights: boolean;
  • Type: boolean
  • Default: undefined (container insights disabled)

Enable container insights or not.


hostInstanceSpotPriceOptional
public readonly hostInstanceSpotPrice: string;
  • Type: string
  • Default: undefined

The maximum hourly price (in USD) to be paid for any Spot Instance launched to fulfill the request.

Host instance asg would use spot instances if hostInstanceSpotPrice is set.

https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.aws_ecs.AddCapacityOptions.html#spotprice


hostInstanceTypeOptional
public readonly hostInstanceType: string;
  • Type: string
  • Default: t2.micro

Instance type of the ECS host instance.


logGroupOptional
public readonly logGroup: ILogGroup;
  • Type: aws-cdk-lib.aws_logs.ILogGroup
  • Default: Creates default cdk log group

Log group of the certbot task and the aws-cli task.


recordDomainNamesOptional
public readonly recordDomainNames: string[];
  • Type: string[]
  • Default: [ props.hostedZone.zoneName ]

Domain names for A records to elastic ip of ECS host instance.


removalPolicyOptional
public readonly removalPolicy: RemovalPolicy;
  • Type: aws-cdk-lib.RemovalPolicy
  • Default: RemovalPolicy.DESTROY

Removal policy for the file system and log group (if using default).


securityGroupsOptional
public readonly securityGroups: ISecurityGroup[];
  • Type: aws-cdk-lib.aws_ec2.ISecurityGroup[]
  • Default: Creates security group with allowAllOutbound and ingress rule (ipv4, ipv6) => (tcp 80, 443).

Security group of the ECS host instance.


serverTaskDefinitionOptional
public readonly serverTaskDefinition: LowCostECSTaskDefinitionOptions;

Task definition for the server ecs task.

sampleTaskDefinition


vpcOptional
public readonly vpc: IVpc;
  • Type: aws-cdk-lib.aws_ec2.IVpc
  • Default: Creates vpc with only public subnets and no NAT gateways.

VPC of the ECS cluster and EFS file system.


LowCostECSTaskDefinitionOptions

Initializer

import { LowCostECSTaskDefinitionOptions } from 'low-cost-ecs'

const lowCostECSTaskDefinitionOptions: LowCostECSTaskDefinitionOptions = { ... }

Properties

Name Type Description
containers aws-cdk-lib.aws_ecs.ContainerDefinitionOptions[] No description.
taskDefinition aws-cdk-lib.aws_ecs.Ec2TaskDefinitionProps No description.
volumes aws-cdk-lib.aws_ecs.Volume[] No description.

containersRequired
public readonly containers: ContainerDefinitionOptions[];
  • Type: aws-cdk-lib.aws_ecs.ContainerDefinitionOptions[]

taskDefinitionOptional
public readonly taskDefinition: Ec2TaskDefinitionProps;
  • Type: aws-cdk-lib.aws_ecs.Ec2TaskDefinitionProps

volumesOptional
public readonly volumes: Volume[];
  • Type: aws-cdk-lib.aws_ecs.Volume[]