How do I perform a blue/green deployment for zero-downtime releases?
In this guide, we will set up a blue/green deployment model to achieve zero-downtime releases. This approach helps ensure that end users experience no downtime while new versions of applications are being deployed. We will utilize AWS services such as EC2, Elastic Load Balancer (ALB), and ECS (Elastic Container Service).
Overview:
- EC2 Instances - Hosting two separate environments (Blue and Green).
- Application Load Balancer (ALB) - Routes traffic to either the Blue or Green environment.
- ECS Services - Deploy versions of the application to different target groups associated with the ALB.
import * as pulumi from "@pulumi/pulumi";
import * as aws from "@pulumi/aws";
import * as std from "@pulumi/std";
const main = new aws.ec2.Vpc("main", {cidrBlock: "10.0.0.0/16"});
const mainSubnet: aws.ec2.Subnet[] = [];
for (const range = {value: 0}; range.value < 2; range.value++) {
mainSubnet.push(new aws.ec2.Subnet(`main-${range.value}`, {
vpcId: main.id,
cidrBlock: std.cidrsubnetOutput({
input: main.cidrBlock,
newbits: 8,
netnum: range.value,
}).apply(invoke => invoke.result),
availabilityZone: [
"us-west-2a",
"us-west-2b",
][range.value],
}));
}
const albSg = new aws.ec2.SecurityGroup("alb_sg", {
vpcId: main.id,
ingress: [{
fromPort: 80,
toPort: 80,
protocol: "tcp",
cidrBlocks: ["0.0.0.0/0"],
}],
egress: [{
fromPort: 0,
toPort: 0,
protocol: "-1",
cidrBlocks: ["0.0.0.0/0"],
}],
});
const mainLoadBalancer = new aws.lb.LoadBalancer("main", {
name: "blue-green-alb",
internal: false,
loadBalancerType: "application",
securityGroups: [albSg.id],
subnets: mainSubnet.map(__item => __item.id),
});
const blue = new aws.lb.TargetGroup("blue", {
name: "blue-target-group",
port: 80,
protocol: "HTTP",
vpcId: main.id,
healthCheck: {
path: "/",
interval: 30,
timeout: 5,
unhealthyThreshold: 2,
healthyThreshold: 2,
},
});
const green = new aws.lb.TargetGroup("green", {
name: "green-target-group",
port: 80,
protocol: "HTTP",
vpcId: main.id,
healthCheck: {
path: "/",
interval: 30,
timeout: 5,
unhealthyThreshold: 2,
healthyThreshold: 2,
},
});
const http = new aws.lb.Listener("http", {
loadBalancerArn: mainLoadBalancer.arn,
port: 80,
protocol: "HTTP",
defaultActions: [{
type: "forward",
targetGroupArn: blue.arn,
}],
});
const mainCluster = new aws.ecs.Cluster("main", {name: "blue-green-cluster"});
const mainTaskDefinition = new aws.ecs.TaskDefinition("main", {
family: "my-task-def",
containerDefinitions: JSON.stringify([{
name: "my-app",
image: "nginx",
cpu: 256,
memory: 512,
essential: true,
portMappings: [{
containerPort: 80,
hostPort: 80,
protocol: "tcp",
}],
}]),
});
const blueService = new aws.ecs.Service("blue", {
name: "blue-service",
cluster: mainCluster.id,
taskDefinition: mainTaskDefinition.arn,
desiredCount: 1,
launchType: "EC2",
loadBalancers: [{
targetGroupArn: blue.arn,
containerName: "my-app",
containerPort: 80,
}],
});
const greenService = new aws.ecs.Service("green", {
name: "green-service",
cluster: mainCluster.id,
taskDefinition: mainTaskDefinition.arn,
desiredCount: 1,
launchType: "EC2",
loadBalancers: [{
targetGroupArn: green.arn,
containerName: "my-app",
containerPort: 80,
}],
});
export const loadBalancerDns = mainLoadBalancer.dnsName;
Key Points:
- AWS VPC and Subnets: We created a VPC to provide network resources and divided it into two subnets for high availability.
- Security Group: Configured a security group to allow HTTP traffic.
- Application Load Balancer (ALB): Deployed to distribute traffic based on the target group.
- Target Groups (Blue and Green): Defined to manage two separate versions of the application.
- ECS Cluster and Services: Set up an ECS cluster with ECS services pointing to the respective target groups.
Summary: In this deployment model, we set up an EC2-based infrastructure with an ALB that intelligently forwards requests to either the blue or green target groups. By switching the default target group of the ALB, we can smoothly perform a blue/green deployment, ensuring no downtime for users. This approach allows for easy rollback and independent testing of new features.
Deploy this code
Want to deploy this code? Sign up for a free Pulumi account to deploy in a few clicks.
Sign upNew to Pulumi?
Want to deploy this code? Sign up with Pulumi to deploy in a few clicks.
Sign upThank you for your feedback!
If you have a question about how to use Pulumi, reach out in Community Slack.
Open an issue on GitHub to report a problem or suggest an improvement.