@@ -19,6 +19,9 @@ Metadata:
19
19
- MemoryLimit
20
20
- MemoryReservation
21
21
- HealthCheckGracePeriodSeconds
22
+ - TaskDeregistrationDelay
23
+ - ExternalFacing
24
+ - LoadBalancerPriority
22
25
- Label :
23
26
default : Application Parameters
24
27
Parameters :
@@ -30,7 +33,6 @@ Metadata:
30
33
Parameters :
31
34
- SplunkToken
32
35
- SplunkUrl
33
- - SplunkEnv
34
36
35
37
Parameters :
36
38
ParentVPCStack :
@@ -41,7 +43,7 @@ Parameters:
41
43
42
44
ParentAlertStack :
43
45
Type : String
44
- Default : " "
46
+ Default : ' '
45
47
46
48
ContainerName :
47
49
Type : String
@@ -58,6 +60,19 @@ Parameters:
58
60
Type : Number
59
61
Default : 15
60
62
63
+ ExternalFacing :
64
+ Description : Boolean flag which enables the service to be exposed via the external load balancer
65
+ Type : String
66
+ Default : false
67
+ AllowedValues : [true, false]
68
+
69
+ LoadBalancerPriority :
70
+ Description : The priority of the service in the load balancer
71
+ Type : Number
72
+ MinValue : 1
73
+ MaxValue : 100
74
+ ConstraintDescription : ' Priority must be provided'
75
+
61
76
ApplicationContext :
62
77
Type : String
63
78
@@ -93,10 +108,18 @@ Parameters:
93
108
Type : String
94
109
95
110
Conditions :
96
- HasAlertTopic : !Not [!Equals [!Ref ParentAlertStack, '']]
111
+ IsExternalFacing : !Equals [!Ref ExternalFacing, true]
112
+ IsInternalFacing : !Equals [!Ref ExternalFacing, false]
113
+ CreateExternalAlarms : !And
114
+ - !Not [!Equals [!Ref ParentAlertStack, '']]
115
+ - !Equals [!Ref ExternalFacing, true]
116
+ CreateInternalAlarms : !And
117
+ - !Not [!Equals [!Ref ParentAlertStack, '']]
118
+ - !Equals [!Ref ExternalFacing, false]
97
119
98
120
Resources :
99
121
ExternalTargetGroup :
122
+ Condition : IsExternalFacing
100
123
Type : AWS::ElasticLoadBalancingV2::TargetGroup
101
124
Properties :
102
125
VpcId :
@@ -115,12 +138,14 @@ Resources:
115
138
- Key : deregistration_delay.timeout_seconds
116
139
Value : !Ref TaskDeregistrationDelay
117
140
118
- ExternalListenerRule :
141
+ ExternalHttpsListenerRule :
142
+ DependsOn : ExternalTargetGroup
143
+ Condition : IsExternalFacing
119
144
Type : AWS::ElasticLoadBalancingV2::ListenerRule
120
145
Properties :
121
146
ListenerArn :
122
- ' Fn::ImportValue ' : !Sub '${ParentECSStack}-ExternalLoadBalancerListener '
123
- Priority : 6
147
+ ' Fn::ImportValue ' : !Sub '${ParentECSStack}-ExternalLoadBalancerHttpsListener '
148
+ Priority : !Ref LoadBalancerPriority
124
149
Conditions :
125
150
- Field : path-pattern
126
151
Values :
@@ -129,6 +154,42 @@ Resources:
129
154
- TargetGroupArn : !Ref ExternalTargetGroup
130
155
Type : forward
131
156
157
+ InternalTargetGroup :
158
+ Condition : IsInternalFacing
159
+ Type : AWS::ElasticLoadBalancingV2::TargetGroup
160
+ Properties :
161
+ VpcId :
162
+ ' Fn::ImportValue ' : !Sub '${ParentVPCStack}-VPC'
163
+ Port : 80
164
+ Protocol : HTTP
165
+ Matcher :
166
+ HttpCode : 200-299
167
+ HealthCheckIntervalSeconds : 10
168
+ HealthCheckPath : !Sub '/actuator/health'
169
+ HealthCheckProtocol : HTTP
170
+ HealthCheckTimeoutSeconds : 5 # Healthcheck timeout must be smaller than the interval
171
+ HealthyThresholdCount : 2
172
+ UnhealthyThresholdCount : 3
173
+ TargetGroupAttributes :
174
+ - Key : deregistration_delay.timeout_seconds
175
+ Value : !Ref TaskDeregistrationDelay
176
+
177
+ InternalHttpsListenerRule :
178
+ DependsOn : InternalTargetGroup
179
+ Condition : IsInternalFacing
180
+ Type : AWS::ElasticLoadBalancingV2::ListenerRule
181
+ Properties :
182
+ ListenerArn :
183
+ ' Fn::ImportValue ' : !Sub '${ParentECSStack}-InternalLoadBalancerHttpsListener'
184
+ Priority : !Ref LoadBalancerPriority
185
+ Conditions :
186
+ - Field : path-pattern
187
+ Values :
188
+ - !Sub " ${ApplicationContext}/*"
189
+ Actions :
190
+ - TargetGroupArn : !Ref InternalTargetGroup
191
+ Type : forward
192
+
132
193
ServiceRole :
133
194
Type : AWS::IAM::Role
134
195
Properties :
@@ -144,7 +205,12 @@ Resources:
144
205
ManagedPolicyArns :
145
206
- arn:aws:iam::aws:policy/service-role/AmazonEC2ContainerServiceRole
146
207
147
- Service :
208
+ ExternalService :
209
+ DependsOn :
210
+ - ExternalTargetGroup
211
+ - TaskDefinition
212
+ - ServiceRole
213
+ Condition : IsExternalFacing
148
214
Type : AWS::ECS::Service
149
215
Properties :
150
216
Cluster :
@@ -165,6 +231,32 @@ Resources:
165
231
ContainerPort : 8080
166
232
TargetGroupArn : !Ref ExternalTargetGroup
167
233
234
+ InternalService :
235
+ DependsOn :
236
+ - InternalTargetGroup
237
+ - TaskDefinition
238
+ - ServiceRole
239
+ Condition : IsInternalFacing
240
+ Type : AWS::ECS::Service
241
+ Properties :
242
+ Cluster :
243
+ ' Fn::ImportValue ' : !Sub '${ParentECSStack}-Cluster'
244
+ Role : !Ref ServiceRole
245
+ DesiredCount : !Ref DesiredCount
246
+ HealthCheckGracePeriodSeconds : !Ref HealthCheckGracePeriodSeconds
247
+ PlacementStrategies :
248
+ - Type : spread
249
+ Field : ' attribute:ecs.availability-zone'
250
+ - Type : spread
251
+ Field : ' instanceId'
252
+ - Type : binpack
253
+ Field : ' memory'
254
+ TaskDefinition : !Ref TaskDefinition
255
+ LoadBalancers :
256
+ - ContainerName : !Ref ContainerName
257
+ ContainerPort : 8080
258
+ TargetGroupArn : !Ref InternalTargetGroup
259
+
168
260
TaskDefinition :
169
261
Type : AWS::ECS::TaskDefinition
170
262
Properties :
@@ -197,8 +289,10 @@ Resources:
197
289
- Name : SPRING_PROFILES_ACTIVE
198
290
Value : !Ref SpringProfile
199
291
200
- HTTPCodeTarget5XXTooHighAlarm :
201
- Condition : HasAlertTopic
292
+ HTTPCodeExternalTarget5XXTooHighAlarm :
293
+ DependsOn :
294
+ - ExternalTargetGroup
295
+ Condition : CreateExternalAlarms
202
296
Type : ' AWS::CloudWatch::Alarm'
203
297
Properties :
204
298
AlarmDescription : ' ${AWS::StackName} HTTP 500 response code alarm'
@@ -218,8 +312,11 @@ Resources:
218
312
' Fn::ImportValue ' : !Sub '${ParentECSStack}-ExternalLoadBalancerName'
219
313
- Name : TargetGroup
220
314
Value : !GetAtt 'ExternalTargetGroup.TargetGroupFullName'
221
- NoHealthyServiceAlarm :
222
- Condition : HasAlertTopic
315
+ NoHealthyExternalServiceAlarm :
316
+ DependsOn :
317
+ - ExternalTargetGroup
318
+ - ExternalService
319
+ Condition : CreateExternalAlarms
223
320
Type : ' AWS::CloudWatch::Alarm'
224
321
Properties :
225
322
AlarmDescription : ' ${AWS::StackName} has no healthy services'
@@ -240,10 +337,65 @@ Resources:
240
337
- Name : TargetGroup
241
338
Value : !GetAtt 'ExternalTargetGroup.TargetGroupFullName'
242
339
340
+ HTTPCodeInternalTarget5XXTooHighAlarm :
341
+ DependsOn :
342
+ - InternalTargetGroup
343
+ Condition : CreateInternalAlarms
344
+ Type : ' AWS::CloudWatch::Alarm'
345
+ Properties :
346
+ AlarmDescription : ' ${AWS::StackName} HTTP 500 response code alarm'
347
+ Namespace : ' AWS/ApplicationELB'
348
+ MetricName : HTTPCode_Target_5XX_Count
349
+ Statistic : Sum
350
+ Period : 60
351
+ EvaluationPeriods : 1
352
+ ComparisonOperator : GreaterThanThreshold
353
+ Threshold : 0
354
+ TreatMissingData : notBreaching
355
+ AlarmActions :
356
+ - ' Fn::ImportValue ' : !Sub '${ParentAlertStack}-TopicARN'
357
+ Dimensions :
358
+ - Name : LoadBalancer
359
+ Value :
360
+ ' Fn::ImportValue ' : !Sub '${ParentECSStack}-InternalLoadBalancerName'
361
+ - Name : TargetGroup
362
+ Value : !GetAtt 'InternalTargetGroup.TargetGroupFullName'
363
+ NoHealthyInternalServiceAlarm :
364
+ DependsOn :
365
+ - InternalTargetGroup
366
+ - InternalService
367
+ Condition : CreateInternalAlarms
368
+ Type : ' AWS::CloudWatch::Alarm'
369
+ Properties :
370
+ AlarmDescription : ' ${AWS::StackName} has no healthy services'
371
+ Namespace : ' AWS/ApplicationELB'
372
+ MetricName : HealthyHostCount
373
+ Statistic : Minimum
374
+ Period : 60
375
+ EvaluationPeriods : 1
376
+ ComparisonOperator : LessThanThreshold
377
+ Threshold : 1
378
+ TreatMissingData : breaching
379
+ AlarmActions :
380
+ - ' Fn::ImportValue ' : !Sub '${ParentAlertStack}-TopicARN'
381
+ Dimensions :
382
+ - Name : LoadBalancer
383
+ Value :
384
+ ' Fn::ImportValue ' : !Sub '${ParentECSStack}-InternalLoadBalancerName'
385
+ - Name : TargetGroup
386
+ Value : !GetAtt 'InternalTargetGroup.TargetGroupFullName'
387
+
243
388
Outputs :
244
- ServiceName :
245
- Description : ' The name of the service running the ECS'
246
- Value : !Ref Service
389
+ ExternalServiceName :
390
+ Condition : IsExternalFacing
391
+ Description : ' The name of the external service running the ECS'
392
+ Value : !Ref ExternalService
393
+ Export :
394
+ Name : !Sub '${AWS::StackName}-Name'
395
+ InternalServiceName :
396
+ Condition : IsInternalFacing
397
+ Description : ' The name of the internal service running the ECS'
398
+ Value : !Ref InternalService
247
399
Export :
248
400
Name : !Sub '${AWS::StackName}-Name'
249
401
ApplicationContext :
0 commit comments