-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
vagrant
committed
Dec 11, 2019
0 parents
commit 5d2830a
Showing
24 changed files
with
1,690 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,21 @@ | ||
apiVersion: v1 | ||
appVersion: 5.0.6 | ||
description: Highly available Kubernetes implementation of Redis | ||
engine: gotpl | ||
home: http://redis.io/ | ||
icon: https://upload.wikimedia.org/wikipedia/en/thumb/6/6b/Redis_Logo.svg/1200px-Redis_Logo.svg.png | ||
keywords: | ||
- redis | ||
- keyvalue | ||
- database | ||
maintainers: | ||
- email: [email protected] | ||
name: ssalaues | ||
- email: [email protected] | ||
name: dandydeveloper | ||
name: redis-ha | ||
sources: | ||
- https://redis.io/download | ||
- https://github.com/scality/Zenko/tree/development/1.0/kubernetes/zenko/charts/redis-ha | ||
- https://github.com/oliver006/redis_exporter | ||
version: 4.1.5 |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,6 @@ | ||
approvers: | ||
- ssalaues | ||
- dandydeveloper | ||
reviewers: | ||
- ssalaues | ||
- dandydeveloper |
Large diffs are not rendered by default.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,10 @@ | ||
--- | ||
## Enable HAProxy to manage Load Balancing | ||
haproxy: | ||
enabled: true | ||
annotations: | ||
any.domain/key: "value" | ||
serviceAccount: | ||
create: true | ||
metrics: | ||
enabled: true |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,25 @@ | ||
Redis can be accessed via port {{ .Values.redis.port }} and Sentinel can be accessed via port {{ .Values.sentinel.port }} on the following DNS name from within your cluster: | ||
{{ template "redis-ha.fullname" . }}.{{ .Release.Namespace }}.svc.cluster.local | ||
|
||
To connect to your Redis server: | ||
|
||
{{- if .Values.auth }} | ||
1. To retrieve the redis password: | ||
echo $(kubectl get secret {{ template "redis-ha.fullname" . }} -o "jsonpath={.data['auth']}" | base64 --decode) | ||
|
||
2. Connect to the Redis master pod that you can use as a client. By default the {{ template "redis-ha.fullname" . }}-server-0 pod is configured as the master: | ||
|
||
kubectl exec -it {{ template "redis-ha.fullname" . }}-server-0 sh -n {{ .Release.Namespace }} | ||
|
||
3. Connect using the Redis CLI (inside container): | ||
|
||
redis-cli -a <REDIS-PASS-FROM-SECRET> | ||
{{- else }} | ||
1. Run a Redis pod that you can use as a client: | ||
|
||
kubectl exec -it {{ template "redis-ha.fullname" . }}-server-0 sh -n {{ .Release.Namespace }} | ||
|
||
2. Connect using the Redis CLI: | ||
|
||
redis-cli -h {{ template "redis-ha.fullname" . }}.{{ .Release.Namespace }}.svc.cluster.local | ||
{{- end }} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,262 @@ | ||
{{/* vim: set filetype=mustache: */}} | ||
|
||
{{- define "config-redis.conf" }} | ||
{{- if .Values.redis.customConfig }} | ||
{{ tpl .Values.redis.customConfig . | indent 4 }} | ||
{{- else }} | ||
dir "/data" | ||
port {{ .Values.redis.port }} | ||
{{- range $key, $value := .Values.redis.config }} | ||
{{ $key }} {{ $value }} | ||
{{- end }} | ||
{{- if .Values.auth }} | ||
requirepass replace-default-auth | ||
masterauth replace-default-auth | ||
{{- end }} | ||
{{- end }} | ||
{{- end }} | ||
|
||
{{- define "config-sentinel.conf" }} | ||
{{- if .Values.sentinel.customConfig }} | ||
{{ tpl .Values.sentinel.customConfig . | indent 4 }} | ||
{{- else }} | ||
dir "/data" | ||
{{- range $key, $value := .Values.sentinel.config }} | ||
sentinel {{ $key }} {{ template "redis-ha.masterGroupName" $ }} {{ $value }} | ||
{{- end }} | ||
{{- if .Values.auth }} | ||
sentinel auth-pass {{ template "redis-ha.masterGroupName" . }} replace-default-auth | ||
{{- end }} | ||
{{- end }} | ||
{{- end }} | ||
|
||
{{- define "config-init.sh" }} | ||
HOSTNAME="$(hostname)" | ||
INDEX="${HOSTNAME##*-}" | ||
MASTER="$(redis-cli -h {{ template "redis-ha.fullname" . }} -p {{ .Values.sentinel.port }} sentinel get-master-addr-by-name {{ template "redis-ha.masterGroupName" . }} | grep -E '[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}')" | ||
MASTER_GROUP="{{ template "redis-ha.masterGroupName" . }}" | ||
QUORUM="{{ .Values.sentinel.quorum }}" | ||
REDIS_CONF=/data/conf/redis.conf | ||
REDIS_PORT={{ .Values.redis.port }} | ||
SENTINEL_CONF=/data/conf/sentinel.conf | ||
SENTINEL_PORT={{ .Values.sentinel.port }} | ||
SERVICE={{ template "redis-ha.fullname" . }} | ||
set -eu | ||
|
||
sentinel_update() { | ||
echo "Updating sentinel config with master $MASTER" | ||
eval MY_SENTINEL_ID="\${SENTINEL_ID_$INDEX}" | ||
sed -i "1s/^/sentinel myid $MY_SENTINEL_ID\\n/" "$SENTINEL_CONF" | ||
sed -i "2s/^/sentinel monitor $MASTER_GROUP $1 $REDIS_PORT $QUORUM \\n/" "$SENTINEL_CONF" | ||
echo "sentinel announce-ip $ANNOUNCE_IP" >> $SENTINEL_CONF | ||
echo "sentinel announce-port $SENTINEL_PORT" >> $SENTINEL_CONF | ||
} | ||
|
||
redis_update() { | ||
echo "Updating redis config" | ||
echo "slaveof $1 $REDIS_PORT" >> "$REDIS_CONF" | ||
echo "slave-announce-ip $ANNOUNCE_IP" >> $REDIS_CONF | ||
echo "slave-announce-port $REDIS_PORT" >> $REDIS_CONF | ||
} | ||
|
||
copy_config() { | ||
cp /readonly-config/redis.conf "$REDIS_CONF" | ||
cp /readonly-config/sentinel.conf "$SENTINEL_CONF" | ||
} | ||
|
||
setup_defaults() { | ||
echo "Setting up defaults" | ||
if [ "$INDEX" = "0" ]; then | ||
echo "Setting this pod as the default master" | ||
redis_update "$ANNOUNCE_IP" | ||
sentinel_update "$ANNOUNCE_IP" | ||
sed -i "s/^.*slaveof.*//" "$REDIS_CONF" | ||
else | ||
DEFAULT_MASTER="$(getent hosts "$SERVICE-announce-0" | awk '{ print $1 }')" | ||
if [ -z "$DEFAULT_MASTER" ]; then | ||
echo "Unable to resolve host" | ||
exit 1 | ||
fi | ||
echo "Setting default slave config.." | ||
redis_update "$DEFAULT_MASTER" | ||
sentinel_update "$DEFAULT_MASTER" | ||
fi | ||
} | ||
|
||
find_master() { | ||
echo "Attempting to find master" | ||
if [ "$(redis-cli -h "$MASTER"{{ if .Values.auth }} -a "$AUTH"{{ end }} ping)" != "PONG" ]; then | ||
echo "Can't ping master, attempting to force failover" | ||
if redis-cli -h "$SERVICE" -p "$SENTINEL_PORT" sentinel failover "$MASTER_GROUP" | grep -q 'NOGOODSLAVE' ; then | ||
setup_defaults | ||
return 0 | ||
fi | ||
sleep 10 | ||
MASTER="$(redis-cli -h $SERVICE -p $SENTINEL_PORT sentinel get-master-addr-by-name $MASTER_GROUP | grep -E '[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}')" | ||
if [ "$MASTER" ]; then | ||
sentinel_update "$MASTER" | ||
redis_update "$MASTER" | ||
else | ||
echo "Could not failover, exiting..." | ||
exit 1 | ||
fi | ||
else | ||
echo "Found reachable master, updating config" | ||
sentinel_update "$MASTER" | ||
redis_update "$MASTER" | ||
fi | ||
} | ||
|
||
mkdir -p /data/conf/ | ||
|
||
echo "Initializing config.." | ||
copy_config | ||
|
||
ANNOUNCE_IP=$(getent hosts "$SERVICE-announce-$INDEX" | awk '{ print $1 }') | ||
if [ -z "$ANNOUNCE_IP" ]; then | ||
"Could not resolve the announce ip for this pod" | ||
exit 1 | ||
elif [ "$MASTER" ]; then | ||
find_master | ||
else | ||
setup_defaults | ||
fi | ||
|
||
if [ "${AUTH:-}" ]; then | ||
echo "Setting auth values" | ||
ESCAPED_AUTH=$(echo "$AUTH" | sed -e 's/[\/&]/\\&/g'); | ||
sed -i "s/replace-default-auth/${ESCAPED_AUTH}/" "$REDIS_CONF" "$SENTINEL_CONF" | ||
fi | ||
|
||
echo "Ready..." | ||
{{- end }} | ||
|
||
{{- define "config-haproxy.cfg" }} | ||
{{- if .Values.haproxy.customConfig }} | ||
{{ .Values.haproxy.customConfig | indent 4}} | ||
{{- else }} | ||
defaults REDIS | ||
mode tcp | ||
timeout connect {{ .Values.haproxy.timeout.connect }} | ||
timeout server {{ .Values.haproxy.timeout.server }} | ||
timeout client {{ .Values.haproxy.timeout.client }} | ||
|
||
listen health_check_http_url | ||
bind :8888 | ||
mode http | ||
monitor-uri /healthz | ||
option dontlognull | ||
|
||
{{- $root := . }} | ||
{{- $fullName := include "redis-ha.fullname" . }} | ||
{{- $replicas := int (toString .Values.replicas) }} | ||
{{- $masterGroupName := include "redis-ha.masterGroupName" . }} | ||
{{- range $i := until $replicas }} | ||
# Check Sentinel and whether they are nominated master | ||
backend check_if_redis_is_master_{{ $i }} | ||
mode tcp | ||
option tcp-check | ||
tcp-check connect | ||
{{- if $root.auth }} | ||
tcp-check send AUTH\ {{ $root.redisPassword }}\r\n | ||
tcp-check expect string +OK | ||
{{- end }} | ||
tcp-check send PING\r\n | ||
tcp-check expect string +PONG | ||
tcp-check send SENTINEL\ get-master-addr-by-name\ {{ $masterGroupName }}\r\n | ||
tcp-check expect string REPLACE_ANNOUNCE{{ $i }} | ||
tcp-check send QUIT\r\n | ||
tcp-check expect string +OK | ||
{{- range $i := until $replicas }} | ||
server R{{ $i }} {{ $fullName }}-announce-{{ $i }}:26379 check inter 1s | ||
{{- end }} | ||
{{- end }} | ||
|
||
# decide redis backend to use | ||
#master | ||
frontend ft_redis_master | ||
bind *:{{ $root.Values.redis.port }} | ||
use_backend bk_redis_master | ||
{{- if .Values.haproxy.readOnly.enabled }} | ||
#slave | ||
frontend ft_redis_slave | ||
bind *:{{ .Values.haproxy.readOnly.port }} | ||
use_backend bk_redis_slave | ||
{{- end }} | ||
# Check all redis servers to see if they think they are master | ||
backend bk_redis_master | ||
mode tcp | ||
option tcp-check | ||
tcp-check connect | ||
{{- if .Values.auth }} | ||
tcp-check send AUTH\ REPLACE_AUTH_SECRET\r\n | ||
tcp-check expect string +OK | ||
{{- end }} | ||
tcp-check send PING\r\n | ||
tcp-check expect string +PONG | ||
tcp-check send info\ replication\r\n | ||
tcp-check expect string role:master | ||
tcp-check send QUIT\r\n | ||
tcp-check expect string +OK | ||
{{- range $i := until $replicas }} | ||
use-server R{{ $i }} if { srv_is_up(R{{ $i }}) } { nbsrv(check_if_redis_is_master_{{ $i }}) ge 2 } | ||
server R{{ $i }} {{ $fullName }}-announce-{{ $i }}:{{ $root.Values.redis.port }} check inter 1s fall 1 rise 1 | ||
{{- end }} | ||
{{- if .Values.haproxy.readOnly.enabled }} | ||
backend bk_redis_slave | ||
mode tcp | ||
option tcp-check | ||
tcp-check connect | ||
{{- if .Values.auth }} | ||
tcp-check send AUTH\ REPLACE_AUTH_SECRET\r\n | ||
tcp-check expect string +OK | ||
{{- end }} | ||
tcp-check send PING\r\n | ||
tcp-check expect string +PONG | ||
tcp-check send info\ replication\r\n | ||
tcp-check expect string role:slave | ||
tcp-check send QUIT\r\n | ||
tcp-check expect string +OK | ||
{{- range $i := until $replicas }} | ||
server R{{ $i }} {{ $fullName }}-announce-{{ $i }}:{{ $root.Values.redis.port }} check inter 1s fall 1 rise 1 | ||
{{- end }} | ||
{{- end }} | ||
{{- if .Values.haproxy.metrics.enabled }} | ||
frontend metrics | ||
mode http | ||
bind *:{{ .Values.haproxy.metrics.port }} | ||
option http-use-htx | ||
http-request use-service prometheus-exporter if { path {{ .Values.haproxy.metrics.scrapePath }} } | ||
{{- end }} | ||
{{- if .Values.haproxy.extraConfig }} | ||
# Additional configuration | ||
{{ .Values.haproxy.extraConfig | indent 4 }} | ||
{{- end }} | ||
{{- end }} | ||
{{- end }} | ||
|
||
|
||
{{- define "config-haproxy_init.sh" }} | ||
HAPROXY_CONF=/data/haproxy.cfg | ||
cp /readonly/haproxy.cfg "$HAPROXY_CONF" | ||
{{- $fullName := include "redis-ha.fullname" . }} | ||
{{- $replicas := int (toString .Values.replicas) }} | ||
{{- range $i := until $replicas }} | ||
for loop in $(seq 1 10); do | ||
getent hosts {{ $fullName }}-announce-{{ $i }} && break | ||
echo "Waiting for service {{ $fullName }}-announce-{{ $i }} to be ready ($loop) ..." && sleep 1 | ||
done | ||
ANNOUNCE_IP{{ $i }}=$(getent hosts "{{ $fullName }}-announce-{{ $i }}" | awk '{ print $1 }') | ||
if [ -z "$ANNOUNCE_IP{{ $i }}" ]; then | ||
echo "Could not resolve the announce ip for {{ $fullName }}-announce-{{ $i }}" | ||
exit 1 | ||
fi | ||
sed -i "s/REPLACE_ANNOUNCE{{ $i }}/$ANNOUNCE_IP{{ $i }}/" "$HAPROXY_CONF" | ||
|
||
if [ "${AUTH:-}" ]; then | ||
echo "Setting auth values" | ||
ESCAPED_AUTH=$(echo "$AUTH" | sed -e 's/[\/&]/\\&/g'); | ||
sed -i "s/REPLACE_AUTH_SECRET/${ESCAPED_AUTH}/" "$HAPROXY_CONF" | ||
fi | ||
{{- end }} | ||
{{- end }} |
Oops, something went wrong.