Skip navigation links

Package software.amazon.awscdk.services.codedeploy

AWS CodeDeploy Construct Library

See: Description

Package software.amazon.awscdk.services.codedeploy Description

AWS CodeDeploy Construct Library

---

cfn-resources: Stable

cdk-constructs: Stable


AWS CodeDeploy is a deployment service that automates application deployments to Amazon EC2 instances, on-premises instances, serverless Lambda functions, or Amazon ECS services.

The CDK currently supports Amazon EC2, on-premise and AWS Lambda applications.

EC2/on-premise Applications

To create a new CodeDeploy Application that deploys to EC2/on-premise instances:

 ServerApplication application = ServerApplication.Builder.create(this, "CodeDeployApplication")
         .applicationName("MyApplication")
         .build();
 

To import an already existing Application:

 IServerApplication application = ServerApplication.fromServerApplicationName(this, "ExistingCodeDeployApplication", "MyExistingApplication");
 

EC2/on-premise Deployment Groups

To create a new CodeDeploy Deployment Group that deploys to EC2/on-premise instances:

 import software.amazon.awscdk.services.autoscaling.*;
 import software.amazon.awscdk.services.cloudwatch.*;
 
 ServerApplication application;
 AutoScalingGroup asg;
 Alarm alarm;
 
 ServerDeploymentGroup deploymentGroup = ServerDeploymentGroup.Builder.create(this, "CodeDeployDeploymentGroup")
         .application(application)
         .deploymentGroupName("MyDeploymentGroup")
         .autoScalingGroups(List.of(asg))
         // adds User Data that installs the CodeDeploy agent on your auto-scaling groups hosts
         // default: true
         .installAgent(true)
         // adds EC2 instances matching tags
         .ec2InstanceTags(new InstanceTagSet(Map.of(
                 // any instance with tags satisfying
                 // key1=v1 or key1=v2 or key2 (any value) or value v3 (any key)
                 // will match this group
                 "key1", List.of("v1", "v2"),
                 "key2", List.of(),
                 "", List.of("v3"))))
         // adds on-premise instances matching tags
         .onPremiseInstanceTags(new InstanceTagSet(Map.of(
                 "key1", List.of("v1", "v2")), Map.of(
                 "key2", List.of("v3"))))
         // CloudWatch alarms
         .alarms(List.of(alarm))
         // whether to ignore failure to fetch the status of alarms from CloudWatch
         // default: false
         .ignorePollAlarmsFailure(false)
         // auto-rollback configuration
         .autoRollback(AutoRollbackConfig.builder()
                 .failedDeployment(true) // default: true
                 .stoppedDeployment(true) // default: false
                 .deploymentInAlarm(true)
                 .build())
         .build();
 

All properties are optional - if you don't provide an Application, one will be automatically created.

To import an already existing Deployment Group:

 ServerApplication application;
 
 IServerDeploymentGroup deploymentGroup = ServerDeploymentGroup.fromServerDeploymentGroupAttributes(this, "ExistingCodeDeployDeploymentGroup", ServerDeploymentGroupAttributes.builder()
         .application(application)
         .deploymentGroupName("MyExistingDeploymentGroup")
         .build());
 

Load balancers

You can specify a load balancer with the loadBalancer property when creating a Deployment Group.

LoadBalancer is an abstract class with static factory methods that allow you to create instances of it from various sources.

With Classic Elastic Load Balancer, you provide it directly:

 import software.amazon.awscdk.services.elasticloadbalancing.*;
 
 LoadBalancer lb;
 
 lb.addListener(LoadBalancerListener.builder()
         .externalPort(80)
         .build());
 
 ServerDeploymentGroup deploymentGroup = ServerDeploymentGroup.Builder.create(this, "DeploymentGroup")
         .loadBalancer(LoadBalancer.classic(lb))
         .build();
 

With Application Load Balancer or Network Load Balancer, you provide a Target Group as the load balancer:

 import software.amazon.awscdk.services.elasticloadbalancingv2.*;
 
 ApplicationLoadBalancer alb;
 
 ApplicationListener listener = alb.addListener("Listener", BaseApplicationListenerProps.builder().port(80).build());
 ApplicationTargetGroup targetGroup = listener.addTargets("Fleet", AddApplicationTargetsProps.builder().port(80).build());
 
 ServerDeploymentGroup deploymentGroup = ServerDeploymentGroup.Builder.create(this, "DeploymentGroup")
         .loadBalancer(LoadBalancer.application(targetGroup))
         .build();
 

Deployment Configurations

You can also pass a Deployment Configuration when creating the Deployment Group:

 ServerDeploymentGroup deploymentGroup = ServerDeploymentGroup.Builder.create(this, "CodeDeployDeploymentGroup")
         .deploymentConfig(ServerDeploymentConfig.ALL_AT_ONCE)
         .build();
 

The default Deployment Configuration is ServerDeploymentConfig.ONE_AT_A_TIME.

You can also create a custom Deployment Configuration:

 ServerDeploymentConfig deploymentConfig = ServerDeploymentConfig.Builder.create(this, "DeploymentConfiguration")
         .deploymentConfigName("MyDeploymentConfiguration") // optional property
         // one of these is required, but both cannot be specified at the same time
         .minimumHealthyHosts(MinimumHealthyHosts.count(2))
         .build();
 

Or import an existing one:

 IServerDeploymentConfig deploymentConfig = ServerDeploymentConfig.fromServerDeploymentConfigName(this, "ExistingDeploymentConfiguration", "MyExistingDeploymentConfiguration");
 

Lambda Applications

To create a new CodeDeploy Application that deploys to a Lambda function:

 LambdaApplication application = LambdaApplication.Builder.create(this, "CodeDeployApplication")
         .applicationName("MyApplication")
         .build();
 

To import an already existing Application:

 ILambdaApplication application = LambdaApplication.fromLambdaApplicationName(this, "ExistingCodeDeployApplication", "MyExistingApplication");
 

Lambda Deployment Groups

To enable traffic shifting deployments for Lambda functions, CodeDeploy uses Lambda Aliases, which can balance incoming traffic between two different versions of your function. Before deployment, the alias sends 100% of invokes to the version used in production. When you publish a new version of the function to your stack, CodeDeploy will send a small percentage of traffic to the new version, monitor, and validate before shifting 100% of traffic to the new version.

To create a new CodeDeploy Deployment Group that deploys to a Lambda function:

 LambdaApplication myApplication;
 Function func;
 
 Version version = func.getCurrentVersion();
 Alias version1Alias = Alias.Builder.create(this, "alias")
         .aliasName("prod")
         .version(version)
         .build();
 
 LambdaDeploymentGroup deploymentGroup = LambdaDeploymentGroup.Builder.create(this, "BlueGreenDeployment")
         .application(myApplication) // optional property: one will be created for you if not provided
         .alias(version1Alias)
         .deploymentConfig(LambdaDeploymentConfig.LINEAR_10PERCENT_EVERY_1MINUTE)
         .build();
 

In order to deploy a new version of this function:

  1. Reference the version with the latest changes const version = func.currentVersion.
  2. Re-deploy the stack (this will trigger a deployment).
  3. Monitor the CodeDeploy deployment as traffic shifts between the versions.

Create a custom Deployment Config

CodeDeploy for Lambda comes with built-in configurations for traffic shifting. If you want to specify your own strategy, you can do so with the CustomLambdaDeploymentConfig construct, letting you specify precisely how fast a new function version is deployed.

 LambdaApplication application;
 Alias alias;
 CustomLambdaDeploymentConfig config = CustomLambdaDeploymentConfig.Builder.create(this, "CustomConfig")
         .type(CustomLambdaDeploymentConfigType.CANARY)
         .interval(Duration.minutes(1))
         .percentage(5)
         .build();
 LambdaDeploymentGroup deploymentGroup = LambdaDeploymentGroup.Builder.create(this, "BlueGreenDeployment")
         .application(application)
         .alias(alias)
         .deploymentConfig(config)
         .build();
 

You can specify a custom name for your deployment config, but if you do you will not be able to update the interval/percentage through CDK.

 CustomLambdaDeploymentConfig config = CustomLambdaDeploymentConfig.Builder.create(this, "CustomConfig")
         .type(CustomLambdaDeploymentConfigType.CANARY)
         .interval(Duration.minutes(1))
         .percentage(5)
         .deploymentConfigName("MyDeploymentConfig")
         .build();
 

Rollbacks and Alarms

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

 import software.amazon.awscdk.services.cloudwatch.*;
 
 Alias alias;
 
 // or add alarms to an existing group
 Alias blueGreenAlias;
 
 Alarm alarm = Alarm.Builder.create(this, "Errors")
         .comparisonOperator(ComparisonOperator.GREATER_THAN_THRESHOLD)
         .threshold(1)
         .evaluationPeriods(1)
         .metric(alias.metricErrors())
         .build();
 LambdaDeploymentGroup deploymentGroup = LambdaDeploymentGroup.Builder.create(this, "BlueGreenDeployment")
         .alias(alias)
         .deploymentConfig(LambdaDeploymentConfig.LINEAR_10PERCENT_EVERY_1MINUTE)
         .alarms(List.of(alarm))
         .build();
 deploymentGroup.addAlarm(Alarm.Builder.create(this, "BlueGreenErrors")
         .comparisonOperator(ComparisonOperator.GREATER_THAN_THRESHOLD)
         .threshold(1)
         .evaluationPeriods(1)
         .metric(blueGreenAlias.metricErrors())
         .build());
 

Pre and Post Hooks

CodeDeploy allows you to run an arbitrary Lambda function before traffic shifting actually starts (PreTraffic Hook) and after it completes (PostTraffic Hook). With either hook, you have the opportunity to run logic that determines whether the deployment must succeed or fail. For example, with PreTraffic hook you could run integration tests against the newly created Lambda version (but not serving traffic). With PostTraffic hook, you could run end-to-end validation checks.

 Function warmUpUserCache;
 Function endToEndValidation;
 Alias alias;
 
 
 // pass a hook whe creating the deployment group
 LambdaDeploymentGroup deploymentGroup = LambdaDeploymentGroup.Builder.create(this, "BlueGreenDeployment")
         .alias(alias)
         .deploymentConfig(LambdaDeploymentConfig.LINEAR_10PERCENT_EVERY_1MINUTE)
         .preHook(warmUpUserCache)
         .build();
 
 // or configure one on an existing deployment group
 deploymentGroup.addPostHook(endToEndValidation);
 

Import an existing Deployment Group

To import an already existing Deployment Group:

 LambdaApplication application;
 
 ILambdaDeploymentGroup deploymentGroup = LambdaDeploymentGroup.fromLambdaDeploymentGroupAttributes(this, "ExistingCodeDeployDeploymentGroup", LambdaDeploymentGroupAttributes.builder()
         .application(application)
         .deploymentGroupName("MyExistingDeploymentGroup")
         .build());
 
Skip navigation links