Skip to content

Instantly share code, notes, and snippets.

@SaundersB
Created December 14, 2021 00:11
Show Gist options
  • Save SaundersB/b8b95967665babfdb6d82e58a2316887 to your computer and use it in GitHub Desktop.
Save SaundersB/b8b95967665babfdb6d82e58a2316887 to your computer and use it in GitHub Desktop.
CDK Microservice using the same Application Load Balancer v1
import { Construct } from '@aws-cdk/core';
import * as cdk from '@aws-cdk/core';
import * as ec2 from '@aws-cdk/aws-ec2';
import * as ecs from '@aws-cdk/aws-ecs';
import * as ecr from '@aws-cdk/aws-ecr';
import * as elasticloadbalancing from '@aws-cdk/aws-elasticloadbalancingv2';
import { CfnOutput, Duration, RemovalPolicy } from '@aws-cdk/core';
const capitalize = (s: string) => {
return s.charAt(0).toUpperCase() + s.slice(1);
};
export interface ApiProps {
environment: string;
apiName: string;
priority: number;
}
export class Endpoint extends Construct {
constructor(scope: Construct, id: string, props: ApiProps) {
super(scope, id);
const rootStackName = 'your-api';
const applicationNameKabob = `your-endpoints-apis`;
const environment = props.environment;
// Non-PCI Network
const vpc = ec2.Vpc.fromLookup(this, `VPC`, {
vpcId: 'vpc-12345',
});
const port = 8000;
const ecrRepo = new ecr.Repository(this, `ECR`, {
repositoryName: `${props.apiName}-ecr`,
removalPolicy: RemovalPolicy.DESTROY,
imageScanOnPush: true,
lifecycleRules: [
{
tagPrefixList: ['latest'],
maxImageCount: 5,
},
{
maxImageAge: Duration.days(30),
},
],
});
new CfnOutput(this, `EcrRepoUrl`, {
value: ecrRepo.repositoryUri,
});
const clusterName = `${rootStackName}-${environment}-ecs`;
const clusterArn = cdk.Fn.importValue(
`${applicationNameKabob}-${environment}-alb-arn`
);
const cluster = ecs.Cluster.fromClusterAttributes(this, `ECSCluster`, {
clusterName,
vpc,
securityGroups: [],
clusterArn,
});
const securityGroup = ec2.SecurityGroup.fromSecurityGroupId(
this,
'SecurityGroup',
'sg-12345'
);
const listenerArn = cdk.Fn.importValue(
`${rootStackName}-${environment}-alb-listener-arn`
);
const listener =
elasticloadbalancing.ApplicationListener.fromApplicationListenerAttributes(
this,
'AlbListener',
{
listenerArn,
securityGroup,
}
);
const targetGroupHttp = new elasticloadbalancing.ApplicationTargetGroup(
this,
`TargetGroup`,
{
targetGroupName: `${props.apiName.slice(0, 3)}-${environment}-tg`,
port,
vpc,
protocol: elasticloadbalancing.ApplicationProtocol.HTTP,
targetType: elasticloadbalancing.TargetType.IP,
}
);
targetGroupHttp.configureHealthCheck({
path: `/healthcheck`,
protocol: elasticloadbalancing.Protocol.HTTP,
port: `${port}`,
});
const taskDefinition = new ecs.TaskDefinition(
this,
`${capitalize(props.apiName)}ApiTaskDefinion`,
{
family: `${props.apiName}-api-task`,
compatibility: ecs.Compatibility.EC2_AND_FARGATE,
cpu: '256',
memoryMiB: '512',
networkMode: ecs.NetworkMode.AWS_VPC,
}
);
const image = ecs.RepositoryImage.fromEcrRepository(ecrRepo, 'latest');
const container = taskDefinition.addContainer(`Container`, {
image,
memoryLimitMiB: 512,
logging: new ecs.AwsLogDriver({
streamPrefix: `${applicationNameKabob}-${environment}-${props.apiName}-api`,
mode: ecs.AwsLogDriverMode.NON_BLOCKING,
}),
});
container.addPortMappings({ containerPort: port });
const service = new ecs.FargateService(
this,
`${capitalize(props.apiName)}ApiService`,
{
serviceName: `${applicationNameKabob}-${props.apiName}-api-${environment}-service`,
cluster,
desiredCount: 1,
taskDefinition,
}
);
new elasticloadbalancing.ApplicationListenerRule(
this,
(id = `${capitalize(props.apiName)}ApiListenerRule`),
{
listener,
priority: props.priority,
conditions: [
elasticloadbalancing.ListenerCondition.pathPatterns([
`/${props.apiName}*`,
]),
],
targetGroups: [targetGroupHttp],
}
);
service.attachToApplicationTargetGroup(targetGroupHttp);
const scalableTaget = service.autoScaleTaskCount({
minCapacity: 1,
maxCapacity: 5,
});
scalableTaget.scaleOnMemoryUtilization(
`${capitalize(props.apiName)}ScaleUpMem`,
{
targetUtilizationPercent: 75,
}
);
scalableTaget.scaleOnCpuUtilization(
`${capitalize(props.apiName)}ScaleUpCPU`,
{
targetUtilizationPercent: 75,
}
);
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment