feat: create redisha module

- manage redis/sentinel clusters
- ensure ulimit_managed is false
- dynamically find servers in role to identify master
- add redisadm and sentineladm commands
- add script to check if the current host in the master
This commit is contained in:
Ben Vincent 2024-08-09 23:22:37 +10:00
parent aadd0275ac
commit b7fc6a1993
8 changed files with 202 additions and 0 deletions

View File

@ -0,0 +1,14 @@
# manage RedisHA
class redisha (
Boolean $manage_repo = $redisha::params::manage_repo,
Boolean $redisha_members_lookup = $redisha::params::redisha_members_lookup,
Optional[String] $redisha_members_role = $redisha::params::redisha_members_role,
Array $redisha_servers = $redisha::params::redisha_servers,
) inherits redisha::params {
include redisha::redis
include redisha::sentinel
include redisha::tools
Class['redisha::redis'] -> Class['redisha::sentinel'] -> Class['redisha::tools']
}

View File

@ -0,0 +1,25 @@
class redisha::params (
Boolean $redisha_members_lookup = false,
Optional[String] $redisha_members_role = undef,
Array $redisha_servers = [],
# both
Stdlib::Host $redis_host = $facts['networking']['ip'],
Stdlib::Port $redis_port = 6379,
Optional[String] $requirepass = undef,
# redis
Optional[String] $dnf_module_stream = '6',
Integer[1] $databases = 16,
Optional[Variant[String, Sensitive[String], Deferred]] $masterauth = $redisha::params::requirepass,
# sentinel
String[1] $master_name = 'mymaster',
Optional[Variant[String, Sensitive[String]]] $auth_pass = $redisha::params::requirepass,
Integer[1] $quorum = 2,
Enum['yes', 'no'] $sentinel_resolve_hostnames = 'yes',
Enum['yes', 'no'] $sentinel_announce_hostnames = 'yes',
Stdlib::Host $sentinel_announce_ip = $facts['networking']['ip'],
Array[Stdlib::IP::Address] $sentinel_bind = [$facts['networking']['ip']],
Stdlib::Port $sentinel_port = 26379,
){}

View File

@ -0,0 +1,59 @@
class redisha::redis (
Boolean $manage_repo = $redisha::manage_repo,
Boolean $redisha_members_lookup = $redisha::redisha_members_lookup,
Optional[String] $redisha_members_role = $redisha::redisha_members_role,
Array $redisha_servers = $redisha::redisha_servers,
Stdlib::Host $redis_host = $redisha::params::redis_host,
Stdlib::Port $redis_port = $redisha::params::redis_port,
Optional[String] $requirepass = $redisha::params::requirepass,
Optional[String] $dnf_module_stream = $redisha::params::dnf_module_stream,
Integer[1] $databases = $redisha::params::databases,
Optional[Variant[String, Sensitive[String], Deferred]] $masterauth = $redisha::params::masterauth,
) inherits redisha::params {
# if lookup is enabled
if $redisha_members_lookup {
# check that the role is also set
unless !($redisha_members_role == undef) {
fail("redisha_members_role must be provided for ${title} when redisha_members_lookup is True")
}
# if it is, find hosts, sort them so they dont cause changes every run
$servers_array = sort(query_nodes("enc_role='${redisha_members_role}' and region='${facts['region']}'", 'networking.fqdn'))
# else use provided array from params
}else{
$servers_array = $redisha_servers
}
if length($servers_array) >= 3 {
# check if this is the master_node
if $servers_array[0] == $::facts['networking']['fqdn'] {
class { 'redis':
bind => $redis_host,
port => $redis_port,
databases => $databases,
requirepass => $requirepass,
masterauth => $masterauth,
dnf_module_stream => $dnf_module_stream,
ulimit_managed => false,
}
}else{
class { 'redis':
bind => $redis_host,
port => $redis_port,
databases => $databases,
requirepass => $requirepass,
masterauth => $masterauth,
dnf_module_stream => $dnf_module_stream,
ulimit_managed => false,
replicaof => "${servers_array[0]} ${redis_port}",
}
}
}
}

View File

@ -0,0 +1,49 @@
class redisha::sentinel (
Boolean $redisha_members_lookup = $redisha::redisha_members_lookup,
Optional[String] $redisha_members_role = $redisha::redisha_members_role,
Array $redisha_servers = $redisha::redisha_servers,
Stdlib::Port $redis_port = $redisha::params::redis_port,
Optional[String] $requirepass = $redisha::params::requirepass,
String[1] $master_name = $redisha::params::master_name,
Optional[Variant[String, Sensitive[String]]] $auth_pass = $redisha::params::auth_pass,
Integer[1] $quorum = $redisha::params::quorum,
Enum['yes', 'no'] $sentinel_resolve_hostnames = $redisha::params::sentinel_resolve_hostnames,
Enum['yes', 'no'] $sentinel_announce_hostnames = $redisha::params::sentinel_announce_hostnames,
Stdlib::Host $sentinel_announce_ip = $redisha::params::sentinel_announce_ip,
Array[Stdlib::IP::Address] $sentinel_bind = $redisha::params::sentinel_bind,
Stdlib::Port $sentinel_port = $redisha::params::sentinel_port,
) inherits redisha::params {
# if lookup is enabled
if $redisha_members_lookup {
# check that the role is also set
unless !($redisha_members_role == undef) {
fail("redisha_members_role must be provided for ${title} when redisha_members_lookup is True")
}
# if it is, find hosts, sort them so they dont cause changes every run
$servers_array = sort(query_nodes("enc_role='${redisha_members_role}' and region='${facts['region']}'", 'networking.fqdn'))
# else use provided array from params
}else{
$servers_array = $redisha_servers
}
if length($servers_array) >= 3 {
class { 'redis::sentinel':
master_name => $master_name,
redis_host => $servers_array[0],
redis_port => $redis_port,
requirepass => $requirepass,
auth_pass => $auth_pass,
quorum => $quorum,
sentinel_resolve_hostnames => $sentinel_resolve_hostnames,
sentinel_announce_ip => $sentinel_announce_ip,
sentinel_announce_hostnames => $sentinel_announce_hostnames,
sentinel_port => $sentinel_port,
sentinel_bind => $sentinel_bind,
}
}
}

View File

@ -0,0 +1,35 @@
class redisha::tools (
Stdlib::Host $redis_host = $redisha::params::redis_host,
Stdlib::Port $redis_port = $redisha::params::redis_port,
Stdlib::Port $sentinel_port = $redisha::params::sentinel_port,
Optional[String] $requirepass = $redisha::params::requirepass,
) inherits redisha::params {
# add command to automate redis-cli commands against redis
file {'/usr/local/sbin/redisadm':
ensure => 'file',
owner => 'root',
group => 'root',
mode => '0700',
content => template('redisha/redisadm.erb'),
}
# add command to automate redis-cli commands against sentinel
file {'/usr/local/sbin/sentineladm':
ensure => 'file',
owner => 'root',
group => 'root',
mode => '0700',
content => template('redisha/sentineladm.erb'),
}
# add command to check if current host is the redis master
file {'/usr/local/bin/check_redis_master':
ensure => 'file',
owner => 'root',
group => 'root',
mode => '0755',
content => template('redisha/check_redis_master.erb'),
}
}

View File

@ -0,0 +1,2 @@
#!/usr/bin/bash
sudo /usr/local/sbin/sentineladm info | grep -q <%= @facts['networking']['fqdn'] %>

View File

@ -0,0 +1,9 @@
#!/usr/bin/bash
REDIS_HOST=<%= @redis_host %>
REDIS_PORT=<%= @redis_port %>
if [ $# -gt 0 ]; then
REDISCLI_AUTH=<%= @requirepass %> redis-cli -h "$REDIS_HOST" -p "$REDIS_PORT" "$@"
else
REDISCLI_AUTH=<%= @requirepass %> redis-cli -h "$REDIS_HOST" -p "$REDIS_PORT"
fi

View File

@ -0,0 +1,9 @@
#!/usr/bin/bash
REDIS_HOST=<%= @redis_host %>
SENTINEL_PORT=<%= @sentinel_port %>
if [ $# -gt 0 ]; then
REDISCLI_AUTH=<%= @requirepass %> redis-cli -h "$REDIS_HOST" -p "$SENTINEL_PORT" "$@"
else
REDISCLI_AUTH=<%= @requirepass %> redis-cli -h "$REDIS_HOST" -p "$SENTINEL_PORT"
fi