Skip to content

Commit

Permalink
feat(celery): add elasticache, celery worker and celery beat constructs
Browse files Browse the repository at this point in the history
  • Loading branch information
Brian Caffey committed May 14, 2021
1 parent c1c1a49 commit 634b268
Show file tree
Hide file tree
Showing 5 changed files with 145 additions and 14 deletions.
42 changes: 42 additions & 0 deletions src/celery/beat/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
import * as ecs from '@aws-cdk/aws-ecs';
import * as logs from '@aws-cdk/aws-logs';
import * as cdk from '@aws-cdk/core';

export interface CeleryBeatProps {
readonly image: ecs.ContainerImage;
readonly command: string[];
readonly environment: { [key: string]: string };
readonly cluster: ecs.ICluster;
}

export class CeleryBeat extends cdk.Construct {
constructor(scope: cdk.Construct, id: string, props: CeleryBeatProps) {
super(scope, id);


const taskDefinition = new ecs.TaskDefinition(scope, `TaskDefinitionFor${id}`, {
compatibility: ecs.Compatibility.FARGATE,
cpu: '256',
memoryMiB: '512',
});

taskDefinition.addContainer(`TaskContainerFor${id}`, {
image: props.image,
command: props.command,
environment: props.environment,
logging: ecs.LogDriver.awsLogs(
{
logRetention: logs.RetentionDays.ONE_DAY,
streamPrefix: `${id}Container`,
},
),
});

new ecs.FargateService(scope, `FargateService${id}`, {
cluster: props.cluster,
taskDefinition,
// only run one instance of celery beat
desiredCount: 1,
});
}
}
2 changes: 2 additions & 0 deletions src/celery/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
export * from './beat';
export * from './worker';
43 changes: 43 additions & 0 deletions src/celery/worker/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
import * as ecs from '@aws-cdk/aws-ecs';
import * as logs from '@aws-cdk/aws-logs';
import * as cdk from '@aws-cdk/core';

export interface CeleryWorkerProps {
readonly image: ecs.ContainerImage;
readonly command: string[];
readonly environment: { [key: string]: string };
readonly cluster: ecs.ICluster;
}

export class CeleryWorker extends cdk.Construct {
constructor(scope: cdk.Construct, id: string, props: CeleryWorkerProps) {
super(scope, id);


const taskDefinition = new ecs.TaskDefinition(scope, `TaskDefinitionFor${id}`, {
compatibility: ecs.Compatibility.FARGATE,
cpu: '256',
memoryMiB: '512',
});

taskDefinition.addContainer(`TaskContainerFor${id}`, {
image: props.image,
command: props.command,
environment: props.environment,
logging: ecs.LogDriver.awsLogs(
{
logRetention: logs.RetentionDays.ONE_DAY,
streamPrefix: `${id}Container`,
},
),
});

new ecs.FargateService(scope, `FargateService${id}`, {
cluster: props.cluster,
taskDefinition,
desiredCount: 1,
});

// TODO: scaling options
}
}
31 changes: 17 additions & 14 deletions src/django-cdk.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import * as s3 from '@aws-cdk/aws-s3';
import * as secretsmanager from '@aws-cdk/aws-secretsmanager';
import * as cdk from '@aws-cdk/core';
import { RdsPostgresInstance } from './database';
import { ElastiCacheCluster } from './elasticache';
import { managementCommandTask } from './tasks';
import { ApplicationVpc } from './vpc';

Expand Down Expand Up @@ -86,12 +87,27 @@ export class DjangoCdk extends cdk.Construct {
secret: this.secret,
});


/**
* A security group in the VPC for our application (ECS Fargate services and tasks)
* Allow the application services to access the RDS security group
*/
const appSecurityGroup = new ec2.SecurityGroup(scope, 'appSecurityGroup', {
vpc: this.vpc,
});

const elastiCacheRedis = new ElastiCacheCluster(scope, 'ElastiCacheCluster', {
vpc: this.vpc,
appSecurityGroup,
});

const environment: { [key: string]: string } = {
AWS_STORAGE_BUCKET_NAME: staticFilesBucket.bucketName,
POSTGRES_SERVICE_HOST: database.rdsPostgresInstance.dbInstanceEndpointAddress,
POSTGRES_PASSWORD: this.secret.secretValue.toString(),
DEBUG: '0',
DJANGO_SETTINGS_MODULE: 'backend.settings.production',
REDIS_SERVICE_HOST: elastiCacheRedis.elastiCacheCluster.attrRedisEndpointAddress,
};

taskDefinition.addContainer('backendContainer', {
Expand All @@ -110,19 +126,6 @@ export class DjangoCdk extends cdk.Construct {
),
});

// container.addPortMappings({
// containerPort: 8000,
// protocol: ecs.Protocol.TCP,
// });

/**
* A security group in the VPC for our application (ECS Fargate services and tasks)
* Allow the application services to access the RDS security group
*/
const appSecurityGroup = new ec2.SecurityGroup(scope, 'appSecurityGroup', {
vpc: this.vpc,
});

new managementCommandTask(scope, 'migrate', {
image: this.image,
command: ['python3', 'manage.py', 'migrate', '--no-input'],
Expand Down Expand Up @@ -160,7 +163,7 @@ export class DjangoCdk extends cdk.Construct {
});

/**
* Allows the app security group to communicate with the database security group
* Allows the app security group to communicate with the RDS security group
*/
database.rdsSecurityGroup.addIngressRule(appSecurityGroup, ec2.Port.tcp(5432));

Expand Down
41 changes: 41 additions & 0 deletions src/elasticache/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
import { Port, SecurityGroup, SubnetType, IVpc } from '@aws-cdk/aws-ec2';
import { CfnCacheCluster, CfnSubnetGroup } from '@aws-cdk/aws-elasticache';
import * as cdk from '@aws-cdk/core';

export interface ElastiCacheRedisProps {
vpc: IVpc;
appSecurityGroup: SecurityGroup;
}

export class ElastiCacheCluster extends cdk.Construct {
readonly elastiCacheCluster: CfnCacheCluster;
readonly elastiCacheClusterSecurityGroup: SecurityGroup;
constructor(scope: cdk.Construct, id: string, props: ElastiCacheRedisProps) {
super(scope, id);

const elastiCacheClusterSecurityGroup = new SecurityGroup(scope, 'ElastiCacheSecurityGroup', {
vpc: props.vpc,
description: 'ElastiCache Security Group',
});
this.elastiCacheClusterSecurityGroup = elastiCacheClusterSecurityGroup;

const elastiCacheClusterSubnetGroup = new CfnSubnetGroup(scope, 'ElastiCacheRedisSubnetGroup', {
subnetIds: props.vpc.selectSubnets({
subnetType: SubnetType.ISOLATED,
}).subnetIds,
description: 'ElastiCache Subnet Group',
});

this.elastiCacheCluster = new CfnCacheCluster(this, 'ElastiCacheCluster', {
clusterName: `${id}-elstiCacheCluster`,
cacheNodeType: 'cache.t2.micro',
engine: 'redis',
numCacheNodes: 1,
vpcSecurityGroupIds: [elastiCacheClusterSecurityGroup.securityGroupId],
cacheSubnetGroupName: elastiCacheClusterSubnetGroup.ref,
});

this.elastiCacheCluster.addDependsOn(elastiCacheClusterSubnetGroup);
elastiCacheClusterSecurityGroup.connections.allowFrom(props.appSecurityGroup, Port.tcp(6379));
}
}

0 comments on commit 634b268

Please sign in to comment.