Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
67 changes: 67 additions & 0 deletions terraform/aws/modules/composition/envoy-proxy/data.tf
Original file line number Diff line number Diff line change
@@ -1,3 +1,70 @@
# =========================================================================
# Data Sources
# =========================================================================

data "aws_region" "current" {}

data "aws_caller_identity" "current" {}

# =========================================================================
# Blue-Green Deployment Data Sources
# =========================================================================

# Find existing blue ASG for blue-green deployments
# This assumes the blue ASG is already tagged appropriately
data "aws_autoscaling_groups" "groups_blue" {

# Filter by common tags to find ASGs from this module
dynamic "filter" {
for_each = local.common_tags

content {
name = "tag:${filter.key}"
values = [filter.value]
}
}

# Filter specifically for blue deployment
filter {
name = "tag:Deployment"
values = ["blue"]
}
}

# Find existing green ASG for blue-green deployments
data "aws_autoscaling_groups" "groups_green" {

# Filter by common tags to find ASGs from this module
dynamic "filter" {
for_each = local.common_tags

content {
name = "tag:${filter.key}"
values = [filter.value]
}
}

# Filter specifically for blue deployment
filter {
name = "tag:Deployment"
values = ["green"]
}
}

# Get details of the blue ASG
data "aws_autoscaling_group" "asg_blue" {
count = length(data.aws_autoscaling_groups.groups_blue.names) > 0 ? 1 : 0
name = data.aws_autoscaling_groups.groups_blue.names[0]
}

# Get details of the green ASG
data "aws_autoscaling_group" "asg_green" {
count = length(data.aws_autoscaling_groups.groups_green.names) > 0 ? 1 : 0
name = data.aws_autoscaling_groups.groups_green.names[0]
}

# Reference to existing IAM role (if using existing)
data "aws_iam_role" "existing_envoy_role" {
count = var.create_iam_role ? 0 : 1
name = var.existing_iam_role_name
}
56 changes: 55 additions & 1 deletion terraform/aws/modules/composition/envoy-proxy/locals.tf
Original file line number Diff line number Diff line change
Expand Up @@ -65,5 +65,59 @@ locals {

# Launch Template selection - use created or existing
launch_template_id = var.use_existing_launch_template ? var.existing_launch_template_id : aws_launch_template.envoy[0].id
launch_template_version = var.use_existing_launch_template ? var.existing_launch_template_version : "$Latest"
launch_template_version = var.use_existing_launch_template ? var.existing_launch_template_version : aws_launch_template.envoy[0].latest_version

enable_bg_rollout = var.blue_green_rollout != null && length(try(data.aws_autoscaling_groups.groups_blue.names, [])) > 0

rollout_version = length(try(data.aws_autoscaling_groups.groups_blue.names, [])) > 0 ? (
tonumber(
try(
[for t in data.aws_autoscaling_group.asg_blue[0].tag : t.value if t.key == "Version"][0],
"0"
)
)
) : 0

standard_version = length(try(data.aws_autoscaling_groups.groups_green.names, [])) > 0 ? (
tonumber(
try(
[for t in data.aws_autoscaling_group.asg_green[0].tag : t.value if t.key == "Version"][0],
"0"
)
)
) : local.rollout_version

target_group_arns = var.create_target_group ? [aws_lb_target_group.envoy[local.standard_version].arn] : [var.existing_tg_arn]

deployments = local.enable_bg_rollout ? {
(local.rollout_version) = {
lt_version = data.aws_autoscaling_group.asg_blue[0].launch_template[0].version
lt_id = data.aws_autoscaling_group.asg_blue[0].launch_template[0].id
deployment = "blue"
target_group_arns = data.aws_autoscaling_group.asg_blue[0].target_group_arns
weight = var.blue_green_rollout.blue_weight
},
(local.rollout_version + 1) = {
lt_version = local.launch_template_version
lt_id = local.launch_template_id
deployment = "green"
target_group_arns = local.target_group_arns
weight = var.blue_green_rollout.green_weight
}
} : {
(local.standard_version) = {
lt_version = local.launch_template_version
lt_id = local.launch_template_id
deployment = "blue"
target_group_arns = local.target_group_arns
weight = 100
}
}

target_groups = local.enable_bg_rollout ? {
(local.rollout_version) = "blue",
(local.rollout_version + 1) = "green"
} : {
(local.standard_version) = "blue"
}
}
81 changes: 56 additions & 25 deletions terraform/aws/modules/composition/envoy-proxy/main.tf
Original file line number Diff line number Diff line change
Expand Up @@ -191,12 +191,6 @@ module "envoy_iam_role" {
tags = local.common_tags
}

# Reference to existing IAM role (if using existing)
data "aws_iam_role" "existing_envoy_role" {
count = var.create_iam_role ? 0 : 1
name = var.existing_iam_role_name
}

