Simple auto-scaling for Amazon Lightsail Containers written in Javascript

Overview

About

Amazon Lightsail Containers is one of the easiest way to run container based app on AWS. It automatically sets up a load balanced TLS endpoint, custom DNS, free private image registry and more. But I think it lacks one important feature which is auto scaling. That's why I build this tool.

lightsail-containers-autoscaler support both dynamic scaling and scheduled scaling. The aim of this tool is to be as simple as possible hence it is only consist of single Javascript file src/index.js. You just need to schedule this tool to run in regular interval and it will fetch metrics from the Lightsail Container and do the auto-scaling.

I recommend running this tool using Amazon EventBridge and AWS Lambda so you do not have to maintain any servers.

WARNING: This project is in early development and not many tests has been conducted, use it at your own risk.

Requirements

This tool has been tested using following:

  • Node.js v16.x
  • Serverless Framework 3.21 (Used to deploy to AWS)

How to Install

Clone this repo or download the archive and extract to some directory.

git clone [email protected]:rioastamal/lightsail-containers-autoscaler.git

Install all required dependencies.

cd lightsail-containers-autoscaler
npm install

If you want to deploy to your AWS account, then you need to install Serverless Framework.

npm install -g serverless

How to Deploy

Several resources will be created during deployment such as:

  • Amazon DynamoDB
  • Amazon EventBridge
  • AWS Lambda

This deployment uses Serverless Framework so make sure to edit serverless.yml to suit your needs. Settings that you will likely to edit are functions section.

functions:
  autoscaling:
    handler: src/index.handler
    events:
      - schedule:
          rate: rate(10 minutes)
          enabled: true
          input: 
            name: lightsail-containers-autoscaler
            rules:
            - enabled: true
              dry_run: false
              scaling_type: dynamic
              nodes: 3
              power: nano
              metric: cpu
              average: 20
              average_operator: gte
              average_duration_minutes: 10
              wait_after_last_deployment_minutes: 10
            - enabled: true
              dry_run: false
              scaling_type: dynamic
              nodes: 1
              power: nano
              metric: cpu
              average: 5
              average_operator: lte
              average_duration_minutes: 15
              wait_after_last_deployment_minutes: 30
            - enabled: true
              dry_run: false
              scaling_type: scheduled
              nodes: 2
              power: micro
              run_at: "* * 21 * * *"
              wait_after_last_deployment_minutes: 30

Change schedule.rate to run the function as your required interval. See AWS Schedule Syntax for more details. The next thing you may want to change is input. It takes the same format as input.sample.json but in YAML format.

Make sure you already configure your AWS credentials via ~/.aws or via AWS_* environment variables. To deploy just run:

export AWS_DEFAULT_REGION=ap-southeast-1
export APP_CONTAINER_SVC_NAME=demo-auto
serverless deploy

It will run the Lambda function every 10 minutes and do the auto scaling based on rules matched.

How to Run (local)

To run locally, configure your AWS credentials via ~/.aws or via AWS_* environment variables. Then make sure you have permissions to write to DynamoDB table and Lightsail Container service. Take a look at IAM permissions defined in serverless.yml file.

First, define required environment variables. In this case I am using ap-southeast-1 and demo-auto as example values.

export NODE_ENV=development
export APP_REGION=ap-southeast-1
export APP_TABLE_NAME=ls-containers-autoscaling-$NODE_ENV
export APP_CONTAINER_SVC_NAME=demo-auto
export APP_NO_LAMBDA=true

You can use sample configuration input.sample.json as an input.

cat input.sample.json | node src/index.js

It will scale in/out the container service based on the rule matched.

If you want to simulate particular date then pass APP_CURRENT_DATE environment when running this tool.

cat input.sample.json | APP_CURRENT_DATE=2020-08-08T06:30:00+07:00 node src/index.js

Configuration

Explanation of each attribute on configuration that used in as an input for the function.

Attribute Required Value Description
name Required lightsail-containers-autoscaler Magic identifier
rules Required Array List of rules that need to be applied

Supported attributes for each element on rules.

Attribute Required Value Description
enabled Required true or false Enable or disable the rule
dry_run Required true or false Dry run mode, no update applied to the container service
scaling_type Required dynamic or scheduled dynamic is based on metrics and scheduled is based on date/interval
nodes Required Number Number of nodes. Max is 20
power Required String Name of the power (CPU and RAM)
metric Required (dynamic) cpu or memory Metric to monitor, CPU or Memory
average Required (dynamic) Number Average percentage of the container service at given last average_duration_minutes minutes
average_operator Required (dynamic) lte or gte Comparison operator. lte (less than equal) and gte (greater than equal)
average_duration_minutes Required (dynamic) Number Duration of the metric to get. E.g: 10 means it will get average metric (cpu or memory) for the last 10 minutes
wait_after_last_deployment_minutes Required Number Waiting time before doing another scaling. It will not do the scaling when the deployment still under wait_after_last_deployment_minutes
run_at Required (scheduled) Cron Expression Run scaling at specified interval using cron expression, e.g: * * 19 * * * means run auto scaling every 7pm.

Sample 1

  1. Do scale out to 4 nodes and power to micro when average CPU metric is above 70 percent for the last 15 minutes. Only do scaling if last deployment is more than 10 minutes ago.
  2. Do Scale in 1 node and power to nano when average CPU metric is below 5 percent for the last 45 minutes. Only do scaling if last deployment is more than 30 minutes ago.
{
  "name": "lightsail-containers-autoscaler",
  "rules": [
    {
      "enabled": true,
      "dry_run": false,
      "scaling_type": "dynamic",
      "nodes": 4,
      "power": "micro",
      "metric": "cpu",
      "average": 70.0,
      "average_operator": "gte",
      "average_duration_minutes": 15,
      "wait_after_last_deployment_minutes": 10
    },
    {
      "enabled": true,
      "dry_run": false,
      "scaling_type": "dynamic",
      "nodes": 1,
      "power": "nano",
      "metric": "cpu",
      "average": 5.0,
      "average_operator": "lte",
      "average_duration_minutes": 15,
      "wait_after_last_deployment_minutes": 30
    }
  ]
}

Sample 2

  1. Do scale out to 6 nodes and power to micro every Monday to Friday at 8am to 4pm. Only do scaling if last deployment is more than 10 minutes ago.
  2. Do scale in to 1 node and power to nano every Monday to Friday at 5pm to 7am. Only do scaling if last deployment is more than 30 minutes ago.
  3. Do scale in to 1 node and power to nano every weekend. Only do scaling if last deployment is more than 30 minutes ago.
{
  "name": "lightsail-containers-autoscaler",
  "rules": [
    {
      "enabled": true,
      "dry_run": false,
      "scaling_type": "scheduled",
      "nodes": 6,
      "power": "micro",
      "run_at": "* 0-59 8-16 * * 1-5",
      "wait_after_last_deployment_minutes": 10
    },
    {
      "enabled": true,
      "dry_run": false,
      "scaling_type": "scheduled",
      "nodes": 1,
      "power": "nano",
      "run_at": "0-59 0-7,17-23 * * 1-5",
      "wait_after_last_deployment_minutes": 30
    },
    {
      "enabled": true,
      "dry_run": false,
      "scaling_type": "scheduled",
      "nodes": 1,
      "power": "nano",
      "run_at": "* * * * 0,6",
      "wait_after_last_deployment_minutes": 30
    },
  ]
}

To do

  • Add unit tests
  • Improve documentation

Contributing

Fork this repo and send me a Pull Request (PR).

License

This project is licensed under MIT License. See LICENSE file.

You might also like...

Running webdriverio in docker containers so you can easily add tests to your CI.

WebDriverIO tests in Docker Running WebdriverIO tests in a docker container allows you to easily add tests to your CI. About This project uses the aut

Dec 3, 2022

⛴ Manage Docker containers from the menu bar.

⛴ Manage Docker containers from the menu bar.

Captain INTRODUCTION Manage Docker containers. Instantly from the menu bar. See which containers are running and which have stopped. Conveniently star

Dec 8, 2022

Multi-chain defi crypto sniper written in typescript/javascript. Fastest method of sniping with auto-sell and rug prevention features.

Multi-chain defi crypto sniper written in typescript/javascript. Fastest method of sniping with auto-sell and rug prevention features.

CryptoSniper Community Edition Multi-chain defi crypto sniper written in typescript/javascript. Fastest method of sniping with auto-sell and rug preve

Nov 3, 2022

A website made using ReactJS library which displays all the best selling books of 2021 and a feature to check them on amazon.

Getting Started with Create React App This project was bootstrapped with Create React App. Available Scripts In the project directory, you can run: np

Dec 30, 2021

This is an imitation of the Amazon online shopping store. Users can add and remove items from the cart, proceed to checkout and make payments.

AMAZON This is an imitation of the Amazon online shopping store. Users can add and remove items from the cart, proceed to checkout and make payments.

