Skip to content

Commit efd24d1

Browse files
authored
feat(codedeploy): CodeDeploy deployment group construct for ECS (#22295)
closes #1559 *By submitting this pull request, I confirm that my contribution is made under the terms of the Apache-2.0 license*
1 parent 6e0cb2b commit efd24d1

19 files changed

+5645
-36
lines changed

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

+250-3
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,24 @@
1111

1212
<!--END STABILITY BANNER-->
1313

14+
## Table of Contents
15+
16+
- [Introduction](#introduction)
17+
- Deploying to Amazon EC2 and on-premise instances
18+
- [EC2/on-premise Applications](#ec2on-premise-applications)
19+
- [EC2/on-premise Deployment Groups](#ec2on-premise-deployment-groups)
20+
- [EC2/on-premise Deployment Configurations](#ec2on-premise-deployment-configurations)
21+
- Deploying to AWS Lambda functions
22+
- [Lambda Applications](#lambda-applications)
23+
- [Lambda Deployment Groups](#lambda-deployment-groups)
24+
- [Lambda Deployment Configurations](#lambda-deployment-configurations)
25+
- Deploying to Amazon ECS services
26+
- [ECS Applications](#ecs-applications)
27+
- [ECS Deployment Groups](#ecs-deployment-groups)
28+
- [ECS Deployment Configurations](#ecs-deployment-configurations)
29+
30+
## Introduction
31+
1432
AWS CodeDeploy is a deployment service that automates application deployments to
1533
Amazon EC2 instances, on-premises instances, serverless Lambda functions, or
1634
Amazon ECS services.
@@ -98,7 +116,7 @@ To import an already existing Deployment Group:
98116
```ts
99117
declare const application: codedeploy.ServerApplication;
100118
const deploymentGroup = codedeploy.ServerDeploymentGroup.fromServerDeploymentGroupAttributes(
101-
this,
119+
this,
102120
'ExistingCodeDeployDeploymentGroup', {
103121
application,
104122
deploymentGroupName: 'MyExistingDeploymentGroup',
@@ -226,7 +244,7 @@ In order to deploy a new version of this function:
226244
2. Re-deploy the stack (this will trigger a deployment).
227245
3. Monitor the CodeDeploy deployment as traffic shifts between the versions.
228246

229-
### Rollbacks and Alarms
247+
### Lambda Deployment Rollbacks and Alarms
230248

231249
CodeDeploy will roll back if the deployment fails. You can optionally trigger a rollback when one or more alarms are in a failed state:
232250

@@ -281,7 +299,7 @@ const deploymentGroup = new codedeploy.LambdaDeploymentGroup(this, 'BlueGreenDep
281299
deploymentGroup.addPostHook(endToEndValidation);
282300
```
283301

284-
### Import an existing Deployment Group
302+
### Import an existing Lambda Deployment Group
285303

286304
To import an already existing Deployment Group:
287305

@@ -373,6 +391,235 @@ const application = codedeploy.EcsApplication.fromEcsApplicationName(
373391
);
374392
```
375393

394+
## ECS Deployment Groups
395+
396+
CodeDeploy can be used to deploy to load-balanced ECS services.
397+
CodeDeploy performs ECS blue-green deployments by managing ECS task sets and load balancer
398+
target groups. During a blue-green deployment, one task set and target group runs the
399+
original version of your ECS task definition ('blue') and another task set and target group
400+
runs the new version of your ECS task definition ('green').
401+
402+
CodeDeploy orchestrates traffic shifting during ECS blue-green deployments by using
403+
a load balancer listener to balance incoming traffic between the 'blue' and 'green' task sets/target groups
404+
running two different versions of your ECS task definition.
405+
Before deployment, the load balancer listener sends 100% of requests to the 'blue' target group.
406+
When you publish a new version of the task definition and start a CodeDeploy deployment,
407+
CodeDeploy can send a small percentage of traffic to the new 'green' task set behind the 'green' target group,
408+
monitor, and validate before shifting 100% of traffic to the new version.
409+
410+
To create a new CodeDeploy Deployment Group that deploys to an ECS service:
411+
412+
```ts
413+
declare const myApplication: codedeploy.EcsApplication;
414+
declare const cluster: ecs.Cluster;
415+
declare const taskDefinition: ecs.FargateTaskDefinition;
416+
declare const blueTargetGroup: elbv2.ITargetGroup;
417+
declare const greenTargetGroup: elbv2.ITargetGroup;
418+
declare const listener: elbv2.IApplicationListener;
419+
420+
const service = new ecs.FargateService(this, 'Service', {
421+
cluster,
422+
taskDefinition,
423+
deploymentController: {
424+
type: ecs.DeploymentControllerType.CODE_DEPLOY,
425+
},
426+
});
427+
428+
new codedeploy.EcsDeploymentGroup(stack, 'BlueGreenDG', {
429+
service,
430+
blueGreenDeploymentConfig: {
431+
blueTargetGroup,
432+
greenTargetGroup,
433+
listener,
434+
},
435+
deploymentConfig: codedeploy.EcsDeploymentConfig.CANARY_10PERCENT_5MINUTES,
436+
});
437+
```
438+
439+
In order to deploy a new task definition version to the ECS service,
440+
deploy the changes directly through CodeDeploy using the CodeDeploy APIs or console.
441+
When the `CODE_DEPLOY` deployment controller is used, the ECS service cannot be
442+
deployed with a new task definition version through CloudFormation.
443+
444+
For more information on the behavior of CodeDeploy blue-green deployments for ECS, see
445+
[What happens during an Amazon ECS deployment](https://docs.aws.amazon.com/codedeploy/latest/userguide/deployment-steps-ecs.html#deployment-steps-what-happens)
446+
in the CodeDeploy user guide.
447+
448+
Note: If you wish to deploy updates to your ECS service through CDK and CloudFormation instead of directly through CodeDeploy,
449+
using the [`CfnCodeDeployBlueGreenHook`](https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.CfnCodeDeployBlueGreenHook.html)
450+
construct is the recommended approach instead of using the `EcsDeploymentGroup` construct. For a comparison
451+
of ECS blue-green deployments through CodeDeploy (using `EcsDeploymentGroup`) and through CloudFormation (using `CfnCodeDeployBlueGreenHook`),
452+
see [Create an Amazon ECS blue/green deployment through AWS CloudFormation](https://docs.aws.amazon.com/codedeploy/latest/userguide/deployments-create-ecs-cfn.html#differences-ecs-bg-cfn)
453+
in the CloudFormation user guide.
454+
455+
### ECS Deployment Rollbacks and Alarms
456+
457+
CodeDeploy will automatically roll back if a deployment fails.
458+
You can optionally trigger an automatic rollback when one or more alarms are in a failed state during a deployment, or if the deployment stops.
459+
460+
In this example, CodeDeploy will monitor and roll back on alarms set for the
461+
number of unhealthy ECS tasks in each of the blue and green target groups,
462+
as well as alarms set for the number HTTP 5xx responses seen in each of the blue
463+
and green target groups.
464+
465+
```ts
466+
import * as cloudwatch from '@aws-cdk/aws-cloudwatch';
467+
468+
// Alarm on the number of unhealthy ECS tasks in each target group
469+
const blueUnhealthyHosts = new cloudwatch.Alarm(stack, 'BlueUnhealthyHosts', {
470+
alarmName: stack.stackName + '-Unhealthy-Hosts-Blue',
471+
metric: blueTargetGroup.metricUnhealthyHostCount(),
472+
threshold: 1,
473+
evaluationPeriods: 2,
474+
});
475+
476+
const greenUnhealthyHosts = new cloudwatch.Alarm(stack, 'GreenUnhealthyHosts', {
477+
alarmName: stack.stackName + '-Unhealthy-Hosts-Green',
478+
metric: greenTargetGroup.metricUnhealthyHostCount(),
479+
threshold: 1,
480+
evaluationPeriods: 2,
481+
});
482+
483+
// Alarm on the number of HTTP 5xx responses returned by each target group
484+
const blueApiFailure = new cloudwatch.Alarm(stack, 'Blue5xx', {
485+
alarmName: stack.stackName + '-Http-5xx-Blue',
486+
metric: blueTargetGroup.metricHttpCodeTarget(
487+
elbv2.HttpCodeTarget.TARGET_5XX_COUNT,
488+
{ period: cdk.Duration.minutes(1) },
489+
),
490+
threshold: 1,
491+
evaluationPeriods: 1,
492+
});
493+
494+
const greenApiFailure = new cloudwatch.Alarm(stack, 'Green5xx', {
495+
alarmName: stack.stackName + '-Http-5xx-Green',
496+
metric: greenTargetGroup.metricHttpCodeTarget(
497+
elbv2.HttpCodeTarget.TARGET_5XX_COUNT,
498+
{ period: cdk.Duration.minutes(1) },
499+
),
500+
threshold: 1,
501+
evaluationPeriods: 1,
502+
});
503+
504+
new codedeploy.EcsDeploymentGroup(stack, 'BlueGreenDG', {
505+
// CodeDeploy will monitor these alarms during a deployment and automatically roll back
506+
alarms: [blueUnhealthyHosts, greenUnhealthyHosts, blueApiFailure, greenApiFailure],
507+
autoRollback: {
508+
// CodeDeploy will automatically roll back if a deployment is stopped
509+
stoppedDeployment: true,
510+
},
511+
service,
512+
blueGreenDeploymentConfig: {
513+
blueTargetGroup,
514+
greenTargetGroup,
515+
listener,
516+
},
517+
deploymentConfig: codedeploy.EcsDeploymentConfig.CANARY_10PERCENT_5MINUTES,
518+
});
519+
```
520+
521+
### Deployment validation and manual deployment approval
522+
523+
CodeDeploy blue-green deployments provide an opportunity to validate the new task definition version running on
524+
the 'green' ECS task set prior to shifting any production traffic to the new version. A second 'test' listener
525+
serving traffic on a different port be added to the load balancer. For example, the test listener can serve
526+
test traffic on port 9001 while the main listener serves production traffic on port 443.
527+
During a blue-green deployment, CodeDeploy can then shift 100% of test traffic over to the 'green'
528+
task set/target group prior to shifting any production traffic during the deployment.
529+
530+
```ts
531+
declare const myApplication: codedeploy.EcsApplication;
532+
declare const service: ecs.FargateService;
533+
declare const blueTargetGroup: elbv2.ITargetGroup;
534+
declare const greenTargetGroup: elbv2.ITargetGroup;
535+
declare const listener: elbv2.IApplicationListener;
536+
declare const testListener: elbv2.IApplicationListener;
537+
538+
new codedeploy.EcsDeploymentGroup(stack, 'BlueGreenDG', {
539+
service,
540+
blueGreenDeploymentConfig: {
541+
blueTargetGroup,
542+
greenTargetGroup,
543+
listener,
544+
testListener,
545+
},
546+
deploymentConfig: codedeploy.EcsDeploymentConfig.CANARY_10PERCENT_5MINUTES,
547+
});
548+
```
549+
550+
Automated validation steps can run during the CodeDeploy deployment after shifting test traffic and before
551+
shifting production traffic. CodeDeploy supports registering Lambda functions as lifecycle hooks for
552+
an ECS deployment. These Lambda functions can run automated validation steps against the test traffic
553+
port, for example in response to the `AfterAllowTestTraffic` lifecycle hook. For more information about
554+
how to specify the Lambda functions to run for each CodeDeploy lifecycle hook in an ECS deployment, see the
555+
[AppSpec 'hooks' for an Amazon ECS deployment](https://docs.aws.amazon.com/codedeploy/latest/userguide/reference-appspec-file-structure-hooks.html#appspec-hooks-ecs)
556+
section in the CodeDeploy user guide.
557+
558+
After provisioning the 'green' ECS task set and re-routing test traffic during a blue-green deployment,
559+
CodeDeploy can wait for approval before continuing the deployment and re-routing production traffic.
560+
During this approval wait time, you can complete additional validation steps prior to exposing the new
561+
'green' task set to production traffic, such as manual testing through the test listener port or
562+
running automated integration test suites.
563+
564+
To approve the deployment, validation steps use the CodeDeploy
565+
[ContinueDeployment API(https://docs.aws.amazon.com/codedeploy/latest/APIReference/API_ContinueDeployment.html).
566+
If the ContinueDeployment API is not called within the approval wait time period, CodeDeploy will stop the
567+
deployment and can automatically roll back the deployment.
568+
569+
```ts
570+
new codedeploy.EcsDeploymentGroup(stack, 'BlueGreenDG', {
571+
// The deployment will wait for approval for up to 8 hours before stopping the deployment
572+
deploymentApprovalWaitTime: Duration.hours(8),
573+
autoRollback: {
574+
// CodeDeploy will automatically roll back if the 8-hour approval period times out and the deployment stops
575+
stoppedDeployment: true,
576+
},
577+
service,
578+
blueGreenDeploymentConfig: {
579+
blueTargetGroup,
580+
greenTargetGroup,
581+
listener,
582+
testListener,
583+
},
584+
deploymentConfig: codedeploy.EcsDeploymentConfig.CANARY_10PERCENT_5MINUTES,
585+
});
586+
```
587+
588+
### Deployment bake time
589+
590+
You can specify how long CodeDeploy waits before it terminates the original 'blue' ECS task set when a blue-green deployment
591+
is complete in order to let the deployment "bake" a while. During this bake time, CodeDeploy will continue to monitor any
592+
CloudWatch alarms specified for the deployment group and will automatically roll back if those alarms go into a failed state.
593+
594+
```ts
595+
new codedeploy.EcsDeploymentGroup(stack, 'BlueGreenDG', {
596+
service,
597+
blueGreenDeploymentConfig: {
598+
blueTargetGroup,
599+
greenTargetGroup,
600+
listener,
601+
// CodeDeploy will wait for 30 minutes after completing the blue-green deployment before it terminates the blue tasks
602+
terminationWaitTime: Duration.minutes(30),
603+
},
604+
// CodeDeploy will continue to monitor these alarms during the 30-minute bake time and will automatically
605+
// roll back if they go into a failed state at any point during the deployment.
606+
alarms: [blueUnhealthyHosts, greenUnhealthyHosts, blueApiFailure, greenApiFailure],
607+
deploymentConfig: codedeploy.EcsDeploymentConfig.CANARY_10PERCENT_5MINUTES,
608+
});
609+
```
610+
611+
### Import an existing ECS Deployment Group
612+
613+
To import an already existing Deployment Group:
614+
615+
```ts
616+
declare const application: codedeploy.EcsApplication;
617+
const deploymentGroup = codedeploy.EcsDeploymentGroup.fromEcsDeploymentGroupAttributes(this, 'ExistingCodeDeployDeploymentGroup', {
618+
application,
619+
deploymentGroupName: 'MyExistingDeploymentGroup',
620+
});
621+
```
622+
376623
## ECS Deployment Configurations
377624

378625
CodeDeploy for ECS comes with predefined configurations for traffic shifting.

0 commit comments

Comments
 (0)