-
Notifications
You must be signed in to change notification settings - Fork 0
/
grafana.ts
148 lines (127 loc) · 4.55 KB
/
grafana.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
145
146
147
148
import {
aws_cloudfront,
aws_cloudfront_origins,
aws_ec2,
aws_ecs,
aws_ecs_patterns,
aws_iam,
aws_rds,
CfnOutput,
Duration,
} from 'aws-cdk-lib';
import { CachePolicy } from 'aws-cdk-lib/aws-cloudfront';
import { Vpc } from 'aws-cdk-lib/aws-ec2';
import { Construct } from 'constructs';
import * as secretsmanager from 'aws-cdk-lib/aws-secretsmanager';
export interface GrafanaClusterProps {
vpc: Vpc;
cloudFrontPrefixListId: string;
}
export class GrafanaCluster extends Construct {
public readonly serviceSecurityGroup: aws_ec2.SecurityGroup;
constructor(scope: Construct, id: string, props: GrafanaClusterProps) {
super(scope, id);
//Security Groups
const albSecurityGroup = new aws_ec2.SecurityGroup(this, 'alb-sg', {
vpc: props.vpc,
allowAllOutbound: true,
});
albSecurityGroup.addIngressRule(aws_ec2.Peer.prefixList(props.cloudFrontPrefixListId), aws_ec2.Port.tcp(80));
const serviceSecurityGroup = new aws_ec2.SecurityGroup(this, 'service-sg', {
vpc: props.vpc,
allowAllOutbound: true,
});
serviceSecurityGroup.addIngressRule(
aws_ec2.Peer.securityGroupId(albSecurityGroup.securityGroupId),
aws_ec2.Port.tcp(3000),
);
this.serviceSecurityGroup = serviceSecurityGroup;
const rdsSecurityGroup = new aws_ec2.SecurityGroup(this, 'rds-sg', {
vpc: props.vpc,
allowAllOutbound: true,
});
rdsSecurityGroup.addIngressRule(
aws_ec2.Peer.securityGroupId(serviceSecurityGroup.securityGroupId),
aws_ec2.Port.tcp(3306),
);
const rdsPasswordSecret = new secretsmanager.Secret(this, 'rdsSecret', {
generateSecretString: {
excludeCharacters: '/@"',
excludePunctuation: true,
includeSpace: false,
passwordLength: 12,
},
});
//Aurora
const dbUser = 'admin';
const rdsCredential = aws_rds.Credentials.fromPassword(dbUser, rdsPasswordSecret.secretValue);
const aurora = new aws_rds.ServerlessCluster(this, 'aurora', {
engine: aws_rds.DatabaseClusterEngine.AURORA_MYSQL,
vpc: props.vpc,
credentials: rdsCredential,
securityGroups: [rdsSecurityGroup],
defaultDatabaseName: 'grafana',
enableDataApi: true,
});
//Grafana cluster
const cluster = new aws_ecs.Cluster(this, 'Cluster', { vpc: props.vpc });
const image = aws_ecs.ContainerImage.fromRegistry('grafana/grafana-oss:7.5.10');
const logging = new aws_ecs.AwsLogDriver({
streamPrefix: 'grafana',
});
const serviceTaskDefinition = new aws_ecs.FargateTaskDefinition(this, 'GrafanaTaskDefinition', {});
serviceTaskDefinition
.addContainer('GrafanaContainer', {
image,
logging,
environment: {
GF_DATABASE_TYPE: 'mysql',
GF_DATABASE_HOST: aurora.clusterEndpoint.hostname,
GF_DATABASE_USER: rdsCredential.username,
},
secrets: {
GF_DATABASE_PASSWORD: aws_ecs.Secret.fromSecretsManager(rdsPasswordSecret),
},
})
.addPortMappings({
containerPort: 3000,
hostPort: 3000,
});
serviceTaskDefinition.taskRole.attachInlinePolicy(
new aws_iam.Policy(this, 'ecs_task_iam_policy', {
statements: [
new aws_iam.PolicyStatement({
actions: ['secretsmanager:GetSecretValue', 'kms:Decrypt'],
resources: ['*'],
}),
],
}),
);
const fargateService = new aws_ecs_patterns.ApplicationLoadBalancedFargateService(this, 'FargateService', {
cluster,
taskDefinition: serviceTaskDefinition,
securityGroups: [serviceSecurityGroup],
});
fargateService.targetGroup.configureHealthCheck({
path: '/api/health',
});
fargateService.targetGroup.enableCookieStickiness(Duration.seconds(3600), 'grafana_session');
fargateService.loadBalancer.addSecurityGroup(albSecurityGroup);
// CloudFront
const origin = new aws_cloudfront_origins.LoadBalancerV2Origin(fargateService.loadBalancer, {
protocolPolicy: aws_cloudfront.OriginProtocolPolicy.HTTP_ONLY,
});
const distribution = new aws_cloudfront.Distribution(this, 'cloudfront-distribution', {
defaultBehavior: {
cachePolicy: CachePolicy.CACHING_DISABLED,
origin,
originRequestPolicy: aws_cloudfront.OriginRequestPolicy.ALL_VIEWER,
allowedMethods: aws_cloudfront.AllowedMethods.ALLOW_ALL,
viewerProtocolPolicy: aws_cloudfront.ViewerProtocolPolicy.REDIRECT_TO_HTTPS,
},
});
new CfnOutput(this, 'GrafanaUrl', {
value: `https://${distribution.domainName}/`,
});
}
}