Description
Hi *,
I'm still trying to wrap my head around the above setup. There is a github repo (https://github.com/tritonDataCenter/triton-redis-cluster), that sets up a replicating redis sentinel cluster on Triton Datacenter. It basically patches the redis.conf depending from the fact, that a master already exists (or not).
As I understand, sentinel is managing the cluster after the initial setup.
Thus you just create one node first (count = 1) and then scale up afterwards.
I guess, that should be somehow be doable maybe with lifecycle tasks and templates. I don't know, wether (consul?) DNS is even needed.
If that works, you might even be able to use autoscaling to expand the number of cluster nodes dynamically.
I tried to get Qwen3.6 to spit something out along those lines. But obviously there is no such thing as Nomad DNS but maybe one could use IP addresses, too:
# redis-sentinel-replicated.nomad
# Enhanced Nomad job: 3 Redis nodes (1 master + 2 replicas) + 3 Sentinel nodes
# Inspired by tritonDataCenter/triton-redis-cluster replication pattern
job "redis-sentinel-replicated" {
datacenters = ["dc1"]
type = "service"
# ──────────────────────────────────────────────────────────────────────────────
# REDIS CLUSTER (Master + Replicas)
# ──────────────────────────────────────────────────────────────────────────────
group "redis" {
count = 3
restart {
attempts = 3
interval = "5m"
delay = "15s"
mode = "delay"
}
task "redis" {
driver = "docker"
config {
image = "redis:7-alpine"
network_mode = "bridge"
port_map = { redis = 6379 }
}
ports = ["redis"]
# Persistent volume for replication durability
volume "redis_data" {
source = "redis_data"
target = "/data"
}
# Dynamic config: Index 0 → Master, Others → Replica
template {
data = <<-EOT
port 6379
bind 0.0.0.0
protected-mode no
requirepass {{ env "REDIS_PASSWORD" | default "SecureRedisPass123!" }}
masterauth {{ env "REDIS_PASSWORD" | default "SecureRedisPass123!" }}
dir /data
appendonly yes
save 900 1
save 300 10
save 60 10000
replica-announce-ip {{ env "NOMAD_ADDR_redis" }}
{{ if eq (env "NOMAD_ALLOC_INDEX") "0" }}
# I am the master
{{ else }}
replicaof redis-master.service.redis.dc1.nomad.local 6379
{{ end }}
EOT
destination = "tmp/redis.conf"
env = true
}
command = "redis-server"
args = ["/tmp/redis.conf"]
service {
name = "redis-master"
port = "redis"
}
check {
type = "tcp"
port = "redis"
interval = "10s"
timeout = "2s"
}
resources {
cpu = 500
memory = 512
}
}
volume "redis_data" {
type = "host"
source = "/opt/redis/data" # Replace with CSI path for production
}
}
# ──────────────────────────────────────────────────────────────────────────────
# SENTINEL NODES
# ──────────────────────────────────────────────────────────────────────────────
group "sentinel" {
count = 3
restart {
attempts = 3
interval = "5m"
delay = "15s"
mode = "delay"
}
task "sentinel" {
driver = "docker"
config {
image = "redis:7-alpine"
network_mode = "bridge"
port_map = { sentinel = 26379 }
}
ports = ["sentinel"]
# Sentinel config: monitors master via Nomad DNS, re-resolves on failover
template {
data = <<-EOT
port 26379
bind 0.0.0.0
sentinel monitor mymaster redis-master.service.redis.dc1.nomad.local 6379 2
sentinel auth-pass mymaster {{ env "REDIS_PASSWORD" | default "SecureRedisPass123!" }}
sentinel down-after-milliseconds mymaster 5000
sentinel failover-timeout mymaster 60000
sentinel parallel-syncs mymaster 1
sentinel deny-scripts-reconfig yes
sentinel resolve-hostnames yes
EOT
destination = "tmp/sentinel.conf"
env = true
}
command = "redis-sentinel"
args = ["/tmp/sentinel.conf"]
service {
name = "sentinel"
port = "sentinel"
}
check {
type = "tcp"
port = "sentinel"
interval = "10s"
timeout = "2s"
}
resources {
cpu = 250
memory = 128
}
}
}
}
Want to help?
If you can create this pack or job, submit it to the registry and help the community!
Submit a Resource