# Create a new instance profile for existing IAM role
# This allows you to reuse an existing IAM role but create a fresh instance profile
resource "aws_iam_instance_profile" "envoy_profile" {
Expand Down Expand Up @@ -366,9 +360,9 @@ module "alb" {
# Target group for ALB → Envoy ASG
# Targets Envoy traffic listener port
resource "aws_lb_target_group" "envoy" {
count = var.create_target_group ? 1 : 0
for_each = var.create_target_group ? local.target_groups : {}

name = "${local.name_prefix}-tg-${substr(md5("${var.target_group_protocol}-${var.envoy_traffic_port}"), 0, 6)}"
name = "${local.name_prefix}-tg-${substr(md5("${var.target_group_protocol}-${var.envoy_traffic_port}"), 0, 6)}-v${each.key}"
port = var.envoy_traffic_port
protocol = var.target_group_protocol # HTTP or HTTPS based on configuration
vpc_id = var.vpc_id
Expand All @@ -390,7 +384,9 @@ resource "aws_lb_target_group" "envoy" {
tags = merge(
local.common_tags,
{
Name = "${local.name_prefix}-tg"
Name = "${local.name_prefix}-tg"
Deployment = each.value
Version = each.key
}
)

Expand Down Expand Up @@ -426,8 +422,26 @@ resource "aws_lb_listener" "envoy_http" {
}
}

# Forward to target group (only used if type = "forward")
target_group_arn = var.enable_https_listener && var.enable_http_to_https_redirect ? null : (var.create_target_group ? aws_lb_target_group.envoy[0].arn : var.existing_tg_arn)
# Weighted Forward block (used only when not redirecting)
dynamic "forward" {
for_each = !(var.enable_https_listener && var.enable_http_to_https_redirect) ? [1] : []
content {

# Canary target group (optional)
dynamic "target_group" {
for_each = local.deployments
content {
arn = each.value.target_group_arns[0]
weight = each.value.weight
}
}

stickiness {
enabled = false
duration = 1
}
}
}
}

tags = local.common_tags
Expand All @@ -444,8 +458,23 @@ resource "aws_lb_listener" "envoy_https" {
certificate_arn = var.ssl_certificate_arn

default_action {
type = "forward"
target_group_arn = var.create_target_group ? aws_lb_target_group.envoy[0].arn : var.existing_tg_arn
type = "forward"

forward {

dynamic "target_group" {
for_each = local.deployments
content {
arn = each.value.target_group_arns[0]
weight = each.value.weight
}
}

stickiness {
enabled = false
duration = 1
}
}
}

tags = local.common_tags
Expand Down Expand Up @@ -620,13 +649,15 @@ resource "aws_launch_template" "envoy" {
# Auto Scaling Group
# =========================================================================
module "asg" {
for_each = local.deployments

source = "terraform-aws-modules/autoscaling/aws"
version = "~> 7.0"

# Ensure S3 config files are uploaded before ASG starts
depends_on = [aws_s3_object.envoy_config_files]
depends_on = [aws_s3_object.envoy_config_files, aws_launch_template.envoy]

name = "${local.name_prefix}-asg"
name = "${local.name_prefix}-asg-v${each.key}"

# =========================================================================
# Launch Template Configuration Strategy
Expand All @@ -646,8 +677,8 @@ module "asg" {
# Always use a launch template (either existing or our created one)
# This prevents the ASG module from creating its own launch template
create_launch_template = false
launch_template_id = local.launch_template_id
launch_template_version = local.launch_template_version
launch_template_id = each.value.lt_id
launch_template_version = each.value.lt_version

# For mixed instances policy (spot enabled)
mixed_instances_policy = var.enable_spot_instances ? {
Expand Down Expand Up @@ -676,7 +707,7 @@ module "asg" {
default_cooldown = 300

# Target groups
target_group_arns = [var.create_target_group ? aws_lb_target_group.envoy[0].arn : var.existing_tg_arn]
target_group_arns = each.value.target_group_arns

# Termination and lifecycle
termination_policies = var.termination_policies
Expand All @@ -695,7 +726,7 @@ module "asg" {
# Scaling policies - Created separately below

# Tags
tags = local.common_tags
tags = merge(local.common_tags, { Deployment = each.value.deployment, Version = each.key })
}

# =========================================================================
Expand All @@ -704,10 +735,10 @@ module "asg" {

# CPU Target Tracking Scaling Policy
resource "aws_autoscaling_policy" "cpu_target_tracking" {
count = var.enable_autoscaling && var.scaling_policies.cpu_target_tracking.enabled ? 1 : 0
for_each = var.enable_autoscaling && var.scaling_policies.cpu_target_tracking.enabled ? local.deployments : {}

name = "${local.name_prefix}-cpu-target-tracking"
autoscaling_group_name = module.asg.autoscaling_group_name
autoscaling_group_name = module.asg[each.key].autoscaling_group_name
policy_type = "TargetTrackingScaling"

target_tracking_configuration {
Expand All @@ -720,10 +751,10 @@ resource "aws_autoscaling_policy" "cpu_target_tracking" {

# Memory Target Tracking Scaling Policy
resource "aws_autoscaling_policy" "memory_target_tracking" {
count = var.enable_autoscaling && var.scaling_policies.memory_target_tracking.enabled ? 1 : 0
for_each = var.enable_autoscaling && var.scaling_policies.memory_target_tracking.enabled ? local.deployments : {}

name = "${local.name_prefix}-memory-target-tracking"
autoscaling_group_name = module.asg.autoscaling_group_name
name = "${local.name_prefix}-memory-target-tracking-${each.key}"
autoscaling_group_name = module.asg[each.key].autoscaling_group_name
policy_type = "TargetTrackingScaling"

target_tracking_configuration {
Expand All @@ -736,7 +767,7 @@ resource "aws_autoscaling_policy" "memory_target_tracking" {
metric_name = "mem_used_percent"
dimensions {
name = "AutoScalingGroupName"
value = module.asg.autoscaling_group_name
value = module.asg[each.key].autoscaling_group_name
}
}
stat = "Average"
Expand Down
22 changes: 13 additions & 9 deletions terraform/aws/modules/composition/envoy-proxy/outputs.tf
Original file line number Diff line number Diff line change
Expand Up @@ -13,9 +13,9 @@ output "lb_zone_id" {
value = var.create_lb ? module.alb[0].zone_id : null
}

output "target_group_arn" {
description = "ARN of the target group"
value = var.create_target_group ? aws_lb_target_group.envoy[0].arn : var.existing_tg_arn
output "target_group_arns" {
description = "Map of deployment names to target group ARNs"
value = { for v in local.deployments : v.deployment => v.target_group_arns }
}

output "launch_template_id" {
Expand All @@ -33,14 +33,18 @@ output "launch_template_created" {
value = !var.use_existing_launch_template
}

output "asg_id" {
description = "ID of the Auto Scaling Group"
value = module.asg.autoscaling_group_id
output "asg_ids" {
description = "Map of deployment names to Auto Scaling Group IDs"
value = {
for k, v in module.asg : local.deployments[k].deployment => v.autoscaling_group_id
}
}

output "asg_name" {
description = "Name of the Auto Scaling Group"
value = module.asg.autoscaling_group_name
output "asg_names" {
description = "Map of deployment names to Auto Scaling Group names"
value = {
for k, v in module.asg : local.deployments[k].deployment => v.autoscaling_group_name
}
}

output "asg_security_group_id" {
Expand Down
25 changes: 17 additions & 8 deletions terraform/aws/modules/composition/envoy-proxy/variables.tf
Original file line number Diff line number Diff line change
Expand Up @@ -37,10 +37,10 @@ variable "lb_ingress_rules" {
from_port = number
to_port = number
protocol = string
cidr = optional(list(string)) # IPv4 CIDR blocks (e.g., ["0.0.0.0/0"])
ipv6_cidr = optional(list(string)) # IPv6 CIDR blocks (e.g., ["::/0"])
sg_id = optional(list(string)) # Security Group IDs
prefix_list_ids = optional(list(string)) # VPC Endpoint Prefix Lists (e.g., ["pl-6ea54007"])
cidr = optional(list(string)) # IPv4 CIDR blocks (e.g., ["0.0.0.0/0"])
ipv6_cidr = optional(list(string)) # IPv6 CIDR blocks (e.g., ["::/0"])
sg_id = optional(list(string)) # Security Group IDs
prefix_list_ids = optional(list(string)) # VPC Endpoint Prefix Lists (e.g., ["pl-6ea54007"])
}))
default = []
}
Expand All @@ -52,10 +52,10 @@ variable "lb_egress_rules" {
from_port = number
to_port = number
protocol = string
cidr = optional(list(string)) # IPv4 CIDR blocks (e.g., ["0.0.0.0/0"])
ipv6_cidr = optional(list(string)) # IPv6 CIDR blocks (e.g., ["::/0"])
sg_id = optional(list(string)) # Security Group IDs
prefix_list_ids = optional(list(string)) # VPC Endpoint Prefix Lists (e.g., ["pl-6ea54007"])
cidr = optional(list(string)) # IPv4 CIDR blocks (e.g., ["0.0.0.0/0"])
ipv6_cidr = optional(list(string)) # IPv6 CIDR blocks (e.g., ["::/0"])
sg_id = optional(list(string)) # Security Group IDs
prefix_list_ids = optional(list(string)) # VPC Endpoint Prefix Lists (e.g., ["pl-6ea54007"])
}))
default = []
}
Expand Down Expand Up @@ -224,6 +224,15 @@ variable "existing_launch_template_version" {
default = "$Latest"
}

variable "blue_green_rollout" {
description = "Blue-green rollout configuration for Envoy"
type = object({
blue_weight = number,
green_weight = number
})
default = null
}

# =========================================================================
# Launch Template Advanced Configuration (ignored if use_existing_launch_template = true)
# =========================================================================
Expand Down