Mar 23, 2022

How to implement Step-up Authentication using Amazon Cognito

How to implement Step-up Authentication using Amazon Cognito

How to implement Step-up Authentication using Amazon Cognito This repository contains accompanying source code for the AWS Blog post, How to implement

Dec 15, 2022

This is a decentralized Amazon clone, built on the blockchain

The project is a Decentralized version of Amazon, built on the blockchain. Which gives users the ability to purchase and sell items without the involv

Jun 27, 2022

It shows an effective way to correct bus arrival information using data analytics based on Amazon Serverless such as Kiness Data Stream, Kinesis Data Firehose, S3, and Lambda.

It shows an effective way to correct bus arrival information using data analytics based on Amazon Serverless such as Kiness Data Stream, Kinesis Data Firehose, S3, and Lambda.

Amazon Serverless를 이용한 실시간 버스 정보 수집 및 저장 본 github repository는 버스 정보를 주기적으로 수집하여 분석할 수 있도록, Amazon Serverless인 Amazon Kinesis Data Stream, Kinesis Data

Nov 13, 2022

A small web app that tries to imitate the desktop web version of amazon site, you can add items to the basket, delete them, and have your user authentication feature thanks to Firebase.

A small web app that tries to imitate the desktop web version of amazon site, you can add items to the basket, delete them, and have your user authentication feature thanks to Firebase.

Features Here's the feature's included in this project 👨‍👩‍👧‍👦 Login Page 📦 Products Page 🛒 Cart and Checkout Page 📝 Sign up function with Goog

Aug 22, 2022
Owner
Rio Astamal
A passionate web developer since 2003. Currently work at @AWS as Developer Advocate for Indonesia. Opinions and codes are my own.
Rio Astamal
Grupprojekt för kurserna 'Javascript med Ramverk' och 'Agil Utveckling'

JavaScript-med-Ramverk-Laboration-3 Grupprojektet för kurserna Javascript med Ramverk och Agil Utveckling. Utvecklingsguide För information om hur utv

Svante Jonsson IT-Högskolan 3 May 18, 2022
Hemsida för personer i Sverige som kan och vill erbjuda boende till människor på flykt

Getting Started with Create React App This project was bootstrapped with Create React App. Available Scripts In the project directory, you can run: np

null 4 May 3, 2022
Kurs-repo för kursen Webbserver och Databaser

Webbserver och databaser This repository is meant for CME students to access exercises and codealongs that happen throughout the course. I hope you wi

null 14 Jan 3, 2023
🧰 Javascript array-like containers for multithreading

بسم الله الرحمن الرحيم Struct Vec ?? Javascript array-like containers for multithreading Efficiently communicating between js workers is a pain becaus

Mostafa Elbannan 19 Jun 23, 2022
Personal Blog - a project developed with Angular for the front-end interface and Wordpress for the back-end API served with Docker containers

PersonalBlog This project was generated with Angular CLI version 13.0.1. Front-end Interface Development server Run ng serve or ng serve --configurati

null 9 Oct 5, 2022
A Restaurant (Table) Reservation API built with Node, TypeScript, Express, TypeORM, a MySQL DB, all running on Docker containers

Restaurant (Table) Reservation API A simple API for reserving tables at a restaurant. The API is based on the REST architectural style and uses Node.j

null 14 Oct 5, 2022
Docker: Criando containers sem dor de cabeça.

Docker: Criando containers sem dor de cabeça. A evolução do host de aplicações Antigamente... Várias aplicações, vários servidores. Capacidade pouco a

Lucas Magalhães 3 Jun 23, 2022
A Restaurant (Table) Reservation API built with Node, TypeScript, Express, TypeORM, a MySQL DB, all running on Docker containers

Restaurant (Table) Reservation API A simple API for reserving tables at a restaurant. The API is based on the REST architectural style and uses Node.j

null 14 Oct 5, 2022
Customizable browser's home page to interact with your homeserver's Docker containers (e.g. Sonarr/Radarr)

Homarr A homepage for your server. Demo ↗️ • Install ➡️ Join the discord! ?? Table of Contents ?? Table of Contents ?? Getting Started ℹ️ About ?? Kno

Thomas Camlong 1.6k Jan 7, 2023
Govinor is a platform to deploy and preview docker containers.

Govinor A platform for creating and managing Docker containers that integrates with Github to offer branch preview links. Note: This is a work in prog

iFixit 2 Jan 10, 2022