Skip to content

Commit e8801a0

Browse files
authored
feat(ecs): deployment circuit breaker support (#12168)
feat(ecs): deployment circuit breaker support This PR allows you to enable the `deployment circuit breaker` support for Amazon ECS. Depends on - [ ] cfnspec v22 #12170 ---- *By submitting this pull request, I confirm that my contribution is made under the terms of the Apache-2.0 license*
1 parent 52a80bb commit e8801a0

File tree

3 files changed

+81
-0
lines changed

3 files changed

+81
-0
lines changed

packages/@aws-cdk/aws-ecs/README.md

+15
Original file line numberDiff line numberDiff line change
@@ -335,6 +335,21 @@ const service = new ecs.FargateService(this, 'Service', {
335335
`Services` by default will create a security group if not provided.
336336
If you'd like to specify which security groups to use you can override the `securityGroups` property.
337337

338+
### Deployment circuit breaker and rollback
339+
340+
Amazon ECS [deployment circuit breaker](https://aws.amazon.com/tw/blogs/containers/announcing-amazon-ecs-deployment-circuit-breaker/)
341+
automatically rolls back unhealthy service deployments without the need for manual intervention. Use `circuitBreaker` to enable
342+
deployment circuit breaker and optionally enable `rollback` for automatic rollback. See [Using the deployment circuit breaker](https://docs.aws.amazon.com/AmazonECS/latest/developerguide/deployment-type-ecs.html)
343+
for more details.
344+
345+
```ts
346+
const service = new ecs.FargateService(stack, 'Service', {
347+
cluster,
348+
taskDefinition,
349+
circuitBreaker: { rollback: true },
350+
});
351+
```
352+
338353
### Include an application/network load balancer
339354

340355
`Services` are load balancing targets and can be added to a target group, which will be attached to an application/network load balancers:

packages/@aws-cdk/aws-ecs/lib/base/base-service.ts

+29
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,18 @@ export interface DeploymentController {
4444
readonly type?: DeploymentControllerType;
4545
}
4646

47+
/**
48+
* The deployment circuit breaker to use for the service
49+
*/
50+
export interface DeploymentCircuitBreaker {
51+
/**
52+
* Whether to enable rollback on deployment failure
53+
* @default false
54+
*/
55+
readonly rollback?: boolean;
56+
57+
}
58+
4759
export interface EcsTarget {
4860
/**
4961
* The name of the container.
@@ -161,6 +173,13 @@ export interface BaseServiceOptions {
161173
* @default - Rolling update (ECS)
162174
*/
163175
readonly deploymentController?: DeploymentController;
176+
177+
/**
178+
* Whether to enable the deployment circuit breaker. If this property is defined, circuit breaker will be implicitly
179+
* enabled.
180+
* @default - disabled
181+
*/
182+
readonly circuitBreaker?: DeploymentCircuitBreaker;
164183
}
165184

166185
/**
@@ -356,6 +375,16 @@ export abstract class BaseService extends Resource
356375
...additionalProps,
357376
});
358377

378+
if (props.circuitBreaker) {
379+
const deploymentConfiguration = {
380+
DeploymentCircuitBreaker: {
381+
Enable: true,
382+
Rollback: props.circuitBreaker.rollback ?? false,
383+
},
384+
};
385+
// TODO: fix this when this property is available in CfnService
386+
this.resource.addPropertyOverride('DeploymentConfiguration', deploymentConfiguration);
387+
};
359388
if (props.deploymentController?.type === DeploymentControllerType.EXTERNAL) {
360389
Annotations.of(this).addWarning('taskDefinition and launchType are blanked out when using external deployment controller.');
361390
}

packages/@aws-cdk/aws-ecs/test/fargate/test.fargate-service.ts

+37
Original file line numberDiff line numberDiff line change
@@ -212,6 +212,7 @@ export = {
212212
deploymentController: {
213213
type: ecs.DeploymentControllerType.CODE_DEPLOY,
214214
},
215+
circuitBreaker: { rollback: true },
215216
securityGroup: new ec2.SecurityGroup(stack, 'SecurityGroup1', {
216217
allowAllOutbound: true,
217218
description: 'Example',
@@ -235,6 +236,10 @@ export = {
235236
DeploymentConfiguration: {
236237
MaximumPercent: 150,
237238
MinimumHealthyPercent: 55,
239+
DeploymentCircuitBreaker: {
240+
Enable: true,
241+
Rollback: true,
242+
},
238243
},
239244
DeploymentController: {
240245
Type: ecs.DeploymentControllerType.CODE_DEPLOY,
@@ -1786,6 +1791,38 @@ export = {
17861791
test.done();
17871792
},
17881793

1794+
'with circuit breaker'(test: Test) {
1795+
// GIVEN
1796+
const stack = new cdk.Stack();
1797+
const cluster = new ecs.Cluster(stack, 'EcsCluster');
1798+
const taskDefinition = new ecs.FargateTaskDefinition(stack, 'FargateTaskDef');
1799+
1800+
taskDefinition.addContainer('Container', {
1801+
image: ecs.ContainerImage.fromRegistry('hello'),
1802+
});
1803+
1804+
// WHEN
1805+
new ecs.FargateService(stack, 'EcsService', {
1806+
cluster,
1807+
taskDefinition,
1808+
circuitBreaker: { rollback: true },
1809+
});
1810+
1811+
// THEN
1812+
expect(stack).to(haveResource('AWS::ECS::Service', {
1813+
DeploymentConfiguration: {
1814+
MaximumPercent: 200,
1815+
MinimumHealthyPercent: 50,
1816+
DeploymentCircuitBreaker: {
1817+
Enable: true,
1818+
Rollback: true,
1819+
},
1820+
},
1821+
}));
1822+
1823+
test.done();
1824+
},
1825+
17891826
'throws an exception if both serviceArn and serviceName were provided for fromEc2ServiceAttributes'(test: Test) {
17901827
// GIVEN
17911828
const stack = new cdk.Stack();

0 commit comments

Comments
 (0)