-
Notifications
You must be signed in to change notification settings - Fork 0
/
redis-stack.ts
144 lines (122 loc) · 4.87 KB
/
redis-stack.ts
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
import * as cdk from 'aws-cdk-lib';
import { Construct } from 'constructs';
import * as ec2 from 'aws-cdk-lib/aws-ec2';
import * as elasticache from 'aws-cdk-lib/aws-elasticache';
import * as lambda from 'aws-cdk-lib/aws-lambda';
import * as kinesis from 'aws-cdk-lib/aws-kinesis';
import * as firehose from 'aws-cdk-lib/aws-kinesisfirehose';
import * as s3 from 'aws-cdk-lib/aws-s3';
import * as iam from 'aws-cdk-lib/aws-iam';
import * as lambdaEventSources from 'aws-cdk-lib/aws-lambda-event-sources';
export class RedisStack extends cdk.Stack {
constructor(scope: Construct, id: string, props?: cdk.StackProps) {
super(scope, id, props);
// Create VPC And manage security group and Inbound Rules
const vpc = new ec2.Vpc(this, 'RedisVPC', {
ipAddresses: ec2.IpAddresses.cidr('10.0.0.0/16'),
maxAzs: 2,
natGateways: 1,
subnetConfiguration: [
{
cidrMask: 24,
name: 'RedisPublic',
subnetType: ec2.SubnetType.PUBLIC,
},
{
cidrMask: 24,
name: 'RedisPrivate',
subnetType: ec2.SubnetType.PRIVATE_WITH_EGRESS,
},
],
});
const redisSecurityGroup = new ec2.SecurityGroup(this, 'RedisSecurityGroup', {
vpc,
securityGroupName: 'RedisSecurityGroup',
description: 'Redis Security Group',
allowAllOutbound: true,
});
const computeSecurityGroup = new ec2.SecurityGroup(this, 'ComputeSecurityGroup', {
vpc,
securityGroupName: 'ComputeSecurityGroup',
description: 'Compute Security Group',
allowAllOutbound: true,
});
const privateSubnetIds = vpc.selectSubnets({
subnetType: ec2.SubnetType.PRIVATE_WITH_EGRESS,
}).subnetIds;
const redisSubnetGroup = new elasticache.CfnSubnetGroup(this, 'RedisSubnetGroup', {
description: 'Redis Subnet Group',
subnetIds: privateSubnetIds,
});
redisSecurityGroup.addIngressRule(computeSecurityGroup, ec2.Port.tcp(6379), 'Allow Redis Port 6379');
// Create the redis cluster
const redisCluster = new elasticache.CfnCacheCluster(this, 'RedisCluster', {
cacheNodeType: 'cache.t4g.medium',
engine: 'redis',
numCacheNodes: 1,
cacheSubnetGroupName: redisSubnetGroup.ref,
vpcSecurityGroupIds: [redisSecurityGroup.securityGroupId],
});
new cdk.CfnOutput(this, 'RedisClusterEndpoint', {
value: redisCluster.attrRedisEndpointAddress,
});
const bucketForFirehose = new s3.Bucket(this, 'BucketForFirehose', {
bucketName: 'redis-stream',
removalPolicy: cdk.RemovalPolicy.DESTROY,
encryption: s3.BucketEncryption.S3_MANAGED,
});
// Create the firehose delivery with lambda as source with direct put
const firehoseDeliveryRole = new iam.Role(this, 'FirehoseDeliveryRole', {
assumedBy: new iam.ServicePrincipal('firehose.amazonaws.com'),
});
bucketForFirehose.grantReadWrite(firehoseDeliveryRole);
const firehoseDeliveryStream = new firehose.CfnDeliveryStream(this, 'FirehoseDeliveryStreamForRedisProject', {
deliveryStreamName: 'FirehoseDeliveryStreamForRedisProject',
deliveryStreamType: 'DirectPut',
s3DestinationConfiguration: {
bucketArn: bucketForFirehose.bucketArn,
roleArn: firehoseDeliveryRole.roleArn,
cloudWatchLoggingOptions: {
enabled: true,
logGroupName: 'FirehoseDeliveryStreamForRedisProject',
logStreamName: 'FirehoseDeliveryStreamForRedisProject',
},
},
});
// Create lambda with access to redis cluster
const lambdaFunction = new lambda.Function(this, 'LocationProcessor', {
runtime: lambda.Runtime.NODEJS_20_X,
code: lambda.Code.fromAsset('lambda'),
handler: 'index.handler',
vpc,
vpcSubnets: {
subnetType: ec2.SubnetType.PRIVATE_WITH_EGRESS,
},
securityGroups: [computeSecurityGroup],
environment: {
REDIS_HOST: redisCluster.attrRedisEndpointAddress,
REDIS_PORT: redisCluster.attrRedisEndpointPort,
KINESIS_FIREHOSE_NAME: firehoseDeliveryStream.ref,
},
timeout: cdk.Duration.seconds(10),
});
const kinesisIngressStream = new kinesis.Stream(this, 'KinesisIngressStream', {
streamName: 'KinesisIngressStream',
shardCount: 1,
});
new cdk.CfnOutput(this, 'KinesisIngressStreamName', {
value: kinesisIngressStream.streamName,
});
kinesisIngressStream.grantRead(lambdaFunction);
const eventSource = new lambdaEventSources.KinesisEventSource(kinesisIngressStream, {
startingPosition: lambda.StartingPosition.TRIM_HORIZON,
});
lambdaFunction.addEventSource(eventSource);
const firehosePutPolicy = new iam.PolicyStatement({
effect: iam.Effect.ALLOW,
actions: ['firehose:PutRecord', 'firehose:PutRecordBatch'],
resources: [firehoseDeliveryStream.attrArn],
});
lambdaFunction.addToRolePolicy(firehosePutPolicy);
}
}