Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Enable redis-sentinel module #343

Open
wants to merge 8 commits into
base: main
Choose a base branch
from
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
11 changes: 10 additions & 1 deletion locals.tf
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,16 @@ locals {
}
)

redis = try(
redis = var.enable_redis_sentinel ? try(
module.redis_sentinel[0],
{
hostname = null
password = null
redis_port = null
use_password_auth = null
use_tls = null
}
) : try(
module.redis[0],
{
hostname = null
Expand Down
25 changes: 24 additions & 1 deletion main.tf
Original file line number Diff line number Diff line change
Expand Up @@ -71,7 +71,7 @@ module "networking" {
# -----------------------------------------------------------------------------
module "redis" {
source = "./modules/redis"
count = local.enable_redis_module ? 1 : 0
count = local.enable_redis_module && var.enable_redis_sentinel == false ? 1 : 0

active_active = var.operational_mode == "active-active"
friendly_name_prefix = var.friendly_name_prefix
Expand All @@ -91,6 +91,29 @@ module "redis" {
redis_port = var.redis_encryption_in_transit ? "6380" : "6379"
}

# -----------------------------------------------------------------------------
# Redis Sentinel
# -----------------------------------------------------------------------------

module "redis_sentinel" {
count = var.enable_redis_sentinel ? 1 : 0
source = "./modules/redis-sentinel"

domain_name = var.domain_name

aws_iam_instance_profile = module.service_accounts.iam_instance_profile.name
asg_tags = var.asg_tags
ec2_launch_template_tag_specifications = var.ec2_launch_template_tag_specifications
friendly_name_prefix = var.friendly_name_prefix
health_check_grace_period = var.health_check_grace_period
health_check_type = var.health_check_type
instance_type = var.instance_type
key_name = var.key_name
network_id = local.network_id
network_subnets_private = local.network_private_subnets
network_private_subnet_cidrs = local.network_private_subnet_cidrs
}

# -----------------------------------------------------------------------------
# AWS PostreSQL Database
# -----------------------------------------------------------------------------
Expand Down
79 changes: 79 additions & 0 deletions modules/redis-sentinel/compose.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,79 @@
# Description: This file contains the docker-compose configuration for the redis-sentinel module.
services:
redis-leader:
container_name: redis-leader
command: "redis-server --appendonly yes --requirepass ${redis_sentinel_password}"
image: redis:7
ports :
- ${redis_port}:${redis_port}
redis-follower-1:
container_name: redis-follower-1
depends_on:
- redis-leader
command: "redis-server --replicaof redis-leader ${redis_port} --requirepass ${redis_password} --masterauth ${redis_sentinel_password}"
image: redis:7
ports :
- 6380:${redis_port}
redis-follower-2:
container_name: redis-follower-2
depends_on:
- redis-leader
command: "redis-server --replicaof redis-leader ${redis_port} --requirepass ${redis_password} --masterauth ${redis_sentinel_password}"
image: redis:7
ports :
- 6381:${redis_port}
redis-sentinel-1:
container_name: redis-sentinel-1
depends_on:
- redis-leader
- redis-follower-1
- redis-follower-2
command: >
sh -c 'echo "sentinel resolve-hostnames yes" > /etc/sentinel.conf &&
echo "sentinel monitor ${redis_sentinel_leader_name} redis-leader 6379 2" >> /etc/sentinel.conf &&
echo "sentinel auth-pass ${redis_sentinel_leader_name} ${redis_sentinel_password}" >> /etc/sentinel.conf &&
echo "sentinel down-after-milliseconds ${redis_sentinel_leader_name} 5000" >> /etc/sentinel.conf &&
echo "sentinel failover-timeout ${redis_sentinel_leader_name} 10000" >> /etc/sentinel.conf &&
echo "loglevel notice" >> /etc/sentinel.conf &&
echo "sentinel deny-scripts-reconfig yes" >> /etc/sentinel.conf &&
redis-sentinel /etc/sentinel.conf'
image: redis:7
ports:
- ${redis_sentinel_port}:${redis_sentinel_port}
redis-sentinel-2:
container_name: redis-sentinel-2
depends_on:
- redis-leader
- redis-follower-1
- redis-follower-2
command: >
sh -c 'echo "sentinel resolve-hostnames yes" > /etc/sentinel.conf &&
echo "sentinel monitor ${redis_sentinel_leader_name} redis-leader 6379 2" >> /etc/sentinel.conf &&
echo "sentinel auth-pass ${redis_sentinel_leader_name} ${redis_sentinel_password}" >> /etc/sentinel.conf &&
echo "sentinel down-after-milliseconds ${redis_sentinel_leader_name} 5000" >> /etc/sentinel.conf &&
echo "sentinel failover-timeout ${redis_sentinel_leader_name} 10000" >> /etc/sentinel.conf &&
echo "loglevel notice" >> /etc/sentinel.conf &&
echo "sentinel deny-scripts-reconfig yes" >> /etc/sentinel.conf &&
redis-sentinel /etc/sentinel.conf'
image: redis:7
ports:
- 26380:${redis_sentinel_port}
redis-sentinel-3:
container_name: redis-sentinel-3
depends_on:
- redis-leader
- redis-follower-1
- redis-follower-2
command: >
sh -c 'echo "sentinel resolve-hostnames yes" > /etc/sentinel.conf &&
sandrampeter marked this conversation as resolved.
Show resolved Hide resolved
echo "sentinel monitor ${redis_sentinel_leader_name} redis-leader 6379 2" >> /etc/sentinel.conf &&
echo "sentinel auth-pass ${redis_sentinel_leader_name} ${redis_sentinel_password}" >> /etc/sentinel.conf &&
echo "sentinel down-after-milliseconds ${redis_sentinel_leader_name} 5000" >> /etc/sentinel.conf &&
echo "sentinel failover-timeout ${redis_sentinel_leader_name} 10000" >> /etc/sentinel.conf &&
echo "loglevel notice" >> /etc/sentinel.conf &&
echo "sentinel deny-scripts-reconfig yes" >> /etc/sentinel.conf &&
redis-sentinel /etc/sentinel.conf'
image: redis:7
ports:
- 26381:${redis_sentinel_port}

50 changes: 50 additions & 0 deletions modules/redis-sentinel/locals.tf
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
# Copyright (c) HashiCorp, Inc.
# SPDX-License-Identifier: MPL-2.0

locals {
redis_user_data_template = "${path.module}/script.sh"
redis_leader_user_data = templatefile(local.redis_user_data_template, {

compose = base64encode(templatefile(local.compose_path, {
redis_sentinel_password = var.redis_sentinel_password
redis_sentinel_leader_name = var.redis_sentinel_leader_name
redis_sentinel_port = var.redis_sentinel_port
redis_port = var.redis_port
redis_password = var.redis_password
})) })
compose_path = "${path.module}/compose.yaml"
tags = concat(
[
{
key = "Name"
value = "${var.friendly_name_prefix}-tfe"
propagate_at_launch = true
},
],
[
for k, v in var.asg_tags : {
key = k
value = v
propagate_at_launch = true
}
]
)
default_health_check_grace_period = 1500
health_check_grace_period = var.health_check_grace_period != null ? var.health_check_grace_period : local.default_health_check_grace_period
}

data "aws_ami" "ubuntu" {
most_recent = true

filter {
name = "name"
values = ["ubuntu/images/hvm-ssd/ubuntu-focal-20.04-amd64-server-*"]
}

filter {
name = "virtualization-type"
values = ["hvm"]
}

owners = ["099720109477"] # Canonical
}
86 changes: 86 additions & 0 deletions modules/redis-sentinel/main.tf
Original file line number Diff line number Diff line change
@@ -0,0 +1,86 @@
# Copyright (c) HashiCorp, Inc.
# SPDX-License-Identifier: MPL-2.0


# Launch Template for Redis Sentinel
# ----------------------------------

resource "aws_launch_template" "redis_sentinel_leader" {
name_prefix = "${var.friendly_name_prefix}-redis-sentinel-leader"
image_id = data.aws_ami.ubuntu.id
instance_type = var.instance_type
user_data = base64encode(local.redis_leader_user_data)
key_name = var.key_name
vpc_security_group_ids = [aws_security_group.redis_sentinel_inbound_allow.id, aws_security_group.redis_sentinel_outbound_allow.id]

dynamic "tag_specifications" {
for_each = var.ec2_launch_template_tag_specifications

content {
resource_type = tag_specifications.value["resource_type"]
tags = tag_specifications.value["tags"]
}
}

iam_instance_profile {
name = var.aws_iam_instance_profile
}

metadata_options {
http_endpoint = "enabled"
http_put_response_hop_limit = 2
http_tokens = "optional"
}

block_device_mappings {
device_name = "/dev/sda1"
ebs {
encrypted = true
volume_type = "gp2"
volume_size = 50
delete_on_termination = true
}
}

lifecycle {
create_before_destroy = true
}
}

# Autoscaling Group for Redis Sentinel
# ------------------------------------

resource "aws_autoscaling_group" "redis_sentinel" {
name = "${var.friendly_name_prefix}-redis-sentinel-leader-asg"
min_size = 1
max_size = 1
desired_capacity = 1
vpc_zone_identifier = var.network_subnets_private
target_group_arns = [aws_lb_target_group.redis_sentinel_tg_6379.arn,
aws_lb_target_group.redis_sentinel_tg_26379.arn
]

# Increases grace period for any AMI that is not the default Ubuntu
# since RHEL has longer startup time
health_check_grace_period = local.health_check_grace_period
health_check_type = var.health_check_type

launch_template {
id = aws_launch_template.redis_sentinel_leader.id
version = "$Latest"
}

dynamic "tag" {
for_each = local.tags

content {
key = tag.value["key"]
value = tag.value["value"]
propagate_at_launch = tag.value["propagate_at_launch"]
}
}

lifecycle {
create_before_destroy = true
}
}
75 changes: 75 additions & 0 deletions modules/redis-sentinel/networking.tf
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
## DNS Record for Redis Sentinel cluster Load Balancer
# ----------------------------------------------------
data "aws_route53_zone" "tfe" {
name = var.domain_name
private_zone = false
}

resource "aws_route53_record" "sentinel" {
zone_id = data.aws_route53_zone.tfe.zone_id
name = "${var.friendly_name_prefix}-redis-sentinel"
type = "A"

alias {
name = aws_lb.redis_sentinel_lb.dns_name
zone_id = aws_lb.redis_sentinel_lb.zone_id
evaluate_target_health = true
}
}

# Network Load Balancer for Redis Sentinel cluster
# ------------------------------------------------

resource "aws_lb" "redis_sentinel_lb" {
name = "${var.friendly_name_prefix}-redis-sentinel-nlb"
internal = true
load_balancer_type = "network"
subnets = var.network_subnets_private
}

# Network Load Balancer Listener and Target Group for Redis and Sentinel
# ----------------------------------------------------------------------

resource "aws_lb_listener" "redis_sentinel_listener_6379" {
load_balancer_arn = aws_lb.redis_sentinel_lb.arn
port = 6379
protocol = "TCP"

default_action {
type = "forward"
target_group_arn = aws_lb_target_group.redis_sentinel_tg_6379.arn
}
}

resource "aws_lb_target_group" "redis_sentinel_tg_6379" {
name = "${var.friendly_name_prefix}-redis-sentinel-tg-6379"
port = 6379
protocol = "TCP"
vpc_id = var.network_id

health_check {
protocol = "TCP"
}
}

resource "aws_lb_listener" "redis_sentinel_listener_26379" {
load_balancer_arn = aws_lb.redis_sentinel_lb.arn
port = 26379
protocol = "TCP"

default_action {
type = "forward"
target_group_arn = aws_lb_target_group.redis_sentinel_tg_26379.arn
}
}

resource "aws_lb_target_group" "redis_sentinel_tg_26379" {
name = "${var.friendly_name_prefix}-redis-sentinel-tg-26379"
port = 26379
protocol = "TCP"
vpc_id = var.network_id

health_check {
protocol = "TCP"
}
}
39 changes: 39 additions & 0 deletions modules/redis-sentinel/outputs.tf
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
output "hostname" {
value = aws_route53_record.sentinel.fqdn
description = "The hostname of the Redis Sentinel"
}

output "redis_port" {
value = var.redis_port
description = "The port of the Redis"
}

output "redis_sentinel_port" {
value = var.redis_sentinel_port
description = "The port of the Redis Sentinel"
}

output "redis_sentinel_leader_name" {
value = var.redis_sentinel_leader_name
description = "The name of the Redis Sentinel leader"
}

output "redis_sentinel_password" {
value = var.redis_sentinel_password
description = "value of the Redis Sentinel password"
}

output "password" {
value = var.redis_password
description = "value of the Redis password"
}

output "use_password_auth" {
value = var.redis_use_password_auth ? true : false
description = "A boolean which indicates if password authentication is required by the Redis"
}

output "use_tls" {
value = var.use_tls ? true : false
description = "A boolean which indicates if TLS is required by the Redis"
}
Loading
Loading