Home > database >  Best way to accomplish _single_ instance container CI/CD on AWS?
Best way to accomplish _single_ instance container CI/CD on AWS?

Time:08-16

My goal is to have an AWS code commit repo, that on push to main branch will run a code pipeline CI/CD process to deploy a single node app to AWS.

I went through the setup to get this working with fargate via CDK using enter image description here

The load balancer has only one target. There is no requirement that the load balancer should have a target in each zone.

enter image description here

I put everything in the public VPC zone because I do not have NAT. You might want to have your Fargate tasks in the private zone for better security.

I added the health check path with default values because, most likely, you will want to define a custom URL for your service. We can omit the default definition.

import { App, RemovalPolicy, Stack } from 'aws-cdk-lib'
import { Certificate, CertificateValidation } from 'aws-cdk-lib/aws-certificatemanager'
import { Vpc } from 'aws-cdk-lib/aws-ec2'
import { Cluster, ContainerImage, LogDriver } from 'aws-cdk-lib/aws-ecs'
import { ApplicationLoadBalancedFargateService } from 'aws-cdk-lib/aws-ecs-patterns'
import { ApplicationProtocol } from 'aws-cdk-lib/aws-elasticloadbalancingv2'
import { LogGroup } from 'aws-cdk-lib/aws-logs'
import { HostedZone } from 'aws-cdk-lib/aws-route53'
import { env } from 'process'

function createStack (scope, id, props) {
  const stack = new Stack(scope, id, props)

  const logGroup = new LogGroup(stack, 'LogGroup', { logGroupName: 'so-service', removalPolicy: RemovalPolicy.DESTROY })

  const vpc = Vpc.fromLookup(stack, 'Vpc', { vpcName: 'BlogVpc' })

  const domainZone = HostedZone.fromLookup(stack, 'ZonePublic', { domainName: 'victorsmirnov.blog' })

  const domainName = 'service.victorsmirnov.blog'
  const certificate = new Certificate(stack, 'SslCertificate', {
    domainName,
    validation: CertificateValidation.fromDns(domainZone)
  })

  const cluster = new Cluster(stack, 'Cluster', {
    clusterName: 'so-cluster',
    containerInsights: true,
    enableFargateCapacityProviders: true,
    vpc,
  })

  const service = new ApplicationLoadBalancedFargateService(stack, id, {
    assignPublicIp: true,
    certificate,
    cluster,
    cpu: 256,
    desiredCount: 1,
    domainName,
    domainZone,
    memoryLimitMiB: 512,
    openListener: true,
    protocol: ApplicationProtocol.HTTPS,
    publicLoadBalancer: true,
    redirectHTTP: true,
    targetProtocol: ApplicationProtocol.HTTP,
    taskImageOptions: {
      containerName: 'nginx',
      containerPort: 80,
      enableLogging: true,
      family: 'so-service',
      image: ContainerImage.fromRegistry('nginx'),
      logDriver: LogDriver.awsLogs({ streamPrefix: 'nginx', logGroup })
    }
  })

  service.targetGroup.configureHealthCheck({
    path: '/',
  })

  return stack
}

const app = new App()
createStack(app, 'SingleInstanceAlbService', {
  env: { account: env.CDK_DEFAULT_ACCOUNT, region: env.CDK_DEFAULT_REGION }
})

Content for the cdk.json and package.json for completeness.

{
    "app": "node question.js",
    "context": {
        "@aws-cdk/core:newStyleStackSynthesis": true
    }
}
{
    "name": "alb-single-instance",
    "version": "0.1.0",
    "dependencies": {
        "aws-cdk-lib": "^2.37.1",
        "cdk": "^2.37.1",
        "constructs": "^10.1.76"
    },
    "devDependencies": {
        "rimraf": "^3.0.2",
        "snazzy": "^9.0.0",
        "standard": "^17.0.0"
    },
    "scripts": {
        "cdk": "cdk",
        "clean": "rimraf cdk.out dist",
        "format": "standard --fix --verbose | snazzy",
        "test": "standard --verbose | snazzy"
    },
    "type": "module"
}

This should be enough to have a fully functional setup where everything is configured automatically using the CDK.

Maybe you do not need the load balancer because there is no need to balance traffic for only one task. You can set up the Service discovery for your service and use the DNS name for your task without a load balancer. This should save money if you want.

CodePudding user response:

Your application can still be in one AZ. The fact that ALB requires two AZs is only related to ALB itself. So you do not have to create any extra instance of your application in other AZ if you don't want. Though it could be a good idea for high-availability.

  • Related