Skip to content

Instantly share code, notes, and snippets.

@grubernaut
Last active September 27, 2020 17:57
Show Gist options
  • Save grubernaut/2dc93ea62f018444f10b to your computer and use it in GitHub Desktop.
Save grubernaut/2dc93ea62f018444f10b to your computer and use it in GitHub Desktop.
Blue Green Deploys with Terraform

Terraform Blue-Green Deploy example

Note: Use Terraform Modules as functions!!!

This will allow you to create a "networking" module, and use those outputs to populate the security groups, access zones, and subnet id's for your other modules.

Using autoscaling groups with a fixed size will protect you from AWs bugs or instance outages. This way an instance that dies, will be replaced so you always maintain the expected amount of instances for that service.

Workflow:

Given that 'blue-ami-id' = 2; green-ami-id = 1; blue-nodes = 3; and green-nodes = 0

  • Create a new AMI using Packer (pretend this has an ami-id = 3
  • Update green-ami-id to equal 3
  • Slowly scale up green-nodes, using green-nodes as a canary for the new service version
  • Once health checks (whatever user requires: consul, sensu, nagios, etc) pass
  • Slowly scale down blud-nodes to 0.

If everything checks out, you've just rolled instances with Terraform using a Blue-Green deploy!

// Note: Actual filepath for this file would be './awesome-service/main.tf'
variable "security_group" { }
variable "vpc_id" { }
variable "azs" { }
variable "subnet_ids" { }
variable "ami_blue" { }
variable "ami_green" { }
variable "nodes_blue" { }
variable "nodes_green" { }
// BLUE Resources
resource "aws_launch_configuration" "awesome-service-blue" {
image_id = "${var.ami_blue}"
instance_type = "t2.small"
key_name = "${var.key_name}"
security_groups = ["${var.security_group}"]
}
resource "aws_autoscaling_group" "awesome-service-blue" {
name = "awesome-service-blue - ${aws_launch_configuration.awesome-service-blue.name}"
launch_configuration = "${aws_launch_configuration.awesome-service-blue.name}"
desired_capacity = "${var.nodes_blue}"
min_size = "${var.nodes_blue}"
max_size = "${var.nodes_blue}"
availability_zones = ["${split(",", var.azs)}"]
vpc_zone_identifier = ["${split(",", var.subnet_ids)}"]
}
// Green Resources
resource "aws_launch_configuration" "awesome-service-green" {
image_id = "${var.ami_green}"
instance_type = "t2.small"
key_name = "${var.key_name}"
security_groups = ["${var.security_group}"]
}
resource "aws_autoscaling_group" "awesome-service-green" {
name = "awesome-service-green - ${aws_launch_configuration.awesome-service-green.name}"
launch_configuration = "${aws_launch_configuration.awesome-service-green.name}"
desired_capacity = "${var.nodes_green}"
min_size = "${var.nodes_green}"
max_size = "${var.nodes_green}"
availability_zones = ["${split(",", var.azs)}"]
vpc_zone_identifier = ["${split(",", var.subnet_ids)}"]
}
module "my-awesome-service" {
source = "./awesome-service
ami_blue = "<blue_ami_id>"
ami_green = "<green_ami_id>"
nodes_blue = <number_of_blue_nodes>
nodes_green = <number_of_green_nodes>
azs = "${var.azs}" // Use an output from another module for this
subnet_ids = "${var.subnet_ids}" // Use an output from another module for this
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment