freeleaps-ops/freeleaps/helm-pkg/3rd/redis/templates/scripts-configmap.yaml
zhenyus 6a264a1c28 feat: add Redis chart with common dependencies and templates
Signed-off-by: zhenyus <zhenyus@mathmast.com>
2025-03-08 22:01:08 +08:00

862 lines
36 KiB
YAML

{{- /*
Copyright Broadcom, Inc. All Rights Reserved.
SPDX-License-Identifier: APACHE-2.0
*/}}
apiVersion: v1
kind: ConfigMap
metadata:
name: {{ printf "%s-scripts" (include "common.names.fullname" .) }}
namespace: {{ include "common.names.namespace" . | quote }}
labels: {{- include "common.labels.standard" ( dict "customLabels" .Values.commonLabels "context" $ ) | nindent 4 }}
{{- if .Values.commonAnnotations }}
annotations: {{- include "common.tplvalues.render" ( dict "value" .Values.commonAnnotations "context" $ ) | nindent 4 }}
{{- end }}
data:
{{- if and (eq .Values.architecture "replication") .Values.sentinel.enabled }}
start-node.sh: |
#!/bin/bash
. /opt/bitnami/scripts/libos.sh
. /opt/bitnami/scripts/liblog.sh
. /opt/bitnami/scripts/libvalidations.sh
get_port() {
hostname="$1"
type="$2"
port_var=$(echo "${hostname^^}_SERVICE_PORT_$type" | sed "s/-/_/g")
port=${!port_var}
if [ -z "$port" ]; then
case $type in
"SENTINEL")
echo {{ .Values.sentinel.containerPorts.sentinel }}
;;
"REDIS")
echo {{ .Values.master.containerPorts.redis }}
;;
esac
else
echo $port
fi
}
get_full_hostname() {
hostname="$1"
{{- if .Values.useExternalDNS.enabled }}
full_hostname="${hostname}.{{- include "redis.externalDNS.suffix" . }}"
{{- else if eq .Values.sentinel.service.type "NodePort" }}
full_hostname="${hostname}.{{- include "common.names.namespace" . }}"
{{- else }}
full_hostname="${hostname}.${HEADLESS_SERVICE}"
{{- end }}
{{- if .Values.useHostnames }}
echo "${full_hostname}"
{{- else }}
retry_count=0
until getent hosts "${full_hostname}" | awk '{ print $1; exit }' | grep .; do
if [[ $retry_count -lt {{ .Values.nameResolutionThreshold }} ]]; then
sleep {{ .Values.nameResolutionTimeout }}
else
error "IP address for ${full_hostname} not found"
exit 1
fi
((retry_count++))
done
{{- end }}
}
REDISPORT=$(get_port "$HOSTNAME" "REDIS")
HEADLESS_SERVICE="{{ template "common.names.fullname" . }}-headless.{{ include "common.names.namespace" . }}.svc.{{ .Values.clusterDomain }}"
if [ -n "$REDIS_EXTERNAL_MASTER_HOST" ]; then
REDIS_SERVICE="$REDIS_EXTERNAL_MASTER_HOST"
else
REDIS_SERVICE="{{ template "common.names.fullname" . }}.{{ include "common.names.namespace" . }}.svc.{{ .Values.clusterDomain }}"
fi
SENTINEL_SERVICE_PORT=$(get_port "{{ include "common.names.fullname" . }}" "SENTINEL")
redis_cli_command() {
local timeout="${1:-0}"
local args=("-h" "$REDIS_SERVICE" "-p" "$SENTINEL_SERVICE_PORT")
local command="redis-cli"
if is_boolean_yes "$REDIS_TLS_ENABLED"; then
args+=("--tls" "--cert" "$REDIS_TLS_CERT_FILE" "--key" "$REDIS_TLS_KEY_FILE")
[ -n "$REDIS_TLS_CA_FILE" ] && args+=("--cacert" "$REDIS_TLS_CA_FILE")
fi
if [ "$timeout" -gt 0 ]; then
command="timeout $timeout $command"
fi
echo "{{- if and .Values.auth.enabled .Values.auth.sentinel }}REDISCLI_AUTH="\$REDIS_PASSWORD" {{ end }} $command ${args[*]}"
}
validate_quorum() {
quorum_info_command="$(redis_cli_command) sentinel master {{ .Values.sentinel.masterSet }}"
info "about to run the command: $quorum_info_command"
eval $quorum_info_command | grep -Fq "s_down"
}
trigger_manual_failover() {
failover_command="$(redis_cli_command) sentinel failover {{ .Values.sentinel.masterSet }}"
info "about to run the command: $failover_command"
eval $failover_command
}
get_sentinel_master_info() {
sentinel_info_command="$(redis_cli_command {{ .Values.sentinel.getMasterTimeout }}) sentinel get-master-addr-by-name {{ .Values.sentinel.masterSet }}"
info "about to run the command: $sentinel_info_command"
retry_while "eval $sentinel_info_command" 2 5
}
{{- if and .Values.replica.containerSecurityContext.runAsUser (eq (.Values.replica.containerSecurityContext.runAsUser | int) 0) }}
useradd redis
chown -R redis {{ .Values.replica.persistence.path }}
{{- end }}
[[ -f $REDIS_PASSWORD_FILE ]] && export REDIS_PASSWORD="$(< "${REDIS_PASSWORD_FILE}")"
[[ -f $REDIS_MASTER_PASSWORD_FILE ]] && export REDIS_MASTER_PASSWORD="$(< "${REDIS_MASTER_PASSWORD_FILE}")"
# check if there is a master
master_in_persisted_conf="$(get_full_hostname "$HOSTNAME")"
master_port_in_persisted_conf="$REDIS_MASTER_PORT_NUMBER"
master_in_sentinel="$(get_sentinel_master_info)"
redisRetVal=$?
if [[ -f /opt/bitnami/redis-sentinel/etc/sentinel.conf ]]; then
master_in_persisted_conf="$(awk '/monitor/ {print $4}' /opt/bitnami/redis-sentinel/etc/sentinel.conf)"
master_port_in_persisted_conf="$(awk '/monitor/ {print $5}' /opt/bitnami/redis-sentinel/etc/sentinel.conf)"
info "Found previous master ${master_in_persisted_conf}:${master_port_in_persisted_conf} in /opt/bitnami/redis-sentinel/etc/sentinel.conf"
debug "$(cat /opt/bitnami/redis-sentinel/etc/sentinel.conf | grep monitor)"
fi
if [[ -f /opt/bitnami/redis/mounted-etc/users.acl ]];then
cp /opt/bitnami/redis/mounted-etc/users.acl /opt/bitnami/redis/etc/users.acl
fi
if [[ $redisRetVal -ne 0 ]]; then
if [[ "$master_in_persisted_conf" == "$(get_full_hostname "$HOSTNAME")" ]]; then
# Case 1: No active sentinel and in previous sentinel.conf we were the master --> MASTER
info "Configuring the node as master"
export REDIS_REPLICATION_MODE="master"
else
# Case 2: No active sentinel and in previous sentinel.conf we were not master --> REPLICA
info "Configuring the node as replica"
export REDIS_REPLICATION_MODE="replica"
REDIS_MASTER_HOST=${master_in_persisted_conf}
REDIS_MASTER_PORT_NUMBER=${master_port_in_persisted_conf}
fi
else
# Fetches current master's host and port
REDIS_SENTINEL_INFO=($(get_sentinel_master_info))
info "Current master: REDIS_SENTINEL_INFO=(${REDIS_SENTINEL_INFO[0]},${REDIS_SENTINEL_INFO[1]})"
REDIS_MASTER_HOST=${REDIS_SENTINEL_INFO[0]}
REDIS_MASTER_PORT_NUMBER=${REDIS_SENTINEL_INFO[1]}
if [[ "$REDIS_MASTER_HOST" == "$(get_full_hostname "$HOSTNAME")" ]]; then
# Case 3: Active sentinel and master it is this node --> MASTER
info "Configuring the node as master"
export REDIS_REPLICATION_MODE="master"
else
# Case 4: Active sentinel and master is not this node --> REPLICA
info "Configuring the node as replica"
export REDIS_REPLICATION_MODE="replica"
{{- if and .Values.sentinel.automateClusterRecovery (le (int .Values.sentinel.downAfterMilliseconds) 2000) }}
retry_count=1
while validate_quorum
do
info "sleeping, waiting for Redis master to come up"
sleep 1s
if ! ((retry_count % 11)); then
info "Trying to manually failover"
failover_result=$(trigger_manual_failover)
debug "Failover result: $failover_result"
fi
((retry_count+=1))
done
info "Redis master is up now"
{{- end }}
fi
fi
if [[ -n "$REDIS_EXTERNAL_MASTER_HOST" ]]; then
REDIS_MASTER_HOST="$REDIS_EXTERNAL_MASTER_HOST"
REDIS_MASTER_PORT_NUMBER="${REDIS_EXTERNAL_MASTER_PORT}"
fi
if [[ -f /opt/bitnami/redis/mounted-etc/replica.conf ]];then
cp /opt/bitnami/redis/mounted-etc/replica.conf /opt/bitnami/redis/etc/replica.conf
fi
if [[ -f /opt/bitnami/redis/mounted-etc/redis.conf ]];then
cp /opt/bitnami/redis/mounted-etc/redis.conf /opt/bitnami/redis/etc/redis.conf
fi
echo "" >> /opt/bitnami/redis/etc/replica.conf
echo "replica-announce-port $REDISPORT" >> /opt/bitnami/redis/etc/replica.conf
{{- if .Values.sentinel.externalAccess.enabled }}
if [[ -n "${REDIS_CLUSTER_ANNOUNCE_IP}" ]]; then
echo "replica-announce-ip $REDIS_CLUSTER_ANNOUNCE_IP" >> /opt/bitnami/redis/etc/replica.conf
else
echo "replica-announce-ip $(get_full_hostname "$HOSTNAME")" >> /opt/bitnami/redis/etc/replica.conf
fi
{{- else }}
echo "replica-announce-ip $(get_full_hostname "$HOSTNAME")" >> /opt/bitnami/redis/etc/replica.conf
{{- end }}
{{- if .Values.tls.enabled }}
ARGS=("--port" "0")
ARGS+=("--tls-port" "${REDIS_TLS_PORT}")
ARGS+=("--tls-cert-file" "${REDIS_TLS_CERT_FILE}")
ARGS+=("--tls-key-file" "${REDIS_TLS_KEY_FILE}")
{{- if not (empty (include "redis.tlsCACert" .)) }}
ARGS+=("--tls-ca-cert-file" "${REDIS_TLS_CA_FILE}")
{{- end }}
ARGS+=("--tls-auth-clients" "${REDIS_TLS_AUTH_CLIENTS}")
ARGS+=("--tls-replication" "yes")
{{- if .Values.tls.dhParamsFilename }}
ARGS+=("--tls-dh-params-file" "${REDIS_TLS_DH_PARAMS_FILE}")
{{- end }}
{{- else }}
ARGS=("--port" "${REDIS_PORT}")
{{- end }}
if [[ "$REDIS_REPLICATION_MODE" = "slave" ]] || [[ "$REDIS_REPLICATION_MODE" = "replica" ]]; then
ARGS+=("--replicaof" "${REDIS_MASTER_HOST}" "${REDIS_MASTER_PORT_NUMBER}")
fi
{{- if .Values.auth.enabled }}
ARGS+=("--requirepass" "${REDIS_PASSWORD}")
ARGS+=("--masterauth" "${REDIS_MASTER_PASSWORD}")
{{- else }}
ARGS+=("--protected-mode" "no")
{{- end }}
ARGS+=("--include" "/opt/bitnami/redis/etc/replica.conf")
ARGS+=("--include" "/opt/bitnami/redis/etc/redis.conf")
{{- if .Values.replica.extraFlags }}
{{- range .Values.replica.extraFlags }}
ARGS+=({{ . | quote }})
{{- end }}
{{- end }}
{{- if .Values.replica.preExecCmds }}
{{- range $command := .Values.replica.preExecCmds }}
{{- $command | nindent 4 }}
{{- end }}
{{- end }}
{{- if .Values.replica.command }}
exec {{ .Values.replica.command }} "${ARGS[@]}"
{{- else }}
exec redis-server "${ARGS[@]}"
{{- end }}
start-sentinel.sh: |
#!/bin/bash
. /opt/bitnami/scripts/libos.sh
. /opt/bitnami/scripts/libvalidations.sh
. /opt/bitnami/scripts/libfile.sh
HEADLESS_SERVICE="{{ template "common.names.fullname" . }}-headless.{{ include "common.names.namespace" . }}.svc.{{ .Values.clusterDomain }}"
REDIS_SERVICE="{{ template "common.names.fullname" . }}.{{ include "common.names.namespace" . }}.svc.{{ .Values.clusterDomain }}"
get_port() {
hostname="$1"
type="$2"
port_var=$(echo "${hostname^^}_SERVICE_PORT_$type" | sed "s/-/_/g")
port=${!port_var}
if [ -z "$port" ]; then
case $type in
"SENTINEL")
echo {{ .Values.sentinel.containerPorts.sentinel }}
;;
"REDIS")
echo {{ .Values.master.containerPorts.redis }}
;;
esac
else
echo $port
fi
}
get_full_hostname() {
hostname="$1"
{{- if .Values.useExternalDNS.enabled }}
full_hostname="${hostname}.{{- include "redis.externalDNS.suffix" . }}"
{{- else if eq .Values.sentinel.service.type "NodePort" }}
full_hostname="${hostname}.{{- include "common.names.namespace" . }}"
{{- else }}
full_hostname="${hostname}.${HEADLESS_SERVICE}"
{{- end }}
{{- if .Values.useHostnames }}
echo "${full_hostname}"
{{- else }}
retry_count=0
until getent hosts "${full_hostname}" | awk '{ print $1; exit }' | grep .; do
if [[ $retry_count -lt {{ .Values.nameResolutionThreshold }} ]]; then
sleep {{ .Values.nameResolutionTimeout }}
else
error "IP address for ${full_hostname} not found"
exit 1
fi
((retry_count++))
done
{{- end }}
}
SERVPORT=$(get_port "$HOSTNAME" "SENTINEL")
REDISPORT=$(get_port "$HOSTNAME" "REDIS")
SENTINEL_SERVICE_PORT=$(get_port "{{ include "common.names.fullname" . }}" "SENTINEL")
sentinel_conf_set() {
local -r key="${1:?missing key}"
local value="${2:-}"
# Sanitize inputs
value="${value//\\/\\\\}"
value="${value//&/\\&}"
value="${value//\?/\\?}"
[[ "$value" = "" ]] && value="\"$value\""
replace_in_file "/opt/bitnami/redis-sentinel/etc/prepare-sentinel.conf" "^#*\s*${key} .*" "${key} ${value}" false
}
sentinel_conf_add() {
echo $'\n'"$@" >> "/opt/bitnami/redis-sentinel/etc/prepare-sentinel.conf"
}
host_id() {
echo "$1" | openssl sha1 | awk '{print $2}'
}
get_sentinel_master_info() {
if is_boolean_yes "$REDIS_SENTINEL_TLS_ENABLED"; then
sentinel_info_command="{{- if and .Values.auth.enabled .Values.auth.sentinel }}REDISCLI_AUTH="\$REDIS_PASSWORD" {{ end }}timeout {{ .Values.sentinel.getMasterTimeout }} redis-cli -h $REDIS_SERVICE -p $SENTINEL_SERVICE_PORT --tls --cert ${REDIS_SENTINEL_TLS_CERT_FILE} --key ${REDIS_SENTINEL_TLS_KEY_FILE} --cacert ${REDIS_SENTINEL_TLS_CA_FILE} sentinel get-master-addr-by-name {{ .Values.sentinel.masterSet }}"
else
sentinel_info_command="{{- if and .Values.auth.enabled .Values.auth.sentinel }}REDISCLI_AUTH="\$REDIS_PASSWORD" {{ end }}timeout {{ .Values.sentinel.getMasterTimeout }} redis-cli -h $REDIS_SERVICE -p $SENTINEL_SERVICE_PORT sentinel get-master-addr-by-name {{ .Values.sentinel.masterSet }}"
fi
info "about to run the command: $sentinel_info_command"
retry_while "eval $sentinel_info_command" 2 5
}
[[ -f $REDIS_PASSWORD_FILE ]] && export REDIS_PASSWORD="$(< "${REDIS_PASSWORD_FILE}")"
master_in_persisted_conf="$(get_full_hostname "$HOSTNAME")"
if [[ -f /opt/bitnami/redis-sentinel/etc/sentinel.conf ]]; then
master_in_persisted_conf="$(awk '/monitor/ {print $4}' /opt/bitnami/redis-sentinel/etc/sentinel.conf)"
info "Found previous master $master_in_persisted_conf in /opt/bitnami/redis-sentinel/etc/sentinel.conf"
debug "$(cat /opt/bitnami/redis-sentinel/etc/sentinel.conf | grep monitor)"
fi
REDIS_SENTINEL_INFO=($(get_sentinel_master_info))
if [ "$?" -eq "0" ]; then
# current master's host and port obtained from other Sentinel
info "printing REDIS_SENTINEL_INFO=(${REDIS_SENTINEL_INFO[0]},${REDIS_SENTINEL_INFO[1]})"
REDIS_MASTER_HOST=${REDIS_SENTINEL_INFO[0]}
REDIS_MASTER_PORT_NUMBER=${REDIS_SENTINEL_INFO[1]}
else
REDIS_MASTER_HOST="$master_in_persisted_conf"
REDIS_MASTER_PORT_NUMBER="$REDISPORT"
fi
if [[ "$REDIS_MASTER_HOST" == "$(get_full_hostname "$HOSTNAME")" ]]; then
export REDIS_REPLICATION_MODE="master"
else
export REDIS_REPLICATION_MODE="replica"
fi
{{- if or .Values.sentinel.masterService.enabled .Values.sentinel.service.createMaster }}
if [[ "${REDIS_REPLICATION_MODE}" == "master" ]]; then
# Add isMaster label to master node for master service
echo "${REDIS_MASTER_HOST/.*}" > /etc/shared/current
fi
{{- end }}
if [[ -n "$REDIS_EXTERNAL_MASTER_HOST" ]]; then
REDIS_MASTER_HOST="$REDIS_EXTERNAL_MASTER_HOST"
REDIS_MASTER_PORT_NUMBER="${REDIS_EXTERNAL_MASTER_PORT}"
fi
# To prevent incomplete configuration and as the redis container accesses /opt/bitnami/redis-sentinel/etc/sentinel.conf
# as well, prepare the new config in `prepare-sentinel.conf` and move it atomically to the ultimate destination when it is complete.
cp /opt/bitnami/redis-sentinel/mounted-etc/sentinel.conf /opt/bitnami/redis-sentinel/etc/prepare-sentinel.conf
{{- if .Values.auth.enabled }}
printf "\nsentinel auth-pass %s %s" "{{ .Values.sentinel.masterSet }}" "$REDIS_PASSWORD" >> /opt/bitnami/redis-sentinel/etc/prepare-sentinel.conf
{{- if and .Values.auth.enabled .Values.auth.sentinel }}
printf "\nrequirepass %s" "$REDIS_PASSWORD" >> /opt/bitnami/redis-sentinel/etc/prepare-sentinel.conf
{{- end }}
{{- end }}
printf "\nsentinel myid %s" "$(host_id "$HOSTNAME")" >> /opt/bitnami/redis-sentinel/etc/prepare-sentinel.conf
if [[ -z "$REDIS_MASTER_HOST" ]] || [[ -z "$REDIS_MASTER_PORT_NUMBER" ]]
then
# Prevent incorrect configuration to be written to sentinel.conf
error "Redis master host is configured incorrectly (host: $REDIS_MASTER_HOST, port: $REDIS_MASTER_PORT_NUMBER)"
exit 1
fi
{{- if .Values.sentinel.externalAccess.enabled }}
{{- if .Values.sentinel.externalAccess.service.loadBalancerIP }}
sentinel_conf_set "sentinel monitor" "{{ .Values.sentinel.masterSet }} {{ index .Values.sentinel.externalAccess.service.loadBalancerIP 0 }} "$REDIS_MASTER_PORT_NUMBER" {{ .Values.sentinel.quorum }}"
{{- end }}
{{- else }}
sentinel_conf_set "sentinel monitor" "{{ .Values.sentinel.masterSet }} "$REDIS_MASTER_HOST" "$REDIS_MASTER_PORT_NUMBER" {{ .Values.sentinel.quorum }}"
{{- end }}
add_known_sentinel() {
hostname="$1"
ip="$2"
if [[ -n "$hostname" && -n "$ip" && "$hostname" != "$HOSTNAME" ]]; then
sentinel_conf_add "sentinel known-sentinel {{ .Values.sentinel.masterSet }} $(get_full_hostname "$hostname") $(get_port "$hostname" "SENTINEL") $(host_id "$hostname")"
fi
}
add_known_replica() {
hostname="$1"
ip="$2"
if [[ -n "$ip" && "$(get_full_hostname "$hostname")" != "$REDIS_MASTER_HOST" ]]; then
sentinel_conf_add "sentinel known-replica {{ .Values.sentinel.masterSet }} $(get_full_hostname "$hostname") $(get_port "$hostname" "REDIS")"
fi
}
add_known_sentinel_public_ip() {
hostname="$1"
ip="$2"
sentinel_conf_add "sentinel known-sentinel {{ .Values.sentinel.masterSet }} $ip $(get_port "$hostname" "SENTINEL") $(host_id "$hostname")"
}
add_known_replica_public_ip() {
hostname="$1"
ip="$2"
sentinel_conf_add "sentinel known-replica {{ .Values.sentinel.masterSet }} $ip $(get_port "$hostname" "REDIS")"
}
for node in $(seq 0 $(({{ .Values.replica.replicaCount }}-1))); do
hostname="{{ template "common.names.fullname" . }}-node-$node"
{{- if .Values.sentinel.externalAccess.enabled }}
{{- if .Values.sentinel.externalAccess.service.loadBalancerIP }}
ips=($(echo "$REDIS_NODES" | tr " " "\n"))
ip=${ips[$node]}
add_known_sentinel_public_ip "$hostname" "$ip"
add_known_replica_public_ip "$hostname" "$ip"
{{- end}}
{{- else }}
ip="$(getent hosts "$hostname.$HEADLESS_SERVICE" | awk '{ print $1 }')"
add_known_sentinel "$hostname" "$ip"
add_known_replica "$hostname" "$ip"
{{- end}}
done
echo "" >> /opt/bitnami/redis-sentinel/etc/prepare-sentinel.conf
{{- if not (contains "sentinel announce-hostnames" .Values.sentinel.configuration) }}
echo "sentinel announce-hostnames yes" >> /opt/bitnami/redis-sentinel/etc/prepare-sentinel.conf
{{- end }}
{{- if not (contains "sentinel resolve-hostnames" .Values.sentinel.configuration) }}
echo "sentinel resolve-hostnames yes" >> /opt/bitnami/redis-sentinel/etc/prepare-sentinel.conf
{{- end }}
{{- if not (contains "sentinel announce-port" .Values.sentinel.configuration) }}
echo "sentinel announce-port $SERVPORT" >> /opt/bitnami/redis-sentinel/etc/prepare-sentinel.conf
{{- end }}
{{- if .Values.sentinel.externalAccess.enabled }}
{{- if not (contains "sentinel announce-ip" .Values.sentinel.configuration) }}
if [[ -n "${REDIS_CLUSTER_ANNOUNCE_IP}" ]]; then
echo "sentinel announce-ip $REDIS_CLUSTER_ANNOUNCE_IP" >> /opt/bitnami/redis-sentinel/etc/prepare-sentinel.conf
else
echo "sentinel announce-ip $(get_full_hostname "$HOSTNAME")" >> /opt/bitnami/redis-sentinel/etc/prepare-sentinel.conf
fi
{{- else }}
echo "sentinel announce-ip $(get_full_hostname "$HOSTNAME")" >> /opt/bitnami/redis-sentinel/etc/prepare-sentinel.conf
{{- end}}
{{- end}}
{{- if .Values.tls.enabled }}
ARGS=("--port" "0")
ARGS+=("--tls-port" "${REDIS_SENTINEL_TLS_PORT_NUMBER}")
ARGS+=("--tls-cert-file" "${REDIS_SENTINEL_TLS_CERT_FILE}")
ARGS+=("--tls-key-file" "${REDIS_SENTINEL_TLS_KEY_FILE}")
ARGS+=("--tls-ca-cert-file" "${REDIS_SENTINEL_TLS_CA_FILE}")
ARGS+=("--tls-replication" "yes")
ARGS+=("--tls-auth-clients" "${REDIS_SENTINEL_TLS_AUTH_CLIENTS}")
{{- if .Values.tls.dhParamsFilename }}
ARGS+=("--tls-dh-params-file" "${REDIS_SENTINEL_TLS_DH_PARAMS_FILE}")
{{- end }}
{{- end }}
{{- if .Values.sentinel.preExecCmds }}
{{- range $command := .Values.sentinel.preExecCmds }}
{{- $command | nindent 4 }}
{{- end }}
{{- end }}
mv /opt/bitnami/redis-sentinel/etc/prepare-sentinel.conf /opt/bitnami/redis-sentinel/etc/sentinel.conf
exec redis-server /opt/bitnami/redis-sentinel/etc/sentinel.conf {{- if .Values.tls.enabled }} "${ARGS[@]}" {{- end }} --sentinel
prestop-sentinel.sh: |
#!/bin/bash
. /opt/bitnami/scripts/libvalidations.sh
. /opt/bitnami/scripts/libos.sh
HEADLESS_SERVICE="{{ template "common.names.fullname" . }}-headless.{{ include "common.names.namespace" . }}.svc.{{ .Values.clusterDomain }}"
get_full_hostname() {
hostname="$1"
{{- if .Values.useExternalDNS.enabled }}
full_hostname="${hostname}.{{- include "redis.externalDNS.suffix" . }}"
{{- else if eq .Values.sentinel.service.type "NodePort" }}
full_hostname="${hostname}.{{- include "common.names.namespace" . }}"
{{- else }}
full_hostname="${hostname}.${HEADLESS_SERVICE}"
{{- end }}
{{- if .Values.useHostnames }}
echo "${full_hostname}"
{{- else }}
retry_count=0
until getent hosts "${full_hostname}" | awk '{ print $1; exit }' | grep .; do
if [[ $retry_count -lt {{ .Values.nameResolutionThreshold }} ]]; then
sleep {{ .Values.nameResolutionTimeout }}
else
error "IP address for ${full_hostname} not found"
exit 1
fi
((retry_count++))
done
{{- end }}
}
run_sentinel_command() {
if is_boolean_yes "$REDIS_SENTINEL_TLS_ENABLED"; then
redis-cli -h "$REDIS_SERVICE" -p "$REDIS_SENTINEL_TLS_PORT_NUMBER" --tls --cert "$REDIS_SENTINEL_TLS_CERT_FILE" --key "$REDIS_SENTINEL_TLS_KEY_FILE" --cacert "$REDIS_SENTINEL_TLS_CA_FILE" sentinel "$@"
else
redis-cli -h "$REDIS_SERVICE" -p "$REDIS_SENTINEL_PORT" sentinel "$@"
fi
}
sentinel_failover_finished() {
REDIS_SENTINEL_INFO=($(run_sentinel_command get-master-addr-by-name "{{ .Values.sentinel.masterSet }}"))
REDIS_MASTER_HOST="${REDIS_SENTINEL_INFO[0]}"
[[ "$REDIS_MASTER_HOST" != "$(get_full_hostname $HOSTNAME)" ]]
}
REDIS_SERVICE="{{ include "common.names.fullname" . }}.{{ include "common.names.namespace" . }}.svc.{{ .Values.clusterDomain }}"
{{ if .Values.auth.sentinel -}}
# redis-cli automatically consumes credentials from the REDISCLI_AUTH variable
[[ -n "$REDIS_PASSWORD" ]] && export REDISCLI_AUTH="$REDIS_PASSWORD"
[[ -f "$REDIS_PASSWORD_FILE" ]] && export REDISCLI_AUTH="$(< "${REDIS_PASSWORD_FILE}")"
{{- end }}
if ! sentinel_failover_finished; then
echo "I am the master pod and you are stopping me. Starting sentinel failover"
if retry_while "sentinel_failover_finished" "{{ sub .Values.sentinel.terminationGracePeriodSeconds 10 }}" 1; then
echo "Master has been successfuly failed over to a different pod."
exit 0
else
echo "Master failover failed"
exit 1
fi
else
exit 0
fi
prestop-redis.sh: |
#!/bin/bash
. /opt/bitnami/scripts/libvalidations.sh
. /opt/bitnami/scripts/libos.sh
run_redis_command() {
local args=("-h" "127.0.0.1")
if is_boolean_yes "$REDIS_TLS_ENABLED"; then
args+=("-p" "$REDIS_TLS_PORT" "--tls" "--cert" "$REDIS_TLS_CERT_FILE" "--key" "$REDIS_TLS_KEY_FILE")
[ -n "$REDIS_TLS_CA_FILE" ] && args+=("--cacert" "$REDIS_TLS_CA_FILE")
else
args+=("-p" "$REDIS_PORT")
fi
redis-cli "${args[@]}" "$@"
}
is_master() {
REDIS_ROLE=$(run_redis_command role | head -1)
[[ "$REDIS_ROLE" == "master" ]]
}
HEADLESS_SERVICE="{{ template "common.names.fullname" . }}-headless.{{- include "common.names.namespace" . }}.svc.{{ .Values.clusterDomain }}"
get_full_hostname() {
hostname="$1"
{{- if .Values.useExternalDNS.enabled }}
full_hostname="${hostname}.{{- include "redis.externalDNS.suffix" . }}"
{{- else if eq .Values.sentinel.service.type "NodePort" }}
full_hostname="${hostname}.{{- include "common.names.namespace" . }}"
{{- else }}
full_hostname="${hostname}.${HEADLESS_SERVICE}"
{{- end }}
{{- if .Values.useHostnames }}
echo "${full_hostname}"
{{- else }}
retry_count=0
until getent hosts "${full_hostname}" | awk '{ print $1; exit }' | grep .; do
if [[ $retry_count -lt {{ .Values.nameResolutionThreshold }} ]]; then
sleep {{ .Values.nameResolutionTimeout }}
else
error "IP address for ${full_hostname} not found"
exit 1
fi
((retry_count++))
done
{{- end }}
}
run_sentinel_command() {
if is_boolean_yes "$REDIS_SENTINEL_TLS_ENABLED"; then
{{ .Values.auth.sentinel | ternary "" "env -u REDISCLI_AUTH " -}} redis-cli -h "$REDIS_SERVICE" -p "$REDIS_SENTINEL_TLS_PORT_NUMBER" --tls --cert "$REDIS_SENTINEL_TLS_CERT_FILE" --key "$REDIS_SENTINEL_TLS_KEY_FILE" --cacert "$REDIS_SENTINEL_TLS_CA_FILE" sentinel "$@"
else
{{ .Values.auth.sentinel | ternary "" "env -u REDISCLI_AUTH " -}} redis-cli -h "$REDIS_SERVICE" -p "$REDIS_SENTINEL_PORT" sentinel "$@"
fi
}
sentinel_failover_finished() {
REDIS_SENTINEL_INFO=($(run_sentinel_command get-master-addr-by-name "{{ .Values.sentinel.masterSet }}"))
REDIS_MASTER_HOST="${REDIS_SENTINEL_INFO[0]}"
[[ "$REDIS_MASTER_HOST" != "$(get_full_hostname $HOSTNAME)" ]]
}
REDIS_SERVICE="{{ include "common.names.fullname" . }}.{{ include "common.names.namespace" . }}.svc.{{ .Values.clusterDomain }}"
# redis-cli automatically consumes credentials from the REDISCLI_AUTH variable
[[ -n "$REDIS_PASSWORD" ]] && export REDISCLI_AUTH="$REDIS_PASSWORD"
[[ -f "$REDIS_PASSWORD_FILE" ]] && export REDISCLI_AUTH="$(< "${REDIS_PASSWORD_FILE}")"
if is_master && ! sentinel_failover_finished; then
echo "I am the master pod and you are stopping me. Pausing client connections."
# Pausing client write connections to avoid data loss
run_redis_command CLIENT PAUSE "{{ mul (add 2 (sub .Values.sentinel.terminationGracePeriodSeconds 10)) 1000 }}" WRITE
echo "Issuing failover"
# if I am the master, issue a command to failover once
run_sentinel_command failover "{{ .Values.sentinel.masterSet }}"
{{- if .Values.sentinel.redisShutdownWaitFailover }}
echo "Waiting for sentinel to complete failover for up to {{ sub .Values.sentinel.terminationGracePeriodSeconds 10 }}s"
retry_while "sentinel_failover_finished" "{{ sub .Values.sentinel.terminationGracePeriodSeconds 10 }}" 1
{{- end }}
else
exit 0
fi
{{- if or .Values.sentinel.masterService.enabled .Values.sentinel.service.createMaster }}
push-master-label.sh: |
#!/bin/bash
# https://download.redis.io/redis-stable/sentinel.conf
echo "${6/.*}" > /etc/shared/current
echo "${4/.*}" > /etc/shared/previous
{{- end }}
{{- else }}
start-master.sh: |
#!/bin/bash
[[ -f $REDIS_PASSWORD_FILE ]] && export REDIS_PASSWORD="$(< "${REDIS_PASSWORD_FILE}")"
{{- if and .Values.master.containerSecurityContext.runAsUser (eq (.Values.master.containerSecurityContext.runAsUser | int) 0) }}
useradd redis
chown -R redis {{ .Values.master.persistence.path }}
{{- end }}
if [[ -f /opt/bitnami/redis/mounted-etc/master.conf ]];then
cp /opt/bitnami/redis/mounted-etc/master.conf /opt/bitnami/redis/etc/master.conf
fi
if [[ -f /opt/bitnami/redis/mounted-etc/redis.conf ]];then
cp /opt/bitnami/redis/mounted-etc/redis.conf /opt/bitnami/redis/etc/redis.conf
fi
if [[ -f /opt/bitnami/redis/mounted-etc/users.acl ]];then
cp /opt/bitnami/redis/mounted-etc/users.acl /opt/bitnami/redis/etc/users.acl
fi
{{- if .Values.tls.enabled }}
ARGS=("--port" "0")
ARGS+=("--tls-port" "${REDIS_TLS_PORT}")
ARGS+=("--tls-cert-file" "${REDIS_TLS_CERT_FILE}")
ARGS+=("--tls-key-file" "${REDIS_TLS_KEY_FILE}")
{{- if not (empty (include "redis.tlsCACert" .)) }}
ARGS+=("--tls-ca-cert-file" "${REDIS_TLS_CA_FILE}")
{{- end }}
ARGS+=("--tls-auth-clients" "${REDIS_TLS_AUTH_CLIENTS}")
{{- if .Values.tls.dhParamsFilename }}
ARGS+=("--tls-dh-params-file" "${REDIS_TLS_DH_PARAMS_FILE}")
{{- end }}
{{- else }}
ARGS=("--port" "${REDIS_PORT}")
{{- end }}
{{- if .Values.auth.enabled }}
ARGS+=("--requirepass" "${REDIS_PASSWORD}")
ARGS+=("--masterauth" "${REDIS_PASSWORD}")
{{- else }}
ARGS+=("--protected-mode" "no")
{{- end }}
ARGS+=("--include" "/opt/bitnami/redis/etc/redis.conf")
ARGS+=("--include" "/opt/bitnami/redis/etc/master.conf")
{{- if .Values.master.extraFlags }}
{{- range .Values.master.extraFlags }}
ARGS+=({{ . | quote }})
{{- end }}
{{- end }}
{{- if .Values.master.preExecCmds }}
{{- range $command := .Values.master.preExecCmds }}
{{- $command | nindent 4 }}
{{- end }}
{{- end }}
{{- if .Values.master.command }}
exec {{ .Values.master.command }} "${ARGS[@]}"
{{- else }}
exec redis-server "${ARGS[@]}"
{{- end }}
{{- if eq .Values.architecture "replication" }}
start-replica.sh: |
#!/bin/bash
get_port() {
hostname="$1"
type="$2"
port_var=$(echo "${hostname^^}_SERVICE_PORT_$type" | sed "s/-/_/g")
port=${!port_var}
if [ -z "$port" ]; then
case $type in
"SENTINEL")
echo {{ .Values.sentinel.containerPorts.sentinel }}
;;
"REDIS")
echo {{ .Values.master.containerPorts.redis }}
;;
esac
else
echo $port
fi
}
get_full_hostname() {
hostname="$1"
{{- if .Values.useExternalDNS.enabled }}
full_hostname="${hostname}.{{- include "redis.externalDNS.suffix" . }}"
{{- else if eq .Values.sentinel.service.type "NodePort" }}
full_hostname="${hostname}.{{- include "common.names.namespace" . }}"
{{- else }}
full_hostname="${hostname}.${HEADLESS_SERVICE}"
{{- end }}
{{- if .Values.useHostnames }}
echo "${full_hostname}"
{{- else }}
retry_count=0
until getent hosts "${full_hostname}" | awk '{ print $1; exit }' | grep .; do
if [[ $retry_count -lt {{ .Values.nameResolutionThreshold }} ]]; then
sleep {{ .Values.nameResolutionTimeout }}
else
error "IP address for ${full_hostname} not found"
exit 1
fi
((retry_count++))
done
{{- end }}
}
REDISPORT=$(get_port "$HOSTNAME" "REDIS")
HEADLESS_SERVICE="{{ template "common.names.fullname" . }}-headless.{{ include "common.names.namespace" . }}.svc.{{ .Values.clusterDomain }}"
[[ -f $REDIS_PASSWORD_FILE ]] && export REDIS_PASSWORD="$(< "${REDIS_PASSWORD_FILE}")"
[[ -f $REDIS_MASTER_PASSWORD_FILE ]] && export REDIS_MASTER_PASSWORD="$(< "${REDIS_MASTER_PASSWORD_FILE}")"
{{- if and .Values.replica.containerSecurityContext.runAsUser (eq (.Values.replica.containerSecurityContext.runAsUser | int) 0) }}
useradd redis
chown -R redis {{ .Values.replica.persistence.path }}
{{- end }}
if [[ -f /opt/bitnami/redis/mounted-etc/replica.conf ]];then
cp /opt/bitnami/redis/mounted-etc/replica.conf /opt/bitnami/redis/etc/replica.conf
fi
if [[ -f /opt/bitnami/redis/mounted-etc/redis.conf ]];then
cp /opt/bitnami/redis/mounted-etc/redis.conf /opt/bitnami/redis/etc/redis.conf
fi
if [[ -f /opt/bitnami/redis/mounted-etc/users.acl ]];then
cp /opt/bitnami/redis/mounted-etc/users.acl /opt/bitnami/redis/etc/users.acl
fi
echo "" >> /opt/bitnami/redis/etc/replica.conf
echo "replica-announce-port $REDISPORT" >> /opt/bitnami/redis/etc/replica.conf
echo "replica-announce-ip $(get_full_hostname "$HOSTNAME")" >> /opt/bitnami/redis/etc/replica.conf
{{- if .Values.tls.enabled }}
ARGS=("--port" "0")
ARGS+=("--tls-port" "${REDIS_TLS_PORT}")
ARGS+=("--tls-cert-file" "${REDIS_TLS_CERT_FILE}")
ARGS+=("--tls-key-file" "${REDIS_TLS_KEY_FILE}")
{{- if not (empty (include "redis.tlsCACert" .)) }}
ARGS+=("--tls-ca-cert-file" "${REDIS_TLS_CA_FILE}")
{{- end }}
ARGS+=("--tls-auth-clients" "${REDIS_TLS_AUTH_CLIENTS}")
ARGS+=("--tls-replication" "yes")
{{- if .Values.tls.dhParamsFilename }}
ARGS+=("--tls-dh-params-file" "${REDIS_TLS_DH_PARAMS_FILE}")
{{- end }}
{{- else }}
ARGS=("--port" "${REDIS_PORT}")
{{- end }}
ARGS+=("--replicaof" "${REDIS_MASTER_HOST}" "${REDIS_MASTER_PORT_NUMBER}")
{{- if .Values.auth.enabled }}
ARGS+=("--requirepass" "${REDIS_PASSWORD}")
ARGS+=("--masterauth" "${REDIS_MASTER_PASSWORD}")
{{- else }}
ARGS+=("--protected-mode" "no")
{{- end }}
ARGS+=("--include" "/opt/bitnami/redis/etc/redis.conf")
ARGS+=("--include" "/opt/bitnami/redis/etc/replica.conf")
{{- if .Values.replica.extraFlags }}
{{- range .Values.replica.extraFlags }}
ARGS+=({{ . | quote }})
{{- end }}
{{- end }}
{{- if .Values.replica.preExecCmds }}
{{- range $command := .Values.replica.preExecCmds }}
{{- $command | nindent 4 }}
{{- end }} {{- end }}
{{- if .Values.replica.command }}
exec {{ .Values.replica.command }} "${ARGS[@]}"
{{- else }}
exec redis-server "${ARGS[@]}"
{{- end }}
{{- end }}
{{- end }}
---
{{- if or .Values.sentinel.masterService.enabled .Values.sentinel.service.createMaster }}
apiVersion: v1
kind: ConfigMap
metadata:
name: {{ printf "%s-kubectl-scripts" (include "common.names.fullname" .) }}
namespace: {{ include "common.names.namespace" . | quote }}
labels: {{- include "common.labels.standard" ( dict "customLabels" .Values.commonLabels "context" $ ) | nindent 4 }}
{{- if .Values.commonAnnotations }}
annotations: {{- include "common.tplvalues.render" ( dict "value" .Values.commonAnnotations "context" $ ) | nindent 4 }}
{{- end }}
data:
update-master-label.sh: |
#!/bin/bash
while true; do
while [ ! -f "/etc/shared/current" ]; do
sleep 1
done
echo "new master elected, updating label(s)..."
kubectl label pod --field-selector metadata.name="$(< "/etc/shared/current")" isMaster="true" --overwrite
kubectl label pod --field-selector metadata.name="$(< "/etc/shared/current")" app.kubernetes.io/role-
if [ -f /etc/shared/previous ]; then
kubectl label pod --field-selector metadata.name="$(< "/etc/shared/previous")" isMaster="false" --overwrite
fi
rm "/etc/shared/current" "/etc/shared/previous"
done
{{- end }}