1
- import { ApplicationLoadBalancedCodeDeployedFargateService } from '@cdklabs/cdk-ecs-codedeploy' ;
2
- import { CfnOutput , Duration , RemovalPolicy , Stack , StackProps } from 'aws-cdk-lib' ;
3
- import { EcsDeploymentConfig , IEcsDeploymentConfig } from 'aws-cdk-lib/aws-codedeploy' ;
1
+ import {
2
+ CfnOutput ,
3
+ Duration ,
4
+ RemovalPolicy ,
5
+ Stack ,
6
+ StackProps ,
7
+ } from 'aws-cdk-lib' ;
8
+ import {
9
+ IEcsDeploymentConfig ,
10
+ EcsDeploymentConfig ,
11
+ } from 'aws-cdk-lib/aws-codedeploy' ;
4
12
import * as ec2 from 'aws-cdk-lib/aws-ec2' ;
5
- import { FlowLog , FlowLogResourceType , Port } from 'aws-cdk-lib/aws-ec2' ;
6
- import * as ecs from 'aws-cdk-lib/aws-ecs' ;
13
+ import { FlowLog , FlowLogResourceType } from 'aws-cdk-lib/aws-ec2' ;
7
14
import { AssetImage , AwsLogDriver , Secret } from 'aws-cdk-lib/aws-ecs' ;
8
15
import { PolicyStatement } from 'aws-cdk-lib/aws-iam' ;
9
16
import { LogGroup , RetentionDays } from 'aws-cdk-lib/aws-logs' ;
10
- import { Credentials , DatabaseClusterEngine , DatabaseSecret , ServerlessCluster } from 'aws-cdk-lib/aws-rds' ;
17
+ import {
18
+ AuroraMysqlEngineVersion ,
19
+ ClusterInstance ,
20
+ Credentials ,
21
+ DatabaseCluster ,
22
+ DatabaseClusterEngine ,
23
+ DatabaseSecret ,
24
+ } from 'aws-cdk-lib/aws-rds' ;
11
25
import { Construct } from 'constructs' ;
26
+ import { ApplicationLoadBalancedCodeDeployedFargateService } from '@cdklabs/cdk-ecs-codedeploy' ;
27
+ import * as ecs from 'aws-cdk-lib/aws-ecs' ;
12
28
13
29
export interface DeploymentProps extends StackProps {
14
30
deploymentConfigName ?: string ;
@@ -24,25 +40,35 @@ export class DeploymentStack extends Stack {
24
40
25
41
const image = new AssetImage ( '.' , { target : 'build' } ) ;
26
42
27
- const appName = Stack . of ( this ) . stackName . toLowerCase ( ) . replace ( `-${ Stack . of ( this ) . region } -` , '-' ) ;
43
+ const appName = Stack . of ( this )
44
+ . stackName . toLowerCase ( )
45
+ . replace ( `-${ Stack . of ( this ) . region } -` , '-' ) ;
28
46
const vpc = new ec2 . Vpc ( this , 'Vpc' , {
29
47
maxAzs : 3 ,
30
48
natGateways : props ?. natGateways ,
31
49
} ) ;
32
- new FlowLog ( this , 'VpcFlowLog' , { resourceType : FlowLogResourceType . fromVpc ( vpc ) } ) ;
50
+ new FlowLog ( this , 'VpcFlowLog' , {
51
+ resourceType : FlowLogResourceType . fromVpc ( vpc ) ,
52
+ } ) ;
33
53
34
54
const dbName = 'fruits' ;
35
55
const dbSecret = new DatabaseSecret ( this , 'AuroraSecret' , {
36
56
username : 'fruitapi' ,
37
57
secretName : `${ appName } -DB` ,
38
58
} ) ;
39
- const db = new ServerlessCluster ( this , 'AuroraCluster' , {
40
- engine : DatabaseClusterEngine . AURORA_MYSQL ,
41
- vpc,
59
+
60
+ const db = new DatabaseCluster ( this , 'Database' , {
61
+ engine : DatabaseClusterEngine . auroraMysql ( {
62
+ version : AuroraMysqlEngineVersion . VER_3_07_1 ,
63
+ } ) ,
42
64
credentials : Credentials . fromSecret ( dbSecret ) ,
65
+ writer : ClusterInstance . serverlessV2 ( 'writer' ) ,
43
66
defaultDatabaseName : dbName ,
44
- deletionProtection : false ,
67
+ serverlessV2MaxCapacity : 2 ,
68
+ serverlessV2MinCapacity : 0.5 ,
69
+ vpc,
45
70
clusterIdentifier : appName ,
71
+ storageEncrypted : true ,
46
72
} ) ;
47
73
48
74
const cluster = new ecs . Cluster ( this , 'Cluster' , {
@@ -57,64 +83,86 @@ export class DeploymentStack extends Stack {
57
83
} ) ;
58
84
let deploymentConfig : IEcsDeploymentConfig | undefined = undefined ;
59
85
if ( props ?. deploymentConfigName ) {
60
- deploymentConfig = EcsDeploymentConfig . fromEcsDeploymentConfigName ( this , 'DeploymentConfig' , props . deploymentConfigName ) ;
86
+ deploymentConfig = EcsDeploymentConfig . fromEcsDeploymentConfigName (
87
+ this ,
88
+ 'DeploymentConfig' ,
89
+ props . deploymentConfigName ,
90
+ ) ;
61
91
}
62
- const appConfigEnabled = props ?. appConfigRoleArn !== undefined && props . appConfigRoleArn . length > 0 ;
63
- const service = new ApplicationLoadBalancedCodeDeployedFargateService ( this , 'Api' , {
64
- cluster,
65
- capacityProviderStrategies : [
66
- {
67
- capacityProvider : 'FARGATE_SPOT' ,
68
- weight : 1 ,
92
+ const appConfigEnabled =
93
+ props ?. appConfigRoleArn !== undefined &&
94
+ props . appConfigRoleArn . length > 0 ;
95
+ const service = new ApplicationLoadBalancedCodeDeployedFargateService (
96
+ this ,
97
+ 'Api' ,
98
+ {
99
+ cluster,
100
+ capacityProviderStrategies : [
101
+ {
102
+ capacityProvider : 'FARGATE_SPOT' ,
103
+ weight : 1 ,
104
+ } ,
105
+ ] ,
106
+ minHealthyPercent : 50 ,
107
+ maxHealthyPercent : 200 ,
108
+ desiredCount : 3 ,
109
+ cpu : 512 ,
110
+ memoryLimitMiB : 1024 ,
111
+ taskImageOptions : {
112
+ image,
113
+ containerName : 'api' ,
114
+ containerPort : 8080 ,
115
+ family : appName ,
116
+ logDriver : AwsLogDriver . awsLogs ( {
117
+ logGroup : appLogGroup ,
118
+ streamPrefix : 'service' ,
119
+ } ) ,
120
+ secrets : {
121
+ SPRING_DATASOURCE_USERNAME : Secret . fromSecretsManager (
122
+ dbSecret ,
123
+ 'username' ,
124
+ ) ,
125
+ SPRING_DATASOURCE_PASSWORD : Secret . fromSecretsManager (
126
+ dbSecret ,
127
+ 'password' ,
128
+ ) ,
129
+ } ,
130
+ environment : {
131
+ SPRING_DATASOURCE_URL : `jdbc:mysql://${ db . clusterEndpoint . hostname } :${ db . clusterEndpoint . port } /${ dbName } ` ,
132
+ APPCONFIG_AGENT_APPLICATION :
133
+ this . node . tryGetContext ( 'workloadName' ) ,
134
+ APPCONFIG_AGENT_ENVIRONMENT :
135
+ this . node . tryGetContext ( 'environmentName' ) ,
136
+ APPCONFIG_AGENT_ENABLED : appConfigEnabled . toString ( ) ,
137
+ } ,
69
138
} ,
70
- ] ,
71
- minHealthyPercent : 50 ,
72
- maxHealthyPercent : 200 ,
73
- desiredCount : 3 ,
74
- cpu : 512 ,
75
- memoryLimitMiB : 1024 ,
76
- taskImageOptions : {
77
- image,
78
- containerName : 'api' ,
79
- containerPort : 8080 ,
80
- family : appName ,
81
- logDriver : AwsLogDriver . awsLogs ( {
82
- logGroup : appLogGroup ,
83
- streamPrefix : 'service' ,
84
- } ) ,
85
- secrets : {
86
- SPRING_DATASOURCE_USERNAME : Secret . fromSecretsManager ( dbSecret , 'username' ) ,
87
- SPRING_DATASOURCE_PASSWORD : Secret . fromSecretsManager ( dbSecret , 'password' ) ,
88
- } ,
89
- environment : {
90
- SPRING_DATASOURCE_URL : `jdbc:mysql://${ db . clusterEndpoint . hostname } :${ db . clusterEndpoint . port } /${ dbName } ` ,
91
- APPCONFIG_AGENT_APPLICATION : this . node . tryGetContext ( 'workloadName' ) ,
92
- APPCONFIG_AGENT_ENVIRONMENT : this . node . tryGetContext ( 'environmentName' ) ,
93
- APPCONFIG_AGENT_ENABLED : appConfigEnabled . toString ( ) ,
139
+ deregistrationDelay : Duration . seconds ( 5 ) ,
140
+ responseTimeAlarmThreshold : Duration . seconds ( 3 ) ,
141
+ targetHealthCheck : {
142
+ healthyThresholdCount : 2 ,
143
+ unhealthyThresholdCount : 2 ,
144
+ interval : Duration . seconds ( 60 ) ,
145
+ path : '/actuator/health' ,
94
146
} ,
147
+ deploymentConfig,
148
+ terminationWaitTime : Duration . minutes ( 5 ) ,
149
+ apiCanaryTimeout : Duration . seconds ( 5 ) ,
150
+ apiTestSteps : [
151
+ {
152
+ name : 'getAll' ,
153
+ path : '/api/fruits' ,
154
+ jmesPath : 'length(@)' ,
155
+ expectedValue : 5 ,
156
+ } ,
157
+ ] ,
95
158
} ,
96
- deregistrationDelay : Duration . seconds ( 5 ) ,
97
- responseTimeAlarmThreshold : Duration . seconds ( 3 ) ,
98
- targetHealthCheck : {
99
- healthyThresholdCount : 2 ,
100
- unhealthyThresholdCount : 2 ,
101
- interval : Duration . seconds ( 60 ) ,
102
- path : '/actuator/health' ,
103
- } ,
104
- deploymentConfig,
105
- terminationWaitTime : Duration . minutes ( 5 ) ,
106
- apiCanaryTimeout : Duration . seconds ( 5 ) ,
107
- apiTestSteps : [ {
108
- name : 'getAll' ,
109
- path : '/api/fruits' ,
110
- jmesPath : 'length(@)' ,
111
- expectedValue : 5 ,
112
- } ] ,
113
- } ) ;
159
+ ) ;
114
160
115
161
if ( appConfigEnabled ) {
116
162
service . taskDefinition . addContainer ( 'appconfig-agent' , {
117
- image : ecs . ContainerImage . fromRegistry ( 'public.ecr.aws/aws-appconfig/aws-appconfig-agent:2.x' ) ,
163
+ image : ecs . ContainerImage . fromRegistry (
164
+ 'public.ecr.aws/aws-appconfig/aws-appconfig-agent:2.x' ,
165
+ ) ,
118
166
essential : false ,
119
167
logging : AwsLogDriver . awsLogs ( {
120
168
logGroup : appLogGroup ,
@@ -129,13 +177,18 @@ export class DeploymentStack extends Stack {
129
177
portMappings : [ { containerPort : 2772 } ] ,
130
178
} ) ;
131
179
132
- service . taskDefinition . addToTaskRolePolicy ( new PolicyStatement ( {
133
- actions : [ 'sts:AssumeRole' ] ,
134
- resources : [ props ! . appConfigRoleArn ! ] ,
135
- } ) ) ;
180
+ service . taskDefinition . addToTaskRolePolicy (
181
+ new PolicyStatement ( {
182
+ actions : [ 'sts:AssumeRole' ] ,
183
+ resources : [ props ! . appConfigRoleArn ! ] ,
184
+ } ) ,
185
+ ) ;
136
186
}
137
187
138
- service . service . connections . allowTo ( db , Port . tcp ( db . clusterEndpoint . port ) ) ;
188
+ service . service . connections . allowTo (
189
+ db ,
190
+ ec2 . Port . tcp ( db . clusterEndpoint . port ) ,
191
+ ) ;
139
192
140
193
this . apiUrl = new CfnOutput ( this , 'endpointUrl' , {
141
194
value : `http://${ service . listener . loadBalancer . loadBalancerDnsName } ` ,
0 commit comments