6

Autoscaling using Spot Instances with AWS CDK + TS

 1 year ago
source link: https://dev.to/aws-builders/autoscaling-using-spot-instances-with-aws-cdk-ts-4hgh
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.
neoserver,ios ssh client

4 1 1 1 1

 

Autoscaling using Spot Instances with AWS CDK + TS

If you’re a developer (like me xD), you know the value of running applications in the cloud—the ability to scale up and down with ease, the opportunity to test your app anywhere, and the ability to pay for resources as needed.

AWS EC2 Spot Instances are the best of both worlds—they're just like regular EC2 instances, except you don't need to pay for them up front, and they're cheaper than regular instances.

The main advantage to spot instances is that you only pay when you use them (rather than paying an upfront fee). But with spot instances, you also get more flexibility—you can move them around pretty easily, which means they work out as a great option for short-term projects or testing. In general, if your project isn't going to last longer than a few weeks or months, and you're not concerned with having access to all the features of your regular instance type (such as the ability to scale it up), then this is probably the best way to go!

If you want to know more about spot instances please take a look into this awesome blog post.

Let's get your hands dirty!

giphy.gif%3Fcid%3Decf05e47jfhbqm90uca8d5qx9s6etjayg9t975rew3st3unz%26rid%3Dgiphy.gif%26ct%3Dg

Our Architecture:

a vpc with ALB and autoscaling with spot instances

Let's start creating our vpc, piece of cake public and private subnets.

import { IVpc, SubnetType, Vpc } from "aws-cdk-lib/aws-ec2";
import { Construct } from "constructs";

export default class DefaultVpc extends Construct {
  public readonly vpc: IVpc;
  constructor(scope: Construct, id: string) {
    super(scope, id);
    this.vpc = new Vpc(this, "my-vpc", {
      cidr: "10.0.0.1/24",
      subnetConfiguration: [
        {
          cidrMask: 28,
          name: "public subnet",
          subnetType: SubnetType.PUBLIC,
        },
        {
          cidrMask: 28,
          name: "private subnet",
          subnetType: SubnetType.PRIVATE_WITH_NAT,
        },
      ],
    });
  }
}

Application Load Balancer

In this step we need to create an internet facing load balancer

import { AutoScalingGroup } from "aws-cdk-lib/aws-autoscaling";
import { IVpc } from "aws-cdk-lib/aws-ec2";
import { ApplicationLoadBalancer } from "aws-cdk-lib/aws-elasticloadbalancingv2";
import { Construct } from "constructs";

export default class InternetFacingApplicationLoadBalancer extends Construct {
  constructor(scope: Construct, id: string, resources: { vpc: IVpc, ec2AutoScalingGroup: AutoScalingGroup }) {
    super(scope, id);

    const loadBalancer = new ApplicationLoadBalancer(this, "appLoadBalancer", {
      vpc: resources.vpc,
      internetFacing: true,
    });

    const httpListener = loadBalancer.addListener("httpListener", {
      port: 80,
      open: true,
    });

    httpListener.addTargets('ApplicationSpotFleet', {
        port: 8080,
        targets: [resources.ec2AutoScalingGroup],
    });
  }
}

AutoScaling Group

Now we create the autoscaling, ec2 instances and the wonderful decision to use spot instances.
We are using t4g.micro instances with latest Amazon Linux images. We are allowing all outbound traffic and the desired capacity of instances is one, while the maximum is 2.
Maximum spot price is set to 0.007, if the sport price goes up, for example to 0.008, then we have no instances at all. There are ways to address this, but for this example I'll only use in this way.

import { Duration } from "aws-cdk-lib";
import { AutoScalingGroup, HealthCheck } from "aws-cdk-lib/aws-autoscaling";
import {
  AmazonLinuxGeneration,
  AmazonLinuxImage,
  InstanceClass,
  InstanceSize,
  InstanceType,
  IVpc,
} from "aws-cdk-lib/aws-ec2";
import { Construct } from "constructs";

export default class ApplicationAutoScalingGroup extends Construct {
  public readonly autoScalingGroup: AutoScalingGroup;
  constructor(
    scope: Construct,
    id: string,
    resources: { vpc: IVpc }
  ) {
    super(scope, id);

    const applicationAutoScalingGroup = new AutoScalingGroup(this, "AutoScalingGroup", {
      vpc: resources.vpc,
      instanceType: InstanceType.of(
        InstanceClass.BURSTABLE4_GRAVITON,
        InstanceSize.MICRO
      ),
      machineImage: new AmazonLinuxImage({
        generation: AmazonLinuxGeneration.AMAZON_LINUX_2,
      }),
      allowAllOutbound: true,
      maxCapacity: 2,
      minCapacity: 1,
      desiredCapacity: 1,
      spotPrice: "0.007", // $0.0032 per Hour when writing, $0.0084 per Hour on-demand
      healthCheck: HealthCheck.ec2(),
    });

    applicationAutoScalingGroup.scaleOnCpuUtilization("CpuScaling", {
        targetUtilizationPercent: 50,
        cooldown: Duration.minutes(1),
        estimatedInstanceWarmup: Duration.minutes(1),
    });

    this.autoScalingGroup = applicationAutoScalingGroup;
  }
}

Finally our stack will be something like that:

Stack

import { StackProps, Environment, Stack } from 'aws-cdk-lib'
import { Construct } from 'constructs'
import InternetFacingApplicationLoadBalancer from '../lib/application-load-balancer/internet-facing-application-load-balancer'
import ApplicationAutoScalingGroup from '../lib/ec2/auto-scaling-group'
import DefaultVpc from '../lib/vpc/default-vpc'

export interface IStackProps extends StackProps {
  variables?: any
  env: Environment
}

export class ApplicationIntegrationStack extends Stack {
  constructor(scope: Construct, id: string, props: IStackProps) {
    super(scope, id, props)

    const { vpc } = new DefaultVpc(this, 'DefaultVpc')
    const { autoScalingGroup } = new ApplicationAutoScalingGroup(this, 'ApplicationAutoScalingGroup', { vpc })
    new InternetFacingApplicationLoadBalancer(this, 'InternetFacingApplicationLoadBalancer', { vpc, ec2AutoScalingGroup: autoScalingGroup })
  }
}

If you want to take a deep dive into this topic I strongly recommends this re:invent video about spot instances.

That's all folks!

giphy.gif%3Fcid%3Decf05e47jr6zifs1e237bpm4nr8mtc8t8xmyr62ufee6z6px%26rid%3Dgiphy.gif%26ct%3Dg

About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK