dipup 사용 차트를 카탈로그에 동기화 (7개 갱신 + 5개 신규)
dipup 이 go:embed 로 직접 보관·관리하던 Helm 차트를 카탈로그로 옮기는 첫 단계다.
두 저장소가 각자 CVE/SBOM 파이프라인을 운영하는 이중화를 해소하려면, 먼저 카탈로그가
dipup 과 같은 차트·같은 이미지를 보게 만들어야 한다.
배경: CVE 파이프라인 구성 이전에 두 곳에서 같은 차트를 유지하기 어려워 dipup 이 별도로
차트를 관리해 왔고, 그 결과 버전이 갈라졌다. 겹치는 10개 중 버전까지 일치하는 것은
postgresql-ha·dnsup 2개뿐이었다.
## 버전 갱신 (7개) — 신규 버전 디렉토리 추가, 구버전은 보존
| 차트 | 기존 | 신규 | appVersion |
|---|---|---|---|
| apisix | 2.14.0 | 2.16.0 | 3.16.0 → 3.17.0 |
| argo-cd | 7.7.0 | 7.8.11 | v2.13.0 → v2.14.5 |
| cert-manager | v1.16.1 | v1.21.0 | 동일 |
| gitea | 12.4.0 | 12.6.0 | 1.24.6 → 1.26.1 |
| harbor | 1.16.2 | 1.19.1 | 2.12.2 → 2.15.1 |
| kyverno | 3.4.1 | 3.8.2 | v1.14.1 → v1.18.2 |
| rancher | 2.10.1 | 2.14.3 | v2.10.1 → v2.14.3 |
차트 본문은 dipup 이 임베딩한 .tgz 를 그대로 전개했다(네트워크 pull 이 아니라 dipup 이
실제 배포하는 바이트와 동일함을 보장하기 위함). BUILD-README/CUSTOM-README/custom-values
3개 파일은 구버전에서 승계했다.
## 신규 추가 (5개)
infisical-standalone 1.9.0, longhorn 109.3.1+up1.11.2, longhorn-crd 109.3.1+up1.11.2,
metallb 0.16.1, secrets-operator v0.10.33.
longhorn/longhorn-crd 는 업스트림이 아니라 Rancher 패키징 차트(109.x 라인, Rancher 2.14
계열과 짝)다. BUILD-README 의 `helm repo add` 라인은 chart_version_detector 가 파싱하는
계약이라 실제 업스트림 repo 를 검증해 기재했고, 감지기로 현재/최신 버전이 정상 조회되는
것을 확인했다.
## custom-values — 버전과 결합된 이미지 핀 정리
카탈로그 스캐너가 dipup 의 effective image 를 보게 하려면 이미지 핀이 맞아야 한다.
- **kyverno: 승계본이 3.8.2 에서 깨져 재작성.** 3.4.1 은 정리 훅이
`registry: ~ / repository: bitnami/kubectl` 이라 bitnamilegacy 오버라이드가 맞았지만,
3.8.2 는 `registry: ghcr.io / repository: kyverno/readiness-checker` 로 바뀌었다.
그대로 옮기면 ghcr.io/bitnamilegacy/kubectl 이라는 없는 좌표가 된다. 해당 오버라이드를
제거하고, 3.8.2 에서 삭제된 policyReportsCleanup 키도 함께 뺐다. 남는 조치는 tag 고정뿐
(기본 tag 가 비어 latest 로 떨어짐 → v1.18.2 로 고정).
- apisix: 3.16.0-keycloak-authz → 3.17.0-keycloak-authz (차트 appVersion 과 함께 이동)
- gitea: image.tag 1.26.4 핀 추가 — 차트 기본 1.26.1 대비 CRITICAL 2→0, HIGH 44→12
- infisical: image.tag v0.162.7 핀 — 기본 v0.158.x 는 stale Debian base 로 OS 기인 CVE
다수(fixable CRITICAL 53→5, HIGH 491→55). redis/postgresql 은 bitnamilegacy 좌표로.
- longhorn: 실측 기반 리소스 튜닝(manager request, guaranteedInstanceManagerCPU,
systemManagedCSIComponentsResourceLimits). replica 수처럼 노드 수에 의존하는 값은
넣지 않았다 — 소비 측에서 주입한다.
## 검증
12개 차트 전부 `helm template --kube-version 1.34.1` 렌더 성공. 렌더 결과 이미지가
dipup 배포 이미지와 일치함을 확인(paasup/apisix:3.17.0-keycloak-authz,
gitea:1.26.4-rootless, readiness-checker:v1.18.2, infisical:v0.162.7).
## 범위에서 뺀 것
- **keycloak**: 카탈로그는 codecentric(app 17.0.1-legacy), dipup 은 bitnami(app 26.2.4)로
계보가 다르다. 이슈 #1(bitnami 대체 방안 검토)의 결론이 나온 뒤 처리한다.
- **rancher-monitoring(-crd)**: 14c05f1 에서 불필요 판단으로 제거된 차트이고
victoria-metrics 스택으로 대체 예정이라 추가하지 않는다.
- **dip-api/dip-console**: 자체 개발 차트로 각 앱 저장소가 출처다. 대조 결과 앱 저장소와
dipup 사본이 일치해 카탈로그가 개입할 이유가 없다.
- **postgresql-ha/dnsup**: 이미 버전이 일치해 작업 대상이 아니었다.
## 후속 과제
dnsup 은 카탈로그·dipup 사본(1.0.1)이 원본(dip-console-api helm/dnsup 1.0.0)보다 앞서
있다. 1.0.1 에만 있는 service.LoadBalancerIP·service.annotations 지원을 원본으로 백포트한
뒤, 카탈로그에서 dnsup 을 제거하는 것이 자체 개발 차트 출처 원칙에 맞다.
This commit is contained in:
@@ -0,0 +1,25 @@
|
||||
Redis can be accessed via {{ if ne (int .Values.redis.port) 0 }}port {{ .Values.redis.port }}{{ end }} {{ if .Values.redis.tlsPort }} tls-port {{ .Values.redis.tlsPort }}{{ end }} and Sentinel can be accessed via {{ if ne (int .Values.sentinel.port) 0 }}port {{ .Values.sentinel.port }}{{ end }} {{ if .Values.sentinel.tlsPort }} tls-port {{ .Values.sentinel.tlsPort }}{{ end }} 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 -n {{ .Release.Namespace }} -c redis -- sh
|
||||
|
||||
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 -n {{ .Release.Namespace }} -c redis -- sh
|
||||
|
||||
2. Connect using the Redis CLI:
|
||||
|
||||
redis-cli -h {{ template "redis-ha.fullname" . }}.{{ .Release.Namespace }}.svc.cluster.local
|
||||
{{- end }}
|
||||
@@ -0,0 +1,730 @@
|
||||
{{/* 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 }}
|
||||
{{- if .Values.sentinel.tlsPort }}
|
||||
tls-port {{ .Values.redis.tlsPort }}
|
||||
tls-cert-file /tls-certs/{{ .Values.tls.certFile }}
|
||||
tls-key-file /tls-certs/{{ .Values.tls.keyFile }}
|
||||
{{- if .Values.tls.dhParamsFile }}
|
||||
tls-dh-params-file /tls-certs/{{ .Values.tls.dhParamsFile }}
|
||||
{{- end }}
|
||||
{{- if .Values.tls.caCertFile }}
|
||||
tls-ca-cert-file /tls-certs/{{ .Values.tls.caCertFile }}
|
||||
{{- end }}
|
||||
{{- if eq (default "yes" .Values.redis.authClients) "no"}}
|
||||
tls-auth-clients no
|
||||
{{- end }}
|
||||
tls-replication {{ if .Values.redis.tlsReplication }}yes{{ else }}no{{ end }}
|
||||
{{- end }}
|
||||
{{- if .Values.redis.disableCommands }}
|
||||
{{- range .Values.redis.disableCommands }}
|
||||
rename-command {{ . }} ""
|
||||
{{- end }}
|
||||
{{- end }}
|
||||
{{- range $key, $value := .Values.redis.config }}
|
||||
{{- if kindIs "slice" $value }}
|
||||
{{- range $value }}
|
||||
{{ $key }} {{ . }}
|
||||
{{- end }}
|
||||
{{- else }}
|
||||
{{ $key }} {{ $value }}
|
||||
{{- end }}
|
||||
{{- 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"
|
||||
port {{ .Values.sentinel.port }}
|
||||
{{- if .Values.sentinel.bind }}
|
||||
bind {{ .Values.sentinel.bind }}
|
||||
{{- end }}
|
||||
{{- if .Values.sentinel.tlsPort }}
|
||||
tls-port {{ .Values.sentinel.tlsPort }}
|
||||
tls-cert-file /tls-certs/{{ .Values.tls.certFile }}
|
||||
tls-key-file /tls-certs/{{ .Values.tls.keyFile }}
|
||||
{{- if .Values.tls.dhParamsFile }}
|
||||
tls-dh-params-file /tls-certs/{{ .Values.tls.dhParamsFile }}
|
||||
{{- end }}
|
||||
{{- if .Values.tls.caCertFile }}
|
||||
tls-ca-cert-file /tls-certs/{{ .Values.tls.caCertFile }}
|
||||
{{- end }}
|
||||
{{- if eq (default "yes" .Values.sentinel.authClients) "no"}}
|
||||
tls-auth-clients no
|
||||
{{- end }}
|
||||
tls-replication {{ if .Values.sentinel.tlsReplication }}yes{{ else }}no{{ end }}
|
||||
{{- end }}
|
||||
{{- range $key, $value := .Values.sentinel.config }}
|
||||
{{- if eq "maxclients" $key }}
|
||||
{{ $key }} {{ $value }}
|
||||
{{- else }}
|
||||
sentinel {{ $key }} {{ template "redis-ha.masterGroupName" $ }} {{ $value }}
|
||||
{{- end }}
|
||||
{{- end }}
|
||||
{{- if .Values.auth }}
|
||||
sentinel auth-pass {{ template "redis-ha.masterGroupName" . }} replace-default-auth
|
||||
{{- end }}
|
||||
{{- if .Values.sentinel.auth }}
|
||||
requirepass replace-default-sentinel-auth
|
||||
{{- end }}
|
||||
{{- end }}
|
||||
{{- end }}
|
||||
|
||||
{{- define "lib.sh" }}
|
||||
sentinel_get_master() {
|
||||
set +e
|
||||
if [ "$SENTINEL_PORT" -eq 0 ]; then
|
||||
redis-cli -h "${SERVICE}" -p "${SENTINEL_TLS_PORT}" {{ if .Values.sentinel.auth }} -a "${SENTINELAUTH}" --no-auth-warning{{ end }} --tls --cacert /tls-certs/{{ .Values.tls.caCertFile }} {{ if ne (default "yes" .Values.sentinel.authClients) "no"}} --cert /tls-certs/{{ .Values.tls.certFile }} --key /tls-certs/{{ .Values.tls.keyFile }}{{ end }} sentinel get-master-addr-by-name "${MASTER_GROUP}" |\
|
||||
grep -E '((^\s*((([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])\.){3}([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5]))\s*$)|(^\s*((([0-9A-Fa-f]{1,4}:){7}([0-9A-Fa-f]{1,4}|:))|(([0-9A-Fa-f]{1,4}:){6}(:[0-9A-Fa-f]{1,4}|((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3})|:))|(([0-9A-Fa-f]{1,4}:){5}(((:[0-9A-Fa-f]{1,4}){1,2})|:((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3})|:))|(([0-9A-Fa-f]{1,4}:){4}(((:[0-9A-Fa-f]{1,4}){1,3})|((:[0-9A-Fa-f]{1,4})?:((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3}))|:))|(([0-9A-Fa-f]{1,4}:){3}(((:[0-9A-Fa-f]{1,4}){1,4})|((:[0-9A-Fa-f]{1,4}){0,2}:((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3}))|:))|(([0-9A-Fa-f]{1,4}:){2}(((:[0-9A-Fa-f]{1,4}){1,5})|((:[0-9A-Fa-f]{1,4}){0,3}:((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3}))|:))|(([0-9A-Fa-f]{1,4}:){1}(((:[0-9A-Fa-f]{1,4}){1,6})|((:[0-9A-Fa-f]{1,4}){0,4}:((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3}))|:))|(:(((:[0-9A-Fa-f]{1,4}){1,7})|((:[0-9A-Fa-f]{1,4}){0,5}:((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3}))|:)))(%.+)?s*$))'
|
||||
else
|
||||
redis-cli -h "${SERVICE}" -p "${SENTINEL_PORT}" {{ if .Values.sentinel.auth }} -a "${SENTINELAUTH}" --no-auth-warning{{ end }} sentinel get-master-addr-by-name "${MASTER_GROUP}" |\
|
||||
grep -E '((^\s*((([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])\.){3}([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5]))\s*$)|(^\s*((([0-9A-Fa-f]{1,4}:){7}([0-9A-Fa-f]{1,4}|:))|(([0-9A-Fa-f]{1,4}:){6}(:[0-9A-Fa-f]{1,4}|((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3})|:))|(([0-9A-Fa-f]{1,4}:){5}(((:[0-9A-Fa-f]{1,4}){1,2})|:((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3})|:))|(([0-9A-Fa-f]{1,4}:){4}(((:[0-9A-Fa-f]{1,4}){1,3})|((:[0-9A-Fa-f]{1,4})?:((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3}))|:))|(([0-9A-Fa-f]{1,4}:){3}(((:[0-9A-Fa-f]{1,4}){1,4})|((:[0-9A-Fa-f]{1,4}){0,2}:((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3}))|:))|(([0-9A-Fa-f]{1,4}:){2}(((:[0-9A-Fa-f]{1,4}){1,5})|((:[0-9A-Fa-f]{1,4}){0,3}:((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3}))|:))|(([0-9A-Fa-f]{1,4}:){1}(((:[0-9A-Fa-f]{1,4}){1,6})|((:[0-9A-Fa-f]{1,4}){0,4}:((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3}))|:))|(:(((:[0-9A-Fa-f]{1,4}){1,7})|((:[0-9A-Fa-f]{1,4}){0,5}:((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3}))|:)))(%.+)?s*$))'
|
||||
fi
|
||||
set -e
|
||||
}
|
||||
|
||||
sentinel_get_master_retry() {
|
||||
master=''
|
||||
retry=${1}
|
||||
sleep=3
|
||||
for i in $(seq 1 "${retry}"); do
|
||||
master=$(sentinel_get_master)
|
||||
if [ -n "${master}" ]; then
|
||||
break
|
||||
fi
|
||||
sleep $((sleep + i))
|
||||
done
|
||||
echo "${master}"
|
||||
}
|
||||
|
||||
identify_master() {
|
||||
echo "Identifying redis master (get-master-addr-by-name).."
|
||||
echo " using sentinel ({{ template "redis-ha.fullname" . }}), sentinel group name ({{ template "redis-ha.masterGroupName" . }})"
|
||||
MASTER="$(sentinel_get_master_retry 3)"
|
||||
if [ -n "${MASTER}" ]; then
|
||||
echo " $(date) Found redis master (${MASTER})"
|
||||
else
|
||||
echo " $(date) Did not find redis master (${MASTER})"
|
||||
fi
|
||||
}
|
||||
|
||||
sentinel_update() {
|
||||
echo "Updating sentinel config.."
|
||||
echo " evaluating sentinel id (\${SENTINEL_ID_${INDEX}})"
|
||||
eval MY_SENTINEL_ID="\$SENTINEL_ID_${INDEX}"
|
||||
echo " sentinel id (${MY_SENTINEL_ID}), sentinel grp (${MASTER_GROUP}), quorum (${QUORUM})"
|
||||
sed -i "1s/^/sentinel myid ${MY_SENTINEL_ID}\\n/" "${SENTINEL_CONF}"
|
||||
if [ "$SENTINEL_TLS_REPLICATION_ENABLED" = true ]; then
|
||||
echo " redis master (${1}:${REDIS_TLS_PORT})"
|
||||
sed -i "2s/^/sentinel monitor ${MASTER_GROUP} ${1} ${REDIS_TLS_PORT} ${QUORUM} \\n/" "${SENTINEL_CONF}"
|
||||
else
|
||||
echo " redis master (${1}:${REDIS_PORT})"
|
||||
sed -i "2s/^/sentinel monitor ${MASTER_GROUP} ${1} ${REDIS_PORT} ${QUORUM} \\n/" "${SENTINEL_CONF}"
|
||||
fi
|
||||
echo "sentinel announce-ip ${ANNOUNCE_IP}" >> ${SENTINEL_CONF}
|
||||
if [ "$SENTINEL_PORT" -eq 0 ]; then
|
||||
echo " announce (${ANNOUNCE_IP}:${SENTINEL_TLS_PORT})"
|
||||
echo "sentinel announce-port ${SENTINEL_TLS_PORT}" >> ${SENTINEL_CONF}
|
||||
else
|
||||
echo " announce (${ANNOUNCE_IP}:${SENTINEL_PORT})"
|
||||
echo "sentinel announce-port ${SENTINEL_PORT}" >> ${SENTINEL_CONF}
|
||||
fi
|
||||
}
|
||||
|
||||
redis_update() {
|
||||
echo "Updating redis config.."
|
||||
if [ "$REDIS_TLS_REPLICATION_ENABLED" = true ]; then
|
||||
echo " we are slave of redis master (${1}:${REDIS_TLS_PORT})"
|
||||
echo "slaveof ${1} ${REDIS_TLS_PORT}" >> "${REDIS_CONF}"
|
||||
echo "slave-announce-port ${REDIS_TLS_PORT}" >> ${REDIS_CONF}
|
||||
else
|
||||
echo " we are slave of redis master (${1}:${REDIS_PORT})"
|
||||
echo "slaveof ${1} ${REDIS_PORT}" >> "${REDIS_CONF}"
|
||||
echo "slave-announce-port ${REDIS_PORT}" >> ${REDIS_CONF}
|
||||
fi
|
||||
echo "slave-announce-ip ${ANNOUNCE_IP}" >> ${REDIS_CONF}
|
||||
}
|
||||
|
||||
copy_config() {
|
||||
echo "Copying default redis config.."
|
||||
echo " to '${REDIS_CONF}'"
|
||||
cp /readonly-config/redis.conf "${REDIS_CONF}"
|
||||
echo "Copying default sentinel config.."
|
||||
echo " to '${SENTINEL_CONF}'"
|
||||
cp /readonly-config/sentinel.conf "${SENTINEL_CONF}"
|
||||
}
|
||||
|
||||
setup_defaults() {
|
||||
echo "Setting up defaults.."
|
||||
echo " using statefulset index (${INDEX})"
|
||||
if [ "${INDEX}" = "0" ]; then
|
||||
echo "Setting this pod as master for redis and sentinel.."
|
||||
echo " using announce (${ANNOUNCE_IP})"
|
||||
redis_update "${ANNOUNCE_IP}"
|
||||
sentinel_update "${ANNOUNCE_IP}"
|
||||
echo " make sure ${ANNOUNCE_IP} is not a slave (slaveof no one)"
|
||||
sed -i "s/^.*slaveof.*//" "${REDIS_CONF}"
|
||||
else
|
||||
echo "Getting redis master ip.."
|
||||
echo " blindly assuming (${SERVICE}-announce-0) or (${SERVICE}-server-0) are master"
|
||||
DEFAULT_MASTER="$(getent_hosts 0 | awk '{ print $1 }')"
|
||||
if [ -z "${DEFAULT_MASTER}" ]; then
|
||||
echo "Error: Unable to resolve redis master (getent hosts)."
|
||||
exit 1
|
||||
fi
|
||||
echo " identified redis (may be redis master) ip (${DEFAULT_MASTER})"
|
||||
echo "Setting default slave config for redis and sentinel.."
|
||||
echo " using master ip (${DEFAULT_MASTER})"
|
||||
redis_update "${DEFAULT_MASTER}"
|
||||
sentinel_update "${DEFAULT_MASTER}"
|
||||
fi
|
||||
}
|
||||
|
||||
redis_ping() {
|
||||
set +e
|
||||
if [ "$REDIS_PORT" -eq 0 ]; then
|
||||
redis-cli -h "${MASTER}"{{ if .Values.auth }} -a "${AUTH}" --no-auth-warning{{ end }} -p "${REDIS_TLS_PORT}" --tls --cacert /tls-certs/{{ .Values.tls.caCertFile }} {{ if ne (default "yes" .Values.sentinel.authClients) "no"}} --cert /tls-certs/{{ .Values.tls.certFile }} --key /tls-certs/{{ .Values.tls.keyFile }}{{ end }} ping
|
||||
else
|
||||
redis-cli -h "${MASTER}"{{ if .Values.auth }} -a "${AUTH}" --no-auth-warning{{ end }} -p "${REDIS_PORT}" ping
|
||||
fi
|
||||
set -e
|
||||
}
|
||||
|
||||
redis_ping_retry() {
|
||||
ping=''
|
||||
retry=${1}
|
||||
sleep=3
|
||||
for i in $(seq 1 "${retry}"); do
|
||||
if [ "$(redis_ping)" = "PONG" ]; then
|
||||
ping='PONG'
|
||||
break
|
||||
fi
|
||||
sleep $((sleep + i))
|
||||
MASTER=$(sentinel_get_master)
|
||||
done
|
||||
echo "${ping}"
|
||||
}
|
||||
|
||||
find_master() {
|
||||
echo "Verifying redis master.."
|
||||
if [ "$REDIS_PORT" -eq 0 ]; then
|
||||
echo " ping (${MASTER}:${REDIS_TLS_PORT})"
|
||||
else
|
||||
echo " ping (${MASTER}:${REDIS_PORT})"
|
||||
fi
|
||||
if [ "$(redis_ping_retry 3)" != "PONG" ]; then
|
||||
echo " $(date) Can't ping redis master (${MASTER})"
|
||||
echo "Attempting to force failover (sentinel failover).."
|
||||
|
||||
if [ "$SENTINEL_PORT" -eq 0 ]; then
|
||||
echo " on sentinel (${SERVICE}:${SENTINEL_TLS_PORT}), sentinel grp (${MASTER_GROUP})"
|
||||
if redis-cli -h "${SERVICE}" -p "${SENTINEL_TLS_PORT}" {{ if .Values.sentinel.auth }} -a "${SENTINELAUTH}" --no-auth-warning{{ end }} --tls --cacert /tls-certs/{{ .Values.tls.caCertFile }} {{ if ne (default "yes" .Values.sentinel.authClients) "no"}} --cert /tls-certs/{{ .Values.tls.certFile }} --key /tls-certs/{{ .Values.tls.keyFile }}{{ end }} sentinel failover "${MASTER_GROUP}" | grep -q 'NOGOODSLAVE' ; then
|
||||
echo " $(date) Failover returned with 'NOGOODSLAVE'"
|
||||
echo "Setting defaults for this pod.."
|
||||
setup_defaults
|
||||
return 0
|
||||
fi
|
||||
else
|
||||
echo " on sentinel (${SERVICE}:${SENTINEL_PORT}), sentinel grp (${MASTER_GROUP})"
|
||||
if redis-cli -h "${SERVICE}" -p "${SENTINEL_PORT}" {{ if .Values.sentinel.auth }} -a "${SENTINELAUTH}" --no-auth-warning{{ end }} sentinel failover "${MASTER_GROUP}" | grep -q 'NOGOODSLAVE' ; then
|
||||
echo " $(date) Failover returned with 'NOGOODSLAVE'"
|
||||
echo "Setting defaults for this pod.."
|
||||
setup_defaults
|
||||
return 0
|
||||
fi
|
||||
fi
|
||||
|
||||
echo "Hold on for 10sec"
|
||||
sleep 10
|
||||
echo "We should get redis master's ip now. Asking (get-master-addr-by-name).."
|
||||
if [ "$SENTINEL_PORT" -eq 0 ]; then
|
||||
echo " sentinel (${SERVICE}:${SENTINEL_TLS_PORT}), sentinel grp (${MASTER_GROUP})"
|
||||
else
|
||||
echo " sentinel (${SERVICE}:${SENTINEL_PORT}), sentinel grp (${MASTER_GROUP})"
|
||||
fi
|
||||
MASTER="$(sentinel_get_master)"
|
||||
if [ "${MASTER}" ]; then
|
||||
echo " $(date) Found redis master (${MASTER})"
|
||||
echo "Updating redis and sentinel config.."
|
||||
sentinel_update "${MASTER}"
|
||||
redis_update "${MASTER}"
|
||||
else
|
||||
echo "$(date) Error: Could not failover, exiting..."
|
||||
exit 1
|
||||
fi
|
||||
else
|
||||
echo " $(date) Found reachable redis master (${MASTER})"
|
||||
echo "Updating redis and sentinel config.."
|
||||
sentinel_update "${MASTER}"
|
||||
redis_update "${MASTER}"
|
||||
fi
|
||||
}
|
||||
|
||||
redis_ro_update() {
|
||||
echo "Updating read-only redis config.."
|
||||
echo " redis.conf set 'replica-priority 0'"
|
||||
echo "replica-priority 0" >> ${REDIS_CONF}
|
||||
}
|
||||
|
||||
getent_hosts() {
|
||||
index=${1:-${INDEX}}
|
||||
service="${SERVICE}-announce-${index}"
|
||||
host=$(getent hosts "${service}")
|
||||
echo "${host}"
|
||||
}
|
||||
|
||||
identify_announce_ip() {
|
||||
echo "Identify announce ip for this pod.."
|
||||
echo " using (${SERVICE}-announce-${INDEX}) or (${SERVICE}-server-${INDEX})"
|
||||
ANNOUNCE_IP=$(getent_hosts | awk '{ print $1 }')
|
||||
echo " identified announce (${ANNOUNCE_IP})"
|
||||
}
|
||||
{{- end }}
|
||||
|
||||
{{- define "vars.sh" }}
|
||||
HOSTNAME="$(hostname)"
|
||||
{{- if .Values.ro_replicas }}
|
||||
RO_REPLICAS="{{ .Values.ro_replicas }}"
|
||||
{{- end }}
|
||||
INDEX="${HOSTNAME##*-}"
|
||||
SENTINEL_PORT={{ .Values.sentinel.port }}
|
||||
ANNOUNCE_IP=''
|
||||
MASTER=''
|
||||
MASTER_GROUP="{{ template "redis-ha.masterGroupName" . }}"
|
||||
QUORUM="{{ .Values.sentinel.quorum }}"
|
||||
REDIS_CONF=/data/conf/redis.conf
|
||||
REDIS_PORT={{ .Values.redis.port }}
|
||||
REDIS_TLS_PORT={{ .Values.redis.tlsPort }}
|
||||
SENTINEL_CONF=/data/conf/sentinel.conf
|
||||
SENTINEL_TLS_PORT={{ .Values.sentinel.tlsPort }}
|
||||
SERVICE={{ template "redis-ha.fullname" . }}
|
||||
SENTINEL_TLS_REPLICATION_ENABLED={{ default false .Values.sentinel.tlsReplication }}
|
||||
REDIS_TLS_REPLICATION_ENABLED={{ default false .Values.redis.tlsReplication }}
|
||||
{{- end }}
|
||||
|
||||
{{- define "config-init.sh" }}
|
||||
echo "$(date) Start..."
|
||||
{{- include "vars.sh" . }}
|
||||
|
||||
set -eu
|
||||
|
||||
{{- include "lib.sh" . }}
|
||||
|
||||
mkdir -p /data/conf/
|
||||
|
||||
echo "Initializing config.."
|
||||
copy_config
|
||||
|
||||
# where is redis master
|
||||
identify_master
|
||||
|
||||
identify_announce_ip
|
||||
|
||||
if [ -z "${ANNOUNCE_IP}" ]; then
|
||||
"Error: Could not resolve the announce ip for this pod."
|
||||
exit 1
|
||||
elif [ "${MASTER}" ]; then
|
||||
find_master
|
||||
else
|
||||
setup_defaults
|
||||
fi
|
||||
|
||||
{{- if .Values.ro_replicas }}
|
||||
# works only if index is less than 10
|
||||
echo "Verifying redis read-only replica.."
|
||||
echo " we have RO_REPLICAS='${RO_REPLICAS}' with INDEX='${INDEX}'"
|
||||
if echo "${RO_REPLICAS}" | grep -q "${INDEX}" ; then
|
||||
redis_ro_update
|
||||
fi
|
||||
{{- end }}
|
||||
|
||||
if [ "${AUTH:-}" ]; then
|
||||
echo "Setting redis auth values.."
|
||||
ESCAPED_AUTH=$(echo "${AUTH}" | sed -e 's/[\/&]/\\&/g');
|
||||
sed -i "s/replace-default-auth/${ESCAPED_AUTH}/" "${REDIS_CONF}" "${SENTINEL_CONF}"
|
||||
fi
|
||||
|
||||
if [ "${SENTINELAUTH:-}" ]; then
|
||||
echo "Setting sentinel auth values"
|
||||
ESCAPED_AUTH_SENTINEL=$(echo "$SENTINELAUTH" | sed -e 's/[\/&]/\\&/g');
|
||||
sed -i "s/replace-default-sentinel-auth/${ESCAPED_AUTH_SENTINEL}/" "$SENTINEL_CONF"
|
||||
fi
|
||||
|
||||
echo "$(date) Ready..."
|
||||
{{- end }}
|
||||
|
||||
{{- define "trigger-failover-if-master.sh" }}
|
||||
{{- if or (eq (int .Values.redis.port) 0) (eq (int .Values.sentinel.port) 0) }}
|
||||
TLS_CLIENT_OPTION="--tls --cacert /tls-certs/{{ .Values.tls.caCertFile }}{{ if ne (default "yes" .Values.sentinel.authClients) "no"}} --cert /tls-certs/{{ .Values.tls.certFile }} --key /tls-certs/{{ .Values.tls.keyFile }}{{end}}"
|
||||
{{- end }}
|
||||
get_redis_role() {
|
||||
is_master=$(
|
||||
redis-cli \
|
||||
{{- if .Values.auth }}
|
||||
-a "${AUTH}" --no-auth-warning \
|
||||
{{- end }}
|
||||
-h localhost \
|
||||
{{- if (int .Values.redis.port) }}
|
||||
-p {{ .Values.redis.port }} \
|
||||
{{- else }}
|
||||
-p {{ .Values.redis.tlsPort }} ${TLS_CLIENT_OPTION} \
|
||||
{{- end}}
|
||||
info | grep -c 'role:master' || true
|
||||
)
|
||||
}
|
||||
get_redis_role
|
||||
if [[ "$is_master" -eq 1 ]]; then
|
||||
echo "This node is currently master, we trigger a failover."
|
||||
{{- $masterGroupName := include "redis-ha.masterGroupName" . }}
|
||||
response=$(
|
||||
redis-cli \
|
||||
{{- if .Values.sentinel.auth }}
|
||||
-a "${SENTINELAUTH}" --no-auth-warning \
|
||||
{{- end }}
|
||||
-h localhost \
|
||||
{{- if (int .Values.sentinel.port) }}
|
||||
-p {{ .Values.sentinel.port }} \
|
||||
{{- else }}
|
||||
-p {{ .Values.sentinel.tlsPort }} ${TLS_CLIENT_OPTION} \
|
||||
{{- end}}
|
||||
SENTINEL failover {{ $masterGroupName }}
|
||||
)
|
||||
if [[ "$response" != "OK" ]] ; then
|
||||
echo "$response"
|
||||
exit 1
|
||||
fi
|
||||
timeout=30
|
||||
while [[ "$is_master" -eq 1 && $timeout -gt 0 ]]; do
|
||||
sleep 1
|
||||
get_redis_role
|
||||
timeout=$((timeout - 1))
|
||||
done
|
||||
echo "Failover successful"
|
||||
fi
|
||||
{{- end }}
|
||||
|
||||
{{- define "fix-split-brain.sh" }}
|
||||
{{- include "vars.sh" . }}
|
||||
|
||||
ROLE=''
|
||||
REDIS_MASTER=''
|
||||
|
||||
set -eu
|
||||
|
||||
{{- include "lib.sh" . }}
|
||||
|
||||
redis_role() {
|
||||
set +e
|
||||
if [ "$REDIS_PORT" -eq 0 ]; then
|
||||
ROLE=$(redis-cli {{ if .Values.auth }} -a "${AUTH}" --no-auth-warning{{ end }} -p "${REDIS_TLS_PORT}" --tls --cacert /tls-certs/{{ .Values.tls.caCertFile }} {{ if ne (default "yes" .Values.sentinel.authClients) "no"}} --cert /tls-certs/{{ .Values.tls.certFile }} --key /tls-certs/{{ .Values.tls.keyFile }}{{ end }} info | grep role | sed 's/role://' | sed 's/\r//')
|
||||
else
|
||||
ROLE=$(redis-cli {{ if .Values.auth }} -a "${AUTH}" --no-auth-warning{{ end }} -p "${REDIS_PORT}" info | grep role | sed 's/role://' | sed 's/\r//')
|
||||
fi
|
||||
set -e
|
||||
}
|
||||
|
||||
identify_redis_master() {
|
||||
set +e
|
||||
if [ "$REDIS_PORT" -eq 0 ]; then
|
||||
REDIS_MASTER=$(redis-cli {{ if .Values.auth }} -a "${AUTH}" --no-auth-warning{{ end }} -p "${REDIS_TLS_PORT}" --tls --cacert /tls-certs/{{ .Values.tls.caCertFile }} {{ if ne (default "yes" .Values.sentinel.authClients) "no"}} --cert /tls-certs/{{ .Values.tls.certFile }} --key /tls-certs/{{ .Values.tls.keyFile }}{{ end }} info | grep master_host | sed 's/master_host://' | sed 's/\r//')
|
||||
else
|
||||
REDIS_MASTER=$(redis-cli {{ if .Values.auth }} -a "${AUTH}" --no-auth-warning{{ end }} -p "${REDIS_PORT}" info | grep master_host | sed 's/master_host://' | sed 's/\r//')
|
||||
fi
|
||||
set -e
|
||||
}
|
||||
|
||||
reinit() {
|
||||
set +e
|
||||
sh /readonly-config/init.sh
|
||||
|
||||
if [ "$REDIS_PORT" -eq 0 ]; then
|
||||
echo "shutdown" | redis-cli {{ if .Values.auth }} -a "${AUTH}" --no-auth-warning{{ end }} -p "${REDIS_TLS_PORT}" --tls --cacert /tls-certs/{{ .Values.tls.caCertFile }} {{ if ne (default "yes" .Values.sentinel.authClients) "no"}} --cert /tls-certs/{{ .Values.tls.certFile }} --key /tls-certs/{{ .Values.tls.keyFile }}{{ end }}
|
||||
else
|
||||
echo "shutdown" | redis-cli {{ if .Values.auth }} -a "${AUTH}" --no-auth-warning{{ end }} -p "${REDIS_PORT}"
|
||||
fi
|
||||
set -e
|
||||
}
|
||||
|
||||
identify_announce_ip
|
||||
|
||||
while [ -z "${ANNOUNCE_IP}" ]; do
|
||||
echo "Error: Could not resolve the announce ip for this pod."
|
||||
sleep 30
|
||||
identify_announce_ip
|
||||
done
|
||||
|
||||
trap "exit 0" TERM
|
||||
while true; do
|
||||
sleep {{ .Values.splitBrainDetection.interval }}
|
||||
|
||||
# where is redis master
|
||||
identify_master
|
||||
|
||||
if [ "$MASTER" = "$ANNOUNCE_IP" ]; then
|
||||
redis_role
|
||||
if [ "$ROLE" != "master" ]; then
|
||||
reinit
|
||||
fi
|
||||
elif [ "${MASTER}" ]; then
|
||||
identify_redis_master
|
||||
if [ "$REDIS_MASTER" != "$MASTER" ]; then
|
||||
reinit
|
||||
fi
|
||||
fi
|
||||
done
|
||||
|
||||
{{- end }}
|
||||
|
||||
{{- define "config-haproxy.cfg" }}
|
||||
{{- if .Values.haproxy.customConfig }}
|
||||
{{ tpl .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 }}
|
||||
timeout check {{ .Values.haproxy.timeout.check }}
|
||||
|
||||
listen health_check_http_url
|
||||
bind {{ if .Values.haproxy.IPv6.enabled }}[::]{{ end }}:8888 {{ if .Values.haproxy.IPv6.enabled }}v4v6{{ end }}
|
||||
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.Values.sentinel.auth }}
|
||||
tcp-check send "AUTH ${SENTINELAUTH}"\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
|
||||
{{- range $i := until $replicas }}
|
||||
server R{{ $i }} {{ $fullName }}-announce-{{ $i }}:26379 check inter {{ $root.Values.haproxy.checkInterval }}
|
||||
{{- end }}
|
||||
{{- end }}
|
||||
|
||||
# decide redis backend to use
|
||||
#master
|
||||
frontend ft_redis_master
|
||||
{{- if .Values.haproxy.tls.enabled }}
|
||||
bind {{ if .Values.haproxy.IPv6.enabled }}[::]{{ end }}:{{ $root.Values.haproxy.containerPort }} ssl crt {{ .Values.haproxy.tls.certMountPath }}{{ .Values.haproxy.tls.keyName }} {{ if .Values.haproxy.IPv6.enabled }}v4v6{{ end }}
|
||||
{{ else }}
|
||||
bind {{ if .Values.haproxy.IPv6.enabled }}[::]{{ end }}:{{ $root.Values.redis.port }} {{ if .Values.haproxy.IPv6.enabled }}v4v6{{ end }}
|
||||
{{- end }}
|
||||
use_backend bk_redis_master
|
||||
{{- if .Values.haproxy.readOnly.enabled }}
|
||||
#slave
|
||||
frontend ft_redis_slave
|
||||
bind {{ if .Values.haproxy.IPv6.enabled }}[::]{{ end }}:{{ .Values.haproxy.readOnly.port }} {{ if .Values.haproxy.IPv6.enabled }}v4v6{{ end }}
|
||||
use_backend bk_redis_slave
|
||||
{{- end }}
|
||||
# Check all redis servers to see if they think they are master
|
||||
backend bk_redis_master
|
||||
{{- if .Values.haproxy.stickyBalancing }}
|
||||
balance source
|
||||
hash-type consistent
|
||||
{{- end }}
|
||||
mode tcp
|
||||
option tcp-check
|
||||
tcp-check connect
|
||||
{{- if .Values.auth }}
|
||||
tcp-check send "AUTH ${AUTH}"\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 {{ $root.Values.haproxy.checkInterval }} fall {{ $root.Values.haproxy.checkFall }} rise 1
|
||||
{{- end }}
|
||||
{{- if .Values.haproxy.readOnly.enabled }}
|
||||
backend bk_redis_slave
|
||||
{{- if .Values.haproxy.stickyBalancing }}
|
||||
balance source
|
||||
hash-type consistent
|
||||
{{- end }}
|
||||
mode tcp
|
||||
option tcp-check
|
||||
tcp-check connect
|
||||
{{- if .Values.auth }}
|
||||
tcp-check send "AUTH ${AUTH}"\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 {{ $root.Values.haproxy.checkInterval }} fall {{ $root.Values.haproxy.checkFall }} rise 1
|
||||
{{- end }}
|
||||
{{- end }}
|
||||
{{- if .Values.haproxy.metrics.enabled }}
|
||||
frontend stats
|
||||
mode http
|
||||
bind {{ if .Values.haproxy.IPv6.enabled }}[::]{{ end }}:{{ .Values.haproxy.metrics.port }} {{ if .Values.haproxy.IPv6.enabled }}v4v6{{ end }}
|
||||
http-request use-service prometheus-exporter if { path {{ .Values.haproxy.metrics.scrapePath }} }
|
||||
stats enable
|
||||
stats uri /stats
|
||||
stats refresh 10s
|
||||
{{- 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"
|
||||
|
||||
{{- end }}
|
||||
{{- end }}
|
||||
|
||||
{{- define "redis_liveness.sh" }}
|
||||
{{- if not (ne (int .Values.sentinel.port) 0) }}
|
||||
TLS_CLIENT_OPTION="--tls --cacert /tls-certs/{{ .Values.tls.caCertFile }}{{ if ne (default "yes" .Values.sentinel.authClients) "no"}} --cert /tls-certs/{{ .Values.tls.certFile }} --key /tls-certs/{{ .Values.tls.keyFile }}{{end}}"
|
||||
{{- end }}
|
||||
response=$(
|
||||
redis-cli \
|
||||
{{- if .Values.auth }}
|
||||
-a "${AUTH}" --no-auth-warning \
|
||||
{{- end }}
|
||||
-h localhost \
|
||||
{{- if ne (int .Values.redis.port) 0 }}
|
||||
-p {{ .Values.redis.port }} \
|
||||
{{- else }}
|
||||
-p {{ .Values.redis.tlsPort }} ${TLS_CLIENT_OPTION} \
|
||||
{{- end}}
|
||||
ping
|
||||
)
|
||||
echo "response=$response"
|
||||
case $response in
|
||||
PONG|LOADING*) ;;
|
||||
*) exit 1 ;;
|
||||
esac
|
||||
exit 0
|
||||
{{- end }}
|
||||
|
||||
{{- define "redis_readiness.sh" }}
|
||||
{{- if not (ne (int .Values.sentinel.port) 0) }}
|
||||
TLS_CLIENT_OPTION="--tls --cacert /tls-certs/{{ .Values.tls.caCertFile }}{{ if ne (default "yes" .Values.sentinel.authClients) "no"}} --cert /tls-certs/{{ .Values.tls.certFile }} --key /tls-certs/{{ .Values.tls.keyFile }}{{end}}"
|
||||
{{- end }}
|
||||
response=$(
|
||||
redis-cli \
|
||||
{{- if .Values.auth }}
|
||||
-a "${AUTH}" --no-auth-warning \
|
||||
{{- end }}
|
||||
-h localhost \
|
||||
{{- if ne (int .Values.redis.port) 0 }}
|
||||
-p {{ .Values.redis.port }} \
|
||||
{{- else }}
|
||||
-p {{ .Values.redis.tlsPort }} ${TLS_CLIENT_OPTION} \
|
||||
{{- end}}
|
||||
ping
|
||||
)
|
||||
if [ "$response" != "PONG" ] ; then
|
||||
echo "ping=$response"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
response=$(
|
||||
redis-cli \
|
||||
{{- if .Values.auth }}
|
||||
-a "${AUTH}" --no-auth-warning \
|
||||
{{- end }}
|
||||
-h localhost \
|
||||
{{- if ne (int .Values.redis.port) 0 }}
|
||||
-p {{ .Values.redis.port }} \
|
||||
{{- else }}
|
||||
-p {{ .Values.redis.tlsPort }} ${TLS_CLIENT_OPTION} \
|
||||
{{- end}}
|
||||
role
|
||||
)
|
||||
role=$( echo "$response" | sed "1!d" )
|
||||
if [ "$role" = "master" ]; then
|
||||
echo "role=$role"
|
||||
exit 0
|
||||
elif [ "$role" = "slave" ]; then
|
||||
repl=$( echo "$response" | sed "4!d" )
|
||||
echo "role=$role; repl=$repl"
|
||||
if [ "$repl" = "connected" ]; then
|
||||
exit 0
|
||||
else
|
||||
exit 1
|
||||
fi
|
||||
else
|
||||
echo "role=$role"
|
||||
exit 1
|
||||
fi
|
||||
{{- end }}
|
||||
|
||||
{{- define "sentinel_liveness.sh" }}
|
||||
{{- if not (ne (int .Values.sentinel.port) 0) }}
|
||||
TLS_CLIENT_OPTION="--tls --cacert /tls-certs/{{ .Values.tls.caCertFile }}{{ if ne (default "yes" .Values.sentinel.authClients) "no"}} --cert /tls-certs/{{ .Values.tls.certFile }} --key /tls-certs/{{ .Values.tls.keyFile }}{{end}}"
|
||||
{{- end }}
|
||||
response=$(
|
||||
redis-cli \
|
||||
{{- if .Values.sentinel.auth }}
|
||||
-a "${SENTINELAUTH}" --no-auth-warning \
|
||||
{{- end }}
|
||||
-h localhost \
|
||||
{{- if ne (int .Values.sentinel.port) 0 }}
|
||||
-p {{ .Values.sentinel.port }} \
|
||||
{{- else }}
|
||||
-p {{ .Values.sentinel.tlsPort }} ${TLS_CLIENT_OPTION} \
|
||||
{{- end}}
|
||||
ping
|
||||
)
|
||||
if [ "$response" != "PONG" ]; then
|
||||
echo "$response"
|
||||
exit 1
|
||||
fi
|
||||
echo "response=$response"
|
||||
{{- end }}
|
||||
|
||||
@@ -0,0 +1,130 @@
|
||||
{{/* vim: set filetype=mustache: */}}
|
||||
|
||||
{{/*
|
||||
Create a default fully qualified app name.
|
||||
We truncate at 63 chars because some Kubernetes name fields are limited to this (by the DNS naming spec).
|
||||
*/}}
|
||||
{{- define "redis-ha.name" -}}
|
||||
{{- default .Chart.Name .Values.nameOverride | trunc 63 | trimSuffix "-" -}}
|
||||
{{- end -}}
|
||||
|
||||
{{/*
|
||||
Create a default fully qualified app name.
|
||||
We truncate at 63 chars because some Kubernetes name fields are limited to this (by the DNS naming spec).
|
||||
*/}}
|
||||
{{- define "redis-ha.fullname" -}}
|
||||
{{- if .Values.fullnameOverride -}}
|
||||
{{- .Values.fullnameOverride | trunc 63 | trimSuffix "-" -}}
|
||||
{{- else -}}
|
||||
{{- $name := default .Chart.Name .Values.nameOverride -}}
|
||||
{{- if contains $name .Release.Name -}}
|
||||
{{- .Release.Name | trunc 63 | trimSuffix "-" -}}
|
||||
{{- else -}}
|
||||
{{- printf "%s-%s" .Release.Name $name | trunc 63 | trimSuffix "-" -}}
|
||||
{{- end -}}
|
||||
{{- end -}}
|
||||
{{- end -}}
|
||||
|
||||
|
||||
{{/*
|
||||
Return sysctl image
|
||||
*/}}
|
||||
{{- define "redis.sysctl.image" -}}
|
||||
{{- $registryName := default "docker.io" .Values.sysctlImage.registry -}}
|
||||
{{- $tag := default "latest" .Values.sysctlImage.tag | toString -}}
|
||||
{{- printf "%s/%s:%s" $registryName .Values.sysctlImage.repository $tag -}}
|
||||
{{- end -}}
|
||||
|
||||
{{- /*
|
||||
Credit: @technosophos
|
||||
https://github.com/technosophos/common-chart/
|
||||
labels.standard prints the standard Helm labels.
|
||||
The standard labels are frequently used in metadata.
|
||||
*/ -}}
|
||||
{{- define "labels.standard" -}}
|
||||
app: {{ template "redis-ha.name" . }}
|
||||
heritage: {{ .Release.Service | quote }}
|
||||
release: {{ .Release.Name | quote }}
|
||||
chart: {{ template "chartref" . }}
|
||||
{{- end -}}
|
||||
|
||||
{{- /*
|
||||
Credit: @technosophos
|
||||
https://github.com/technosophos/common-chart/
|
||||
chartref prints a chart name and version.
|
||||
It does minimal escaping for use in Kubernetes labels.
|
||||
Example output:
|
||||
zookeeper-1.2.3
|
||||
wordpress-3.2.1_20170219
|
||||
*/ -}}
|
||||
{{- define "chartref" -}}
|
||||
{{- replace "+" "_" .Chart.Version | printf "%s-%s" .Chart.Name -}}
|
||||
{{- end -}}
|
||||
|
||||
{{/*
|
||||
Create the name of the service account to use
|
||||
*/}}
|
||||
{{- define "redis-ha.serviceAccountName" -}}
|
||||
{{- if .Values.serviceAccount.create -}}
|
||||
{{ default (include "redis-ha.fullname" .) .Values.serviceAccount.name }}
|
||||
{{- else -}}
|
||||
{{ default "default" .Values.serviceAccount.name }}
|
||||
{{- end -}}
|
||||
{{- end -}}
|
||||
|
||||
{{- define "redis-ha.masterGroupName" -}}
|
||||
{{- $masterGroupName := tpl ( .Values.redis.masterGroupName | default "") . -}}
|
||||
{{- $validMasterGroupName := regexMatch "^[\\w-\\.]+$" $masterGroupName -}}
|
||||
{{- if $validMasterGroupName -}}
|
||||
{{ $masterGroupName }}
|
||||
{{- else -}}
|
||||
{{ required "A valid .Values.redis.masterGroupName entry is required (matching ^[\\w-\\.]+$)" ""}}
|
||||
{{- end -}}
|
||||
{{- end -}}
|
||||
|
||||
{{/*
|
||||
Return the appropriate apiVersion for poddisruptionbudget.
|
||||
*/}}
|
||||
{{- define "redis-ha.podDisruptionBudget.apiVersion" -}}
|
||||
{{- if .Capabilities.APIVersions.Has "policy/v1" }}
|
||||
{{- print "policy/v1" -}}
|
||||
{{- else -}}
|
||||
{{- print "policy/v1beta1" -}}
|
||||
{{- end -}}
|
||||
{{- end -}}
|
||||
|
||||
{{/*
|
||||
Return true if the detected platform is Openshift
|
||||
Usage:
|
||||
{{- include "common.compatibility.isOpenshift" . -}}
|
||||
*/}}
|
||||
{{- define "compatibility.isOpenshift" -}}
|
||||
{{- if .Capabilities.APIVersions.Has "security.openshift.io/v1" -}}
|
||||
{{- true -}}
|
||||
{{- end -}}
|
||||
{{- end -}}
|
||||
|
||||
{{/*
|
||||
Render a compatible securityContext depending on the platform. By default it is maintained as it is. In other platforms like Openshift we remove default user/group values that do not work out of the box with the restricted-v1 SCC
|
||||
Usage:
|
||||
{{- include "compatibility.renderSecurityContext" (dict "secContext" .Values.containerSecurityContext "context" $) -}}
|
||||
*/}}
|
||||
{{- define "compatibility.renderSecurityContext" -}}
|
||||
{{- $adaptedContext := .secContext -}}
|
||||
|
||||
{{- if (((.context.Values.global).compatibility).openshift) -}}
|
||||
{{- if or (eq .context.Values.global.compatibility.openshift.adaptSecurityContext "force") (and (eq .context.Values.global.compatibility.openshift.adaptSecurityContext "auto") (include "compatibility.isOpenshift" .context)) -}}
|
||||
{{/* Remove incompatible user/group values that do not work in Openshift out of the box */}}
|
||||
{{- $adaptedContext = omit $adaptedContext "fsGroup" "runAsUser" "runAsGroup" -}}
|
||||
{{- if not .secContext.seLinuxOptions -}}
|
||||
{{/* If it is an empty object, we remove it from the resulting context because it causes validation issues */}}
|
||||
{{- $adaptedContext = omit $adaptedContext "seLinuxOptions" -}}
|
||||
{{- end -}}
|
||||
{{- end -}}
|
||||
{{- end -}}
|
||||
{{/* Remove fields that are disregarded when running the container in privileged mode */}}
|
||||
{{- if $adaptedContext.privileged -}}
|
||||
{{- $adaptedContext = omit $adaptedContext "capabilities" "seLinuxOptions" -}}
|
||||
{{- end -}}
|
||||
{{- omit $adaptedContext "enabled" | toYaml -}}
|
||||
{{- end -}}
|
||||
@@ -0,0 +1,15 @@
|
||||
{{- if and .Values.auth (not .Values.existingSecret) -}}
|
||||
apiVersion: v1
|
||||
kind: Secret
|
||||
metadata:
|
||||
name: {{ template "redis-ha.fullname" . }}
|
||||
namespace: {{ .Release.Namespace | quote }}
|
||||
labels:
|
||||
{{ include "labels.standard" . | indent 4 }}
|
||||
{{- range $key, $value := .Values.extraLabels }}
|
||||
{{ $key }}: {{ $value | quote }}
|
||||
{{- end }}
|
||||
type: Opaque
|
||||
data:
|
||||
{{ .Values.authKey }}: {{ .Values.redisPassword | b64enc | quote }}
|
||||
{{- end -}}
|
||||
+64
@@ -0,0 +1,64 @@
|
||||
{{- $fullName := include "redis-ha.fullname" . }}
|
||||
{{- $namespace := .Release.Namespace -}}
|
||||
{{- $replicas := int (toString .Values.replicas) }}
|
||||
{{- $root := . }}
|
||||
{{- range $i := until $replicas }}
|
||||
---
|
||||
apiVersion: v1
|
||||
kind: Service
|
||||
metadata:
|
||||
name: {{ $fullName }}-announce-{{ $i }}
|
||||
namespace: {{ $namespace | quote}}
|
||||
labels:
|
||||
{{ include "labels.standard" $root | indent 4 }}
|
||||
{{- range $key, $value := $root.Values.extraLabels }}
|
||||
{{ $key }}: {{ $value | quote }}
|
||||
{{- end }}
|
||||
annotations:
|
||||
{{- if (semverCompare "<=1.10-0" $.Capabilities.KubeVersion.GitVersion) }}
|
||||
service.alpha.kubernetes.io/tolerate-unready-endpoints: "true"
|
||||
{{- end }}
|
||||
{{- if $root.Values.serviceAnnotations }}
|
||||
{{ toYaml $root.Values.serviceAnnotations | indent 4 }}
|
||||
{{- end }}
|
||||
spec:
|
||||
{{- if (semverCompare ">=1.11-0" $.Capabilities.KubeVersion.GitVersion) }}
|
||||
publishNotReadyAddresses: true
|
||||
{{- end }}
|
||||
type: ClusterIP
|
||||
ports:
|
||||
{{- if ne (int $root.Values.redis.port) 0 }}
|
||||
- name: tcp-server
|
||||
port: {{ $root.Values.redis.port }}
|
||||
protocol: TCP
|
||||
targetPort: redis
|
||||
{{- end }}
|
||||
{{- if $root.Values.redis.tlsPort }}
|
||||
- name: server-tls
|
||||
port: {{ $root.Values.redis.tlsPort }}
|
||||
protocol: TCP
|
||||
targetPort: redis-tls
|
||||
{{- end }}
|
||||
{{- if ne (int $root.Values.sentinel.port) 0 }}
|
||||
- name: tcp-sentinel
|
||||
port: {{ $root.Values.sentinel.port }}
|
||||
protocol: TCP
|
||||
targetPort: sentinel
|
||||
{{- end }}
|
||||
{{- if $root.Values.sentinel.tlsPort }}
|
||||
- name: sentinel-tls
|
||||
port: {{ $root.Values.sentinel.tlsPort }}
|
||||
protocol: TCP
|
||||
targetPort: sentinel-tls
|
||||
{{- end }}
|
||||
{{- if $root.Values.exporter.enabled }}
|
||||
- name: http-exporter
|
||||
port: {{ $root.Values.exporter.port }}
|
||||
protocol: TCP
|
||||
targetPort: {{ $root.Values.exporter.portName }}
|
||||
{{- end }}
|
||||
selector:
|
||||
release: {{ $root.Release.Name }}
|
||||
app: {{ include "redis-ha.name" $root }}
|
||||
"statefulset.kubernetes.io/pod-name": {{ $fullName }}-server-{{ $i }}
|
||||
{{- end }}
|
||||
@@ -0,0 +1,37 @@
|
||||
apiVersion: v1
|
||||
kind: ConfigMap
|
||||
metadata:
|
||||
name: {{ template "redis-ha.fullname" . }}-configmap
|
||||
namespace: {{ .Release.Namespace | quote }}
|
||||
labels:
|
||||
heritage: {{ .Release.Service }}
|
||||
release: {{ .Release.Name }}
|
||||
chart: {{ .Chart.Name }}-{{ .Chart.Version }}
|
||||
app: {{ template "redis-ha.fullname" . }}
|
||||
{{- range $key, $value := .Values.configmap.labels }}
|
||||
{{ $key }}: {{ $value | toString }}
|
||||
{{- end }}
|
||||
{{- range $key, $value := .Values.extraLabels }}
|
||||
{{ $key }}: {{ $value | quote }}
|
||||
{{- end }}
|
||||
data:
|
||||
redis.conf: |
|
||||
{{- include "config-redis.conf" . }}
|
||||
|
||||
sentinel.conf: |
|
||||
{{- include "config-sentinel.conf" . }}
|
||||
|
||||
init.sh: |
|
||||
{{- include "config-init.sh" . }}
|
||||
|
||||
fix-split-brain.sh: |
|
||||
{{- include "fix-split-brain.sh" . }}
|
||||
|
||||
{{ if .Values.haproxy.enabled }}
|
||||
haproxy.cfg: |
|
||||
{{- include "config-haproxy.cfg" . }}
|
||||
{{- end }}
|
||||
haproxy_init.sh: |
|
||||
{{- include "config-haproxy_init.sh" . }}
|
||||
trigger-failover-if-master.sh: |
|
||||
{{- include "trigger-failover-if-master.sh" . }}
|
||||
+14
@@ -0,0 +1,14 @@
|
||||
{{- if .Values.exporter.script }}
|
||||
apiVersion: v1
|
||||
kind: ConfigMap
|
||||
metadata:
|
||||
name: {{ template "redis-ha.fullname" . }}-exporter-script-configmap
|
||||
namespace: {{ .Release.Namespace | quote }}
|
||||
labels:
|
||||
{{ include "labels.standard" . | indent 4 }}
|
||||
{{- range $key, $value := .Values.extraLabels }}
|
||||
{{ $key }}: {{ $value | quote }}
|
||||
{{- end }}
|
||||
data:
|
||||
script: {{ toYaml .Values.exporter.script | indent 2 }}
|
||||
{{- end }}
|
||||
+20
@@ -0,0 +1,20 @@
|
||||
apiVersion: v1
|
||||
kind: ConfigMap
|
||||
metadata:
|
||||
name: {{ template "redis-ha.fullname" . }}-health-configmap
|
||||
namespace: {{ .Release.Namespace | quote }}
|
||||
labels:
|
||||
heritage: {{ .Release.Service }}
|
||||
release: {{ .Release.Name }}
|
||||
chart: {{ .Chart.Name }}-{{ .Chart.Version }}
|
||||
app: {{ template "redis-ha.fullname" . }}
|
||||
{{- range $key, $value := .Values.extraLabels }}
|
||||
{{ $key }}: {{ $value | quote }}
|
||||
{{- end }}
|
||||
data:
|
||||
redis_liveness.sh: |
|
||||
{{- include "redis_liveness.sh" . }}
|
||||
redis_readiness.sh: |
|
||||
{{- include "redis_readiness.sh" . }}
|
||||
sentinel_liveness.sh: |
|
||||
{{- include "sentinel_liveness.sh" . }}
|
||||
@@ -0,0 +1,80 @@
|
||||
{{- if .Values.networkPolicy.enabled }}
|
||||
{{- $root := . }}
|
||||
kind: NetworkPolicy
|
||||
apiVersion: networking.k8s.io/v1
|
||||
metadata:
|
||||
name: {{ template "redis-ha.fullname" . }}-network-policy
|
||||
namespace: {{ .Release.Namespace | quote }}
|
||||
{{- if .Values.networkPolicy.annotations }}
|
||||
annotations:
|
||||
{{- range $key, $value := .Values.networkPolicy.annotations }}
|
||||
{{ $key }}: {{ $value | quote }}
|
||||
{{- end }}
|
||||
{{- end }}
|
||||
labels:
|
||||
{{ include "labels.standard" . | indent 4 }}
|
||||
{{- range $key, $value := .Values.networkPolicy.labels }}
|
||||
{{ $key }}: {{ $value | quote }}
|
||||
{{- end }}
|
||||
spec:
|
||||
podSelector:
|
||||
matchLabels:
|
||||
release: {{ .Release.Name }}
|
||||
app: {{ template "redis-ha.name" . }}
|
||||
policyTypes:
|
||||
- Ingress
|
||||
- Egress
|
||||
egress:
|
||||
- to:
|
||||
- podSelector:
|
||||
matchLabels:
|
||||
release: {{ .Release.Name }}
|
||||
app: {{ template "redis-ha.name" . }}
|
||||
ports:
|
||||
- port: {{ .Values.redis.port }}
|
||||
protocol: TCP
|
||||
- port: {{ .Values.sentinel.port }}
|
||||
protocol: TCP
|
||||
{{- range $rule := .Values.networkPolicy.egressRules }}
|
||||
- to:
|
||||
{{ (tpl (toYaml $rule.selectors) $) | indent 7 }}
|
||||
ports:
|
||||
{{ toYaml $rule.ports | indent 7 }}
|
||||
{{- end }}
|
||||
ingress:
|
||||
- from:
|
||||
- podSelector:
|
||||
matchLabels:
|
||||
release: {{ .Release.Name }}
|
||||
app: {{ template "redis-ha.name" . }}
|
||||
ports:
|
||||
- port: {{ .Values.redis.port }}
|
||||
protocol: TCP
|
||||
- port: {{ .Values.sentinel.port }}
|
||||
protocol: TCP
|
||||
{{- if .Values.haproxy.enabled }}
|
||||
- from:
|
||||
- podSelector:
|
||||
matchLabels:
|
||||
release: {{ .Release.Name }}
|
||||
app: {{ template "redis-ha.name" . }}-haproxy
|
||||
ports:
|
||||
- port: {{ .Values.redis.port }}
|
||||
protocol: TCP
|
||||
- port: {{ .Values.sentinel.port }}
|
||||
protocol: TCP
|
||||
{{- end }}
|
||||
{{- range $rule := .Values.networkPolicy.ingressRules }}
|
||||
- from:
|
||||
{{ (tpl (toYaml $rule.selectors) $) | indent 7 }}
|
||||
ports:
|
||||
{{- if $rule.ports }}
|
||||
{{ toYaml $rule.ports | indent 7 }}
|
||||
{{- else }}
|
||||
- port: {{ $root.Values.redis.port }}
|
||||
protocol: TCP
|
||||
- port: {{ $root.Values.sentinel.port }}
|
||||
protocol: TCP
|
||||
{{- end }}
|
||||
{{- end }}
|
||||
{{- end }}
|
||||
@@ -0,0 +1,21 @@
|
||||
{{- if .Values.podDisruptionBudget -}}
|
||||
apiVersion: {{ template "redis-ha.podDisruptionBudget.apiVersion" . }}
|
||||
kind: PodDisruptionBudget
|
||||
metadata:
|
||||
name: {{ template "redis-ha.fullname" . }}-pdb
|
||||
namespace: {{ .Release.Namespace | quote }}
|
||||
labels:
|
||||
{{ include "labels.standard" . | indent 4 }}
|
||||
{{- range $key, $value := .Values.extraLabels }}
|
||||
{{ $key }}: {{ $value | quote }}
|
||||
{{- end }}
|
||||
spec:
|
||||
selector:
|
||||
matchLabels:
|
||||
# The replica label is set on StatefulSet pods but not the Test pods
|
||||
# We want to avoid including the Test pods in the budget
|
||||
{{ template "redis-ha.fullname" . }}: replica
|
||||
release: {{ .Release.Name }}
|
||||
app: {{ template "redis-ha.name" . }}
|
||||
{{ toYaml .Values.podDisruptionBudget | indent 2 }}
|
||||
{{- end -}}
|
||||
@@ -0,0 +1,17 @@
|
||||
{{- if .Values.prometheusRule.enabled }}
|
||||
apiVersion: monitoring.coreos.com/v1
|
||||
kind: PrometheusRule
|
||||
metadata:
|
||||
name: {{ template "redis-ha.fullname" . }}
|
||||
{{- if .Values.prometheusRule.namespace }}
|
||||
namespace: {{ .Values.prometheusRule.namespace }}
|
||||
{{- end }}
|
||||
labels: {{- toYaml .Values.prometheusRule.additionalLabels | nindent 4 }}
|
||||
spec:
|
||||
groups:
|
||||
- name: {{ template "redis-ha.fullname" . }}
|
||||
{{- if .Values.prometheusRule.interval }}
|
||||
interval: {{ .Values.prometheusRule.interval }}
|
||||
{{- end }}
|
||||
rules: {{- tpl (toYaml .Values.prometheusRule.rules) . | nindent 8 }}
|
||||
{{- end }}
|
||||
@@ -0,0 +1,19 @@
|
||||
{{- if and .Values.serviceAccount.create .Values.rbac.create }}
|
||||
apiVersion: rbac.authorization.k8s.io/v1
|
||||
kind: Role
|
||||
metadata:
|
||||
name: {{ template "redis-ha.fullname" . }}
|
||||
namespace: {{ .Release.Namespace | quote }}
|
||||
labels:
|
||||
{{ include "labels.standard" . | indent 4 }}
|
||||
{{- range $key, $value := .Values.extraLabels }}
|
||||
{{ $key }}: {{ $value | quote }}
|
||||
{{- end }}
|
||||
rules:
|
||||
- apiGroups:
|
||||
- ""
|
||||
resources:
|
||||
- endpoints
|
||||
verbs:
|
||||
- get
|
||||
{{- end }}
|
||||
@@ -0,0 +1,19 @@
|
||||
{{- if and .Values.serviceAccount.create .Values.rbac.create }}
|
||||
apiVersion: rbac.authorization.k8s.io/v1
|
||||
kind: RoleBinding
|
||||
metadata:
|
||||
name: {{ template "redis-ha.fullname" . }}
|
||||
namespace: {{ .Release.Namespace | quote }}
|
||||
labels:
|
||||
{{ include "labels.standard" . | indent 4 }}
|
||||
{{- range $key, $value := .Values.extraLabels }}
|
||||
{{ $key }}: {{ $value | quote }}
|
||||
{{- end }}
|
||||
subjects:
|
||||
- kind: ServiceAccount
|
||||
name: {{ template "redis-ha.serviceAccountName" . }}
|
||||
roleRef:
|
||||
apiGroup: rbac.authorization.k8s.io
|
||||
kind: Role
|
||||
name: {{ template "redis-ha.fullname" . }}
|
||||
{{- end }}
|
||||
@@ -0,0 +1,32 @@
|
||||
{{- if not .Values.restore.existingSecret }}
|
||||
|
||||
|
||||
{{- $regexRestoreS3 := "^s3://.+|^S3://.+" -}}
|
||||
{{- $regexRestoreSSH := "^.+@.+:.+" -}}
|
||||
|
||||
{{- if or (regexFind $regexRestoreSSH (toString .Values.restore.ssh.source)) (regexFind $regexRestoreS3 (toString .Values.restore.s3.source)) }}
|
||||
apiVersion: v1
|
||||
kind: Secret
|
||||
metadata:
|
||||
name: {{ include "redis-ha.fullname" . }}-secret
|
||||
namespace: {{ .Release.Namespace | quote }}
|
||||
labels:
|
||||
heritage: {{ .Release.Service }}
|
||||
release: {{ .Release.Name }}
|
||||
chart: {{ .Chart.Name }}-{{ .Chart.Version }}
|
||||
app: {{ template "redis-ha.fullname" . }}
|
||||
{{- range $key, $value := .Values.extraLabels }}
|
||||
{{ $key }}: {{ $value | quote }}
|
||||
{{- end }}
|
||||
type: Opaque
|
||||
data:
|
||||
{{- if regexFind $regexRestoreSSH (toString .Values.restore.ssh.source) }}
|
||||
SSH_KEY: "{{ .Values.restore.ssh.key | b64enc }}"
|
||||
{{- end }}
|
||||
{{- if regexFind $regexRestoreS3 (toString .Values.restore.s3.source) }}
|
||||
AWS_SECRET_ACCESS_KEY: "{{ .Values.restore.s3.secret_key | b64enc }}"
|
||||
AWS_ACCESS_KEY_ID: "{{ .Values.restore.s3.access_key | b64enc }}"
|
||||
{{- end }}
|
||||
{{- end }}
|
||||
|
||||
{{- end }}
|
||||
@@ -0,0 +1,57 @@
|
||||
apiVersion: v1
|
||||
kind: Service
|
||||
metadata:
|
||||
name: {{ template "redis-ha.fullname" . }}
|
||||
namespace: {{ .Release.Namespace | quote }}
|
||||
labels:
|
||||
{{ include "labels.standard" . | indent 4 }}
|
||||
{{- if .Values.exporter.enabled }}
|
||||
exporter: enabled
|
||||
{{- end }}
|
||||
{{- range $key, $value := .Values.extraLabels }}
|
||||
{{ $key }}: {{ $value | quote }}
|
||||
{{- end }}
|
||||
{{- range $key, $value := .Values.serviceLabels }}
|
||||
{{ $key }}: {{ $value | quote }}
|
||||
{{- end }}
|
||||
annotations:
|
||||
{{- if .Values.serviceAnnotations }}
|
||||
{{ toYaml .Values.serviceAnnotations | indent 4 }}
|
||||
{{- end }}
|
||||
spec:
|
||||
type: ClusterIP
|
||||
clusterIP: None
|
||||
ports:
|
||||
{{- if ne (int .Values.redis.port) 0 }}
|
||||
- name: tcp-server
|
||||
port: {{ .Values.redis.port }}
|
||||
protocol: TCP
|
||||
targetPort: redis
|
||||
{{- end }}
|
||||
{{- if .Values.redis.tlsPort }}
|
||||
- name: server-tls
|
||||
port: {{ .Values.redis.tlsPort }}
|
||||
protocol: TCP
|
||||
targetPort: redis-tls
|
||||
{{- end }}
|
||||
{{- if ne (int .Values.sentinel.port) 0 }}
|
||||
- name: tcp-sentinel
|
||||
port: {{ .Values.sentinel.port }}
|
||||
protocol: TCP
|
||||
targetPort: sentinel
|
||||
{{- end }}
|
||||
{{- if .Values.sentinel.tlsPort }}
|
||||
- name: sentinel-tls
|
||||
port: {{ .Values.sentinel.tlsPort }}
|
||||
protocol: TCP
|
||||
targetPort: sentinel-tls
|
||||
{{- end }}
|
||||
{{- if .Values.exporter.enabled }}
|
||||
- name: http-exporter-port
|
||||
port: {{ .Values.exporter.port }}
|
||||
protocol: TCP
|
||||
targetPort: {{ .Values.exporter.portName }}
|
||||
{{- end }}
|
||||
selector:
|
||||
release: {{ .Release.Name }}
|
||||
app: {{ template "redis-ha.name" . }}
|
||||
@@ -0,0 +1,31 @@
|
||||
{{- if .Values.serviceAccount.create }}
|
||||
apiVersion: v1
|
||||
kind: ServiceAccount
|
||||
metadata:
|
||||
name: {{ template "redis-ha.serviceAccountName" . }}
|
||||
namespace: {{ .Release.Namespace | quote }}
|
||||
labels:
|
||||
heritage: {{ .Release.Service }}
|
||||
release: {{ .Release.Name }}
|
||||
chart: {{ .Chart.Name }}-{{ .Chart.Version }}
|
||||
app: {{ template "redis-ha.fullname" . }}
|
||||
{{- range $key, $value := .Values.extraLabels }}
|
||||
{{ $key }}: {{ $value | quote }}
|
||||
{{- end }}
|
||||
{{- if .Values.serviceAccount.annotations }}
|
||||
annotations:
|
||||
{{ toYaml .Values.serviceAccount.annotations | indent 4 }}
|
||||
{{- end }}
|
||||
{{- if or .Values.auth .Values.sentinel.auth }}
|
||||
secrets:
|
||||
{{- end }}
|
||||
{{- if .Values.auth }}
|
||||
- name: {{ default (include "redis-ha.fullname" .) .Values.existingSecret }}
|
||||
{{- end }}
|
||||
{{- if .Values.sentinel.auth }}
|
||||
- name: {{ default (printf "%s-sentinel" (include "redis-ha.fullname" .)) .Values.sentinel.existingSecret }}
|
||||
{{- end }}
|
||||
{{- if .Values.imagePullSecrets }}
|
||||
imagePullSecrets: {{ toYaml .Values.imagePullSecrets | nindent 0 }}
|
||||
{{- end }}
|
||||
{{- end }}
|
||||
@@ -0,0 +1,39 @@
|
||||
{{- if and ( or .Values.exporter.serviceMonitor.disableAPICheck ( .Capabilities.APIVersions.Has "monitoring.coreos.com/v1" ) ) ( .Values.exporter.serviceMonitor.enabled ) ( .Values.exporter.enabled ) }}
|
||||
apiVersion: monitoring.coreos.com/v1
|
||||
kind: ServiceMonitor
|
||||
metadata:
|
||||
name: {{ template "redis-ha.fullname" . }}
|
||||
namespace: {{ .Values.exporter.serviceMonitor.namespace | default .Release.Namespace | quote }}
|
||||
labels:
|
||||
{{ include "labels.standard" . | indent 4 }}
|
||||
{{- range $key, $value := .Values.extraLabels }}
|
||||
{{ $key }}: {{ $value | quote }}
|
||||
{{- end }}
|
||||
{{- range $key, $value := .Values.exporter.serviceMonitor.labels }}
|
||||
{{ $key }}: {{ $value | quote }}
|
||||
{{- end }}
|
||||
spec:
|
||||
endpoints:
|
||||
- targetPort: {{ .Values.exporter.port }}
|
||||
{{- if .Values.exporter.serviceMonitor.interval }}
|
||||
interval: {{ .Values.exporter.serviceMonitor.interval }}
|
||||
{{- end }}
|
||||
{{- if .Values.exporter.serviceMonitor.telemetryPath }}
|
||||
path: {{ .Values.exporter.serviceMonitor.telemetryPath }}
|
||||
{{- end }}
|
||||
{{- if .Values.exporter.serviceMonitor.timeout }}
|
||||
scrapeTimeout: {{ .Values.exporter.serviceMonitor.timeout }}
|
||||
{{- end }}
|
||||
{{- with .Values.exporter.serviceMonitor.endpointAdditionalProperties }}
|
||||
{{- toYaml . | nindent 4 }}
|
||||
{{- end }}
|
||||
jobLabel: {{ template "redis-ha.fullname" . }}
|
||||
namespaceSelector:
|
||||
matchNames:
|
||||
- {{ .Release.Namespace | quote }}
|
||||
selector:
|
||||
matchLabels:
|
||||
app: {{ template "redis-ha.name" . }}
|
||||
release: {{ .Release.Name }}
|
||||
exporter: enabled
|
||||
{{- end }}
|
||||
@@ -0,0 +1,639 @@
|
||||
{{- $regexRestoreS3 := "^s3://.+|^S3://.+" -}}
|
||||
{{- $regexRestoreSSH := "^.+@.+:.+" -}}
|
||||
|
||||
apiVersion: apps/v1
|
||||
kind: StatefulSet
|
||||
metadata:
|
||||
name: {{ template "redis-ha.fullname" . }}-server
|
||||
namespace: {{ .Release.Namespace | quote }}
|
||||
labels:
|
||||
{{ template "redis-ha.fullname" . }}: replica
|
||||
{{- range $key, $value := .Values.extraLabels }}
|
||||
{{ $key }}: {{ $value | quote }}
|
||||
{{- end }}
|
||||
{{ include "labels.standard" . | indent 4 }}
|
||||
annotations:
|
||||
{{ toYaml .Values.redis.annotations | indent 4 }}
|
||||
spec:
|
||||
selector:
|
||||
matchLabels:
|
||||
release: {{ .Release.Name }}
|
||||
app: {{ template "redis-ha.name" . }}
|
||||
serviceName: {{ template "redis-ha.fullname" . }}
|
||||
replicas: {{ .Values.replicas }}
|
||||
podManagementPolicy: {{ .Values.podManagementPolicy }}
|
||||
updateStrategy:
|
||||
type: {{ .Values.redis.updateStrategy.type }}
|
||||
{{- if .Values.redis.minReadySeconds }}
|
||||
minReadySeconds: {{ .Values.redis.minReadySeconds }}
|
||||
{{- end }}
|
||||
template:
|
||||
metadata:
|
||||
annotations:
|
||||
checksum/init-config: {{ print (include "config-redis.conf" .) (include "config-sentinel.conf" .) (include "config-init.sh" .) (include "fix-split-brain.sh" .) (include "redis_liveness.sh" .) (include "redis_readiness.sh" .) (include "sentinel_liveness.sh" .) (include "trigger-failover-if-master.sh" .)| sha256sum }}
|
||||
{{- if .Values.podAnnotations }}
|
||||
{{ toYaml .Values.podAnnotations | indent 8 }}
|
||||
{{- end }}
|
||||
{{- if and (.Values.exporter.enabled) (not .Values.exporter.serviceMonitor.enabled) }}
|
||||
prometheus.io/port: "{{ .Values.exporter.port }}"
|
||||
prometheus.io/scrape: "true"
|
||||
prometheus.io/path: {{ .Values.exporter.scrapePath }}
|
||||
{{- end }}
|
||||
labels:
|
||||
release: {{ .Release.Name }}
|
||||
app: {{ template "redis-ha.name" . }}
|
||||
{{ template "redis-ha.fullname" . }}: replica
|
||||
{{- range $key, $value := .Values.labels }}
|
||||
{{ $key }}: {{ $value | toString }}
|
||||
{{- end }}
|
||||
{{- range $key, $value := .Values.extraLabels }}
|
||||
{{ $key }}: {{ $value | quote }}
|
||||
{{- end }}
|
||||
spec:
|
||||
{{- if .Values.redis.terminationGracePeriodSeconds }}
|
||||
terminationGracePeriodSeconds: {{ .Values.redis.terminationGracePeriodSeconds }}
|
||||
{{- end }}
|
||||
{{- if .Values.schedulerName }}
|
||||
schedulerName: "{{ .Values.schedulerName }}"
|
||||
{{- end }}
|
||||
{{- if .Values.nodeSelector }}
|
||||
nodeSelector:
|
||||
{{ toYaml .Values.nodeSelector | indent 8 }}
|
||||
{{- end }}
|
||||
{{- if .Values.tolerations }}
|
||||
tolerations:
|
||||
{{ toYaml .Values.tolerations | indent 8 }}
|
||||
{{- end }}
|
||||
affinity:
|
||||
{{- if .Values.affinity }}
|
||||
{{- with .Values.affinity }}
|
||||
{{ tpl . $ | indent 8 }}
|
||||
{{- end }}
|
||||
{{- else }}
|
||||
{{- if .Values.additionalAffinities }}
|
||||
{{ toYaml .Values.additionalAffinities | indent 8 }}
|
||||
{{- end }}
|
||||
podAntiAffinity:
|
||||
{{- if .Values.hardAntiAffinity }}
|
||||
requiredDuringSchedulingIgnoredDuringExecution:
|
||||
- labelSelector:
|
||||
matchLabels:
|
||||
app: {{ template "redis-ha.name" . }}
|
||||
release: {{ .Release.Name }}
|
||||
{{ template "redis-ha.fullname" . }}: replica
|
||||
topologyKey: kubernetes.io/hostname
|
||||
{{- else }}
|
||||
preferredDuringSchedulingIgnoredDuringExecution:
|
||||
- weight: 100
|
||||
podAffinityTerm:
|
||||
labelSelector:
|
||||
matchLabels:
|
||||
app: {{ template "redis-ha.name" . }}
|
||||
release: {{ .Release.Name }}
|
||||
{{ template "redis-ha.fullname" . }}: replica
|
||||
topologyKey: kubernetes.io/hostname
|
||||
{{- end }}
|
||||
{{- end }}
|
||||
{{- if .Values.topologySpreadConstraints.enabled }}
|
||||
topologySpreadConstraints:
|
||||
- maxSkew: {{ .Values.topologySpreadConstraints.maxSkew | default 1 }}
|
||||
topologyKey: {{ .Values.topologySpreadConstraints.topologyKey | default "topology.kubernetes.io/zone" }}
|
||||
whenUnsatisfiable: {{ .Values.topologySpreadConstraints.whenUnsatisfiable | default "ScheduleAnyway" }}
|
||||
labelSelector:
|
||||
matchLabels:
|
||||
app: {{ template "redis-ha.name" . }}
|
||||
release: {{ .Release.Name }}
|
||||
{{ template "redis-ha.fullname" . }}: replica
|
||||
{{- end }}
|
||||
{{- if .Values.imagePullSecrets }}
|
||||
imagePullSecrets: {{ toYaml .Values.imagePullSecrets | nindent 8 }}
|
||||
{{- end }}
|
||||
securityContext: {{- include "compatibility.renderSecurityContext" (dict "secContext" .Values.securityContext "context" $) | nindent 8 }}
|
||||
serviceAccountName: {{ template "redis-ha.serviceAccountName" . }}
|
||||
automountServiceAccountToken: {{ .Values.serviceAccount.automountToken }}
|
||||
initContainers:
|
||||
{{- if .Values.sysctlImage.enabled }}
|
||||
- name: init-sysctl
|
||||
image: {{ template "redis.sysctl.image" . }}
|
||||
imagePullPolicy: {{ .Values.sysctlImage.pullPolicy }}
|
||||
resources: {{ toYaml .Values.sysctlImage.resources | nindent 10 }}
|
||||
{{- if .Values.sysctlImage.mountHostSys }}
|
||||
volumeMounts:
|
||||
- name: host-sys
|
||||
mountPath: /host-sys
|
||||
{{- end }}
|
||||
command: {{ toYaml .Values.sysctlImage.command | nindent 10 }}
|
||||
securityContext: {{- include "compatibility.renderSecurityContext" (dict "secContext" .Values.containerSecurityContext "context" $) | nindent 10 }}
|
||||
{{- end }}
|
||||
{{- if and .Values.hostPath.path .Values.hostPath.chown }}
|
||||
- name: hostpath-chown
|
||||
image: {{ .Values.image.repository }}:{{ .Values.image.tag }}
|
||||
securityContext: {{- include "compatibility.renderSecurityContext" (dict "secContext" .Values.containerSecurityContext "context" $) | nindent 10 }}
|
||||
command:
|
||||
- chown
|
||||
- "{{ .Values.containerSecurityContext.runAsUser }}"
|
||||
- /data
|
||||
volumeMounts:
|
||||
- name: data
|
||||
mountPath: /data
|
||||
{{- end }}
|
||||
- name: config-init
|
||||
image: {{ .Values.image.repository }}:{{ .Values.image.tag }}
|
||||
imagePullPolicy: {{ .Values.image.pullPolicy }}
|
||||
resources:
|
||||
{{ toYaml .Values.init.resources | indent 10 }}
|
||||
command:
|
||||
- sh
|
||||
args:
|
||||
- /readonly-config/init.sh
|
||||
securityContext: {{- include "compatibility.renderSecurityContext" (dict "secContext" .Values.containerSecurityContext "context" $) | nindent 10 }}
|
||||
env:
|
||||
{{- $replicas := int (toString .Values.replicas) -}}
|
||||
{{- range $i := until $replicas }}
|
||||
- name: SENTINEL_ID_{{ $i }}
|
||||
value: {{ printf "%s\n%s\nindex: %d" (include "redis-ha.name" $) ($.Release.Name) $i | sha256sum | trunc 40 }}
|
||||
{{- end }}
|
||||
{{- if .Values.auth }}
|
||||
- name: AUTH
|
||||
valueFrom:
|
||||
secretKeyRef:
|
||||
{{- if .Values.existingSecret }}
|
||||
name: {{ .Values.existingSecret }}
|
||||
{{- else }}
|
||||
name: {{ template "redis-ha.fullname" . }}
|
||||
{{- end }}
|
||||
key: {{ .Values.authKey }}
|
||||
{{- end }}
|
||||
{{- if .Values.sentinel.auth }}
|
||||
- name: SENTINELAUTH
|
||||
valueFrom:
|
||||
secretKeyRef:
|
||||
{{- if .Values.sentinel.existingSecret }}
|
||||
name: {{ .Values.sentinel.existingSecret }}
|
||||
{{- else }}
|
||||
name: {{ template "redis-ha.fullname" . }}-sentinel
|
||||
{{- end }}
|
||||
key: {{ .Values.sentinel.authKey }}
|
||||
{{- end }}
|
||||
volumeMounts:
|
||||
- name: config
|
||||
mountPath: /readonly-config
|
||||
readOnly: true
|
||||
- name: data
|
||||
mountPath: /data
|
||||
{{- if .Values.redis.tlsPort }}
|
||||
- mountPath: /tls-certs
|
||||
name: tls-certs
|
||||
{{- end}}
|
||||
{{ if regexFind $regexRestoreS3 (toString .Values.restore.s3.source) }}
|
||||
- name: restore-s3
|
||||
image: s3cmd/s3cmd:latest
|
||||
imagePullPolicy: {{ .Values.image.pullPolicy }}
|
||||
resources:
|
||||
{{ toYaml .Values.init.resources | indent 10 }}
|
||||
command:
|
||||
- sh
|
||||
args:
|
||||
- "-c"
|
||||
- "timeout -t {{ .Values.restore.timeout }} \
|
||||
s3cmd get {{ if .Values.restore.s3.region }}--region {{ .Values.restore.s3.region }} {{ end }}--force '{{ .Values.restore.s3.source }}' /data/dump.rdb_ \
|
||||
&& test -s /data/dump.rdb_ \
|
||||
&& if test -s /data/dump.rdb; \
|
||||
then cp -v /data/dump.rdb /data/dump.rdb_orig; fi \
|
||||
&& mv -v /data/dump.rdb_ /data/dump.rdb"
|
||||
envFrom:
|
||||
- secretRef:
|
||||
{{- if .Values.restore.existingSecret }}
|
||||
name: {{ .Values.existingSecret }}
|
||||
{{- else }}
|
||||
name: {{ include "redis-ha.fullname" . }}-secret
|
||||
{{- end }}
|
||||
volumeMounts:
|
||||
- name: data
|
||||
mountPath: /data
|
||||
{{- end }}
|
||||
{{ if regexFind $regexRestoreSSH (toString .Values.restore.ssh.source) }}
|
||||
- name: restore-ssh
|
||||
image: lgatica/openssh-client:latest
|
||||
imagePullPolicy: {{ .Values.image.pullPolicy }}
|
||||
resources:
|
||||
{{ toYaml .Values.init.resources | indent 10 }}
|
||||
command:
|
||||
- sh
|
||||
args:
|
||||
- "-c"
|
||||
- "rm -f key && echo -e \"${SSH_KEY}\" >key \
|
||||
&& chmod 400 key \
|
||||
&& timeout {{ .Values.restore.timeout }} \
|
||||
scp -i key \
|
||||
-o StrictHostKeyChecking=no \
|
||||
-o UserKnownHostsFile=/dev/null \
|
||||
'{{ .Values.restore.ssh.source }}' \
|
||||
/data/dump.rdb_ \
|
||||
&& test -s /data/dump.rdb_ \
|
||||
&& if test -s /data/dump.rdb; \
|
||||
then cp -v /data/dump.rdb /data/dump.rdb_orig; fi \
|
||||
&& mv -v /data/dump.rdb_ /data/dump.rdb"
|
||||
securityContext: {{- include "compatibility.renderSecurityContext" (dict "secContext" .Values.containerSecurityContext "context" $) | nindent 10 }}
|
||||
envFrom:
|
||||
- secretRef:
|
||||
{{- if .Values.restore.existingSecret }}
|
||||
name: {{ .Values.existingSecret }}
|
||||
{{- else }}
|
||||
name: {{ include "redis-ha.fullname" . }}-secret
|
||||
{{- end }}
|
||||
volumeMounts:
|
||||
- name: data
|
||||
mountPath: /data
|
||||
{{- end }}
|
||||
{{- if .Values.extraInitContainers }}
|
||||
{{- toYaml .Values.extraInitContainers | nindent 6 }}
|
||||
{{- end }}
|
||||
containers:
|
||||
- name: redis
|
||||
image: {{ .Values.image.repository }}:{{ .Values.image.tag }}
|
||||
imagePullPolicy: {{ .Values.image.pullPolicy }}
|
||||
command:
|
||||
{{- if .Values.redis.customCommand }}
|
||||
{{ toYaml .Values.redis.customCommand | indent 10 }}
|
||||
{{- else }}
|
||||
- redis-server
|
||||
{{- end }}
|
||||
args:
|
||||
{{- if .Values.redis.customArgs }}
|
||||
{{ toYaml .Values.redis.customArgs | indent 10 }}
|
||||
{{- else }}
|
||||
- /data/conf/redis.conf
|
||||
{{- end }}
|
||||
securityContext: {{- include "compatibility.renderSecurityContext" (dict "secContext" .Values.containerSecurityContext "context" $) | nindent 10 }}
|
||||
{{- if .Values.auth }}
|
||||
env:
|
||||
- name: AUTH
|
||||
valueFrom:
|
||||
secretKeyRef:
|
||||
{{- if .Values.existingSecret }}
|
||||
name: {{ .Values.existingSecret }}
|
||||
{{- else }}
|
||||
name: {{ template "redis-ha.fullname" . }}
|
||||
{{- end }}
|
||||
key: {{ .Values.authKey }}
|
||||
{{- end }}
|
||||
{{- if .Values.redis.envFrom }}
|
||||
envFrom:
|
||||
{{ toYaml .Values.redis.envFrom | indent 10 }}
|
||||
{{- end }}
|
||||
{{- if .Values.redis.livenessProbe.enabled }}
|
||||
livenessProbe:
|
||||
initialDelaySeconds: {{ .Values.redis.livenessProbe.initialDelaySeconds }}
|
||||
periodSeconds: {{ .Values.redis.livenessProbe.periodSeconds }}
|
||||
timeoutSeconds: {{ .Values.redis.livenessProbe.timeoutSeconds }}
|
||||
successThreshold: {{ .Values.redis.livenessProbe.successThreshold }}
|
||||
failureThreshold: {{ .Values.redis.livenessProbe.failureThreshold }}
|
||||
exec:
|
||||
command:
|
||||
- sh
|
||||
- -c
|
||||
- /health/redis_liveness.sh
|
||||
{{- end }}
|
||||
{{- if .Values.redis.readinessProbe.enabled }}
|
||||
readinessProbe:
|
||||
initialDelaySeconds: {{ .Values.redis.readinessProbe.initialDelaySeconds }}
|
||||
periodSeconds: {{ .Values.redis.readinessProbe.periodSeconds }}
|
||||
timeoutSeconds: {{ .Values.redis.readinessProbe.timeoutSeconds }}
|
||||
successThreshold: {{ .Values.redis.readinessProbe.successThreshold }}
|
||||
failureThreshold: {{ .Values.redis.readinessProbe.failureThreshold }}
|
||||
exec:
|
||||
command:
|
||||
- sh
|
||||
- -c
|
||||
- /health/redis_readiness.sh
|
||||
{{- end }}
|
||||
{{- if .Values.redis.startupProbe.enabled }}
|
||||
startupProbe:
|
||||
initialDelaySeconds: {{ .Values.redis.startupProbe.initialDelaySeconds }}
|
||||
periodSeconds: {{ .Values.redis.startupProbe.periodSeconds }}
|
||||
timeoutSeconds: {{ .Values.redis.startupProbe.timeoutSeconds }}
|
||||
successThreshold: {{ .Values.redis.startupProbe.successThreshold }}
|
||||
failureThreshold: {{ .Values.redis.startupProbe.failureThreshold }}
|
||||
exec:
|
||||
command:
|
||||
- sh
|
||||
- -c
|
||||
- /health/redis_readiness.sh
|
||||
{{- end }}
|
||||
resources:
|
||||
{{ toYaml .Values.redis.resources | indent 10 }}
|
||||
ports:
|
||||
{{- if ne (int .Values.redis.port) 0 }}
|
||||
- name: redis
|
||||
containerPort: {{ .Values.redis.port }}
|
||||
{{- end }}
|
||||
{{- if .Values.redis.tlsPort }}
|
||||
- name: redis-tls
|
||||
containerPort: {{ .Values.redis.tlsPort }}
|
||||
{{- end }}
|
||||
volumeMounts:
|
||||
- name: config
|
||||
mountPath: /readonly-config
|
||||
readOnly: true
|
||||
- mountPath: /data
|
||||
name: data
|
||||
{{- if .Values.redis.tlsPort }}
|
||||
- mountPath: /tls-certs
|
||||
name: tls-certs
|
||||
{{- end}}
|
||||
- mountPath: /health
|
||||
name: health
|
||||
{{- if .Values.redis.extraVolumeMounts }}
|
||||
{{- toYaml .Values.redis.extraVolumeMounts | nindent 8 }}
|
||||
{{- end }}
|
||||
lifecycle:
|
||||
{{ toYaml .Values.redis.lifecycle | indent 10 }}
|
||||
- name: sentinel
|
||||
image: {{ .Values.image.repository }}:{{ .Values.image.tag }}
|
||||
imagePullPolicy: {{ .Values.image.pullPolicy }}
|
||||
command:
|
||||
{{- if .Values.sentinel.customCommand }}
|
||||
{{ toYaml .Values.sentinel.customCommand | indent 10 }}
|
||||
{{- else }}
|
||||
- redis-sentinel
|
||||
{{- end }}
|
||||
args:
|
||||
{{- if .Values.sentinel.customArgs }}
|
||||
{{ toYaml .Values.sentinel.customArgs | indent 10 }}
|
||||
{{- else }}
|
||||
- /data/conf/sentinel.conf
|
||||
{{- end }}
|
||||
securityContext: {{- include "compatibility.renderSecurityContext" (dict "secContext" .Values.containerSecurityContext "context" $) | nindent 10 }}
|
||||
{{- if or .Values.auth .Values.sentinel.auth}}
|
||||
env:
|
||||
{{- if .Values.auth }}
|
||||
- name: AUTH
|
||||
valueFrom:
|
||||
secretKeyRef:
|
||||
{{- if .Values.existingSecret }}
|
||||
name: {{ .Values.existingSecret }}
|
||||
{{- else }}
|
||||
name: {{ template "redis-ha.fullname" . }}
|
||||
{{- end }}
|
||||
key: {{ .Values.authKey }}
|
||||
{{- end }}
|
||||
{{- if .Values.sentinel.auth }}
|
||||
- name: SENTINELAUTH
|
||||
valueFrom:
|
||||
secretKeyRef:
|
||||
{{- if .Values.sentinel.existingSecret }}
|
||||
name: {{ .Values.sentinel.existingSecret }}
|
||||
{{- else }}
|
||||
name: {{ template "redis-ha.fullname" . }}-sentinel
|
||||
{{- end }}
|
||||
key: {{ .Values.sentinel.authKey }}
|
||||
{{- end }}
|
||||
{{- end }}
|
||||
{{- if .Values.sentinel.livenessProbe.enabled }}
|
||||
livenessProbe:
|
||||
initialDelaySeconds: {{ .Values.sentinel.livenessProbe.initialDelaySeconds }}
|
||||
periodSeconds: {{ .Values.sentinel.livenessProbe.periodSeconds }}
|
||||
timeoutSeconds: {{ .Values.sentinel.livenessProbe.timeoutSeconds }}
|
||||
successThreshold: {{ .Values.sentinel.livenessProbe.successThreshold }}
|
||||
failureThreshold: {{ .Values.sentinel.livenessProbe.failureThreshold }}
|
||||
exec:
|
||||
command:
|
||||
- sh
|
||||
- -c
|
||||
- /health/sentinel_liveness.sh
|
||||
{{- end }}
|
||||
{{- if .Values.sentinel.readinessProbe.enabled }}
|
||||
readinessProbe:
|
||||
initialDelaySeconds: {{ .Values.sentinel.readinessProbe.initialDelaySeconds }}
|
||||
periodSeconds: {{ .Values.sentinel.readinessProbe.periodSeconds }}
|
||||
timeoutSeconds: {{ .Values.sentinel.readinessProbe.timeoutSeconds }}
|
||||
successThreshold: {{ .Values.sentinel.readinessProbe.successThreshold }}
|
||||
failureThreshold: {{ .Values.sentinel.readinessProbe.failureThreshold }}
|
||||
exec:
|
||||
command:
|
||||
- sh
|
||||
- -c
|
||||
- /health/sentinel_liveness.sh
|
||||
{{- end }}
|
||||
{{- if .Values.sentinel.startupProbe.enabled }}
|
||||
startupProbe:
|
||||
initialDelaySeconds: {{ .Values.sentinel.startupProbe.initialDelaySeconds }}
|
||||
periodSeconds: {{ .Values.sentinel.startupProbe.periodSeconds }}
|
||||
timeoutSeconds: {{ .Values.sentinel.startupProbe.timeoutSeconds }}
|
||||
successThreshold: {{ .Values.sentinel.startupProbe.successThreshold }}
|
||||
failureThreshold: {{ .Values.sentinel.startupProbe.failureThreshold }}
|
||||
exec:
|
||||
command:
|
||||
- sh
|
||||
- -c
|
||||
- /health/sentinel_liveness.sh
|
||||
{{- end }}
|
||||
resources:
|
||||
{{ toYaml .Values.sentinel.resources | indent 10 }}
|
||||
ports:
|
||||
{{- if ne (int .Values.sentinel.port) 0 }}
|
||||
- name: sentinel
|
||||
containerPort: {{ .Values.sentinel.port }}
|
||||
{{- end }}
|
||||
{{- if .Values.sentinel.tlsPort }}
|
||||
- name: sentinel-tls
|
||||
containerPort: {{ .Values.sentinel.tlsPort }}
|
||||
{{- end }}
|
||||
volumeMounts:
|
||||
- mountPath: /data
|
||||
name: data
|
||||
{{- if .Values.redis.tlsPort }}
|
||||
- mountPath: /tls-certs
|
||||
name: tls-certs
|
||||
{{- end }}
|
||||
- mountPath: /health
|
||||
name: health
|
||||
{{- if .Values.sentinel.extraVolumeMounts }}
|
||||
{{- toYaml .Values.sentinel.extraVolumeMounts | nindent 8 }}
|
||||
{{- end }}
|
||||
lifecycle:
|
||||
{{ toYaml .Values.sentinel.lifecycle | indent 10 }}
|
||||
|
||||
- name: split-brain-fix
|
||||
image: {{ .Values.image.repository }}:{{ .Values.image.tag }}
|
||||
imagePullPolicy: {{ .Values.image.pullPolicy }}
|
||||
command:
|
||||
- sh
|
||||
args:
|
||||
- /readonly-config/fix-split-brain.sh
|
||||
securityContext: {{- include "compatibility.renderSecurityContext" (dict "secContext" .Values.containerSecurityContext "context" $) | nindent 10 }}
|
||||
env:
|
||||
{{- $replicas := int (toString .Values.replicas) -}}
|
||||
{{- range $i := until $replicas }}
|
||||
- name: SENTINEL_ID_{{ $i }}
|
||||
value: {{ printf "%s\n%s\nindex: %d" (include "redis-ha.name" $) ($.Release.Name) $i | sha256sum | trunc 40 }}
|
||||
{{- end }}
|
||||
{{- if .Values.auth }}
|
||||
- name: AUTH
|
||||
valueFrom:
|
||||
secretKeyRef:
|
||||
{{- if .Values.existingSecret }}
|
||||
name: {{ .Values.existingSecret }}
|
||||
{{- else }}
|
||||
name: {{ template "redis-ha.fullname" . }}
|
||||
{{- end }}
|
||||
key: {{ .Values.authKey }}
|
||||
{{- end }}
|
||||
{{- if .Values.sentinel.auth }}
|
||||
- name: SENTINELAUTH
|
||||
valueFrom:
|
||||
secretKeyRef:
|
||||
{{- if .Values.sentinel.existingSecret }}
|
||||
name: {{ .Values.sentinel.existingSecret }}
|
||||
{{- else }}
|
||||
name: {{ template "redis-ha.fullname" . }}-sentinel
|
||||
{{- end }}
|
||||
key: {{ .Values.sentinel.authKey }}
|
||||
{{- end }}
|
||||
resources:
|
||||
{{- toYaml .Values.splitBrainDetection.resources | nindent 10 }}
|
||||
volumeMounts:
|
||||
- name: config
|
||||
mountPath: /readonly-config
|
||||
readOnly: true
|
||||
- mountPath: /data
|
||||
name: data
|
||||
{{- if .Values.redis.tlsPort }}
|
||||
- mountPath: /tls-certs
|
||||
name: tls-certs
|
||||
{{- end }}
|
||||
|
||||
{{- if .Values.exporter.enabled }}
|
||||
- name: redis-exporter
|
||||
image: "{{ .Values.exporter.image }}:{{ .Values.exporter.tag }}"
|
||||
imagePullPolicy: {{ .Values.exporter.pullPolicy }}
|
||||
args:
|
||||
{{- range $key, $value := .Values.exporter.extraArgs }}
|
||||
- --{{ $key }}={{ $value }}
|
||||
{{- end }}
|
||||
securityContext: {{- include "compatibility.renderSecurityContext" (dict "secContext" .Values.containerSecurityContext "context" $) | nindent 10 }}
|
||||
env:
|
||||
- name: REDIS_ADDR
|
||||
{{- if .Values.exporter.sslEnabled }}
|
||||
value: rediss://{{ default "localhost" .Values.exporter.address }}:{{ .Values.redis.tlsPort }}
|
||||
{{- else }}
|
||||
value: redis://{{ default "localhost" .Values.exporter.address }}:{{ .Values.redis.port }}
|
||||
{{- end }}
|
||||
{{- if .Values.auth }}
|
||||
- name: REDIS_PASSWORD
|
||||
valueFrom:
|
||||
secretKeyRef:
|
||||
{{- if .Values.existingSecret }}
|
||||
name: {{ .Values.existingSecret }}
|
||||
{{- else }}
|
||||
name: {{ template "redis-ha.fullname" . }}
|
||||
{{- end }}
|
||||
key: {{ .Values.authKey }}
|
||||
{{- end }}
|
||||
{{- if .Values.exporter.script }}
|
||||
- name: REDIS_EXPORTER_SCRIPT
|
||||
value: /script/script.lua
|
||||
{{- end }}
|
||||
{{- if .Values.exporter.sslEnabled }}
|
||||
- name: REDIS_EXPORTER_TLS_CLIENT_KEY_FILE
|
||||
value: /tls-certs/{{ .Values.tls.keyFile }}
|
||||
- name: REDIS_EXPORTER_TLS_CLIENT_CERT_FILE
|
||||
value: /tls-certs/{{ .Values.tls.certFile }}
|
||||
- name: REDIS_EXPORTER_TLS_CA_CERT_FILE
|
||||
value: /tls-certs/{{ .Values.tls.caCertFile }}
|
||||
{{- end }}
|
||||
livenessProbe:
|
||||
{{ toYaml .Values.exporter.livenessProbe | indent 10 }}
|
||||
readinessProbe:
|
||||
{{ toYaml .Values.exporter.readinessProbe | indent 10 }}
|
||||
resources:
|
||||
{{ toYaml .Values.exporter.resources | indent 10 }}
|
||||
ports:
|
||||
- name: {{ .Values.exporter.portName }}
|
||||
containerPort: {{ .Values.exporter.port }}
|
||||
volumeMounts:
|
||||
{{- if .Values.exporter.script }}
|
||||
- mountPath: /script
|
||||
name: script-mount
|
||||
{{- end }}
|
||||
{{- if .Values.exporter.sslEnabled }}
|
||||
- mountPath: /tls-certs
|
||||
name: tls-certs
|
||||
{{- end }}
|
||||
{{- end }}
|
||||
{{- if .Values.extraContainers }}
|
||||
{{- toYaml .Values.extraContainers | nindent 6 }}
|
||||
{{- end -}}
|
||||
{{- with .Values.priorityClassName | default .Values.global.priorityClassName }}
|
||||
priorityClassName: {{ . }}
|
||||
{{- end }}
|
||||
volumes:
|
||||
- name: config
|
||||
configMap:
|
||||
name: {{ template "redis-ha.fullname" . }}-configmap
|
||||
{{- if .Values.sysctlImage.mountHostSys }}
|
||||
- name: host-sys
|
||||
hostPath:
|
||||
path: /sys
|
||||
{{- end }}
|
||||
{{- if .Values.exporter.script }}
|
||||
- name: script-mount
|
||||
configMap:
|
||||
name: {{ template "redis-ha.fullname" . }}-exporter-script-configmap
|
||||
items:
|
||||
- key: script
|
||||
path: script.lua
|
||||
{{- end }}
|
||||
{{- if .Values.redis.tlsPort }}
|
||||
- name: tls-certs
|
||||
secret:
|
||||
{{- if .Values.tls.secretName }}
|
||||
secretName: {{ .Values.tls.secretName }}
|
||||
{{- else }}
|
||||
secretName: {{ template "redis-ha.fullname" . }}-tls-secret
|
||||
{{- end }}
|
||||
{{- end }}
|
||||
- name: health
|
||||
configMap:
|
||||
name: {{ template "redis-ha.fullname" . }}-health-configmap
|
||||
defaultMode: 0755
|
||||
{{- if .Values.extraVolumes }}
|
||||
{{- toYaml .Values.extraVolumes | nindent 6 }}
|
||||
{{- end -}}
|
||||
{{- if .Values.persistentVolume.enabled }}
|
||||
volumeClaimTemplates:
|
||||
- apiVersion: v1
|
||||
kind: PersistentVolumeClaim
|
||||
metadata:
|
||||
name: data
|
||||
annotations:
|
||||
{{- range $key, $value := .Values.persistentVolume.annotations }}
|
||||
{{ $key }}: {{ $value }}
|
||||
{{- end }}
|
||||
labels: {{- toYaml .Values.persistentVolume.labels | nindent 8 }}
|
||||
|
||||
spec:
|
||||
accessModes:
|
||||
{{- range .Values.persistentVolume.accessModes }}
|
||||
- {{ . | quote }}
|
||||
{{- end }}
|
||||
resources:
|
||||
requests:
|
||||
storage: {{ .Values.persistentVolume.size | quote }}
|
||||
{{- if .Values.persistentVolume.storageClass }}
|
||||
{{- if (eq "-" .Values.persistentVolume.storageClass) }}
|
||||
storageClassName: ""
|
||||
{{- else }}
|
||||
storageClassName: "{{ .Values.persistentVolume.storageClass }}"
|
||||
{{- end }}
|
||||
{{- end }}
|
||||
{{- else if .Values.hostPath.path }}
|
||||
- name: data
|
||||
hostPath:
|
||||
path: {{ tpl .Values.hostPath.path .}}
|
||||
{{- else }}
|
||||
- name: data
|
||||
emptyDir:
|
||||
{{ toYaml .Values.emptyDir | indent 10 }}
|
||||
{{- end }}
|
||||
+202
@@ -0,0 +1,202 @@
|
||||
{{- if .Values.haproxy.enabled }}
|
||||
kind: Deployment
|
||||
apiVersion: apps/v1
|
||||
metadata:
|
||||
name: {{ template "redis-ha.fullname" . }}-haproxy
|
||||
namespace: {{ .Release.Namespace | quote }}
|
||||
labels:
|
||||
{{ include "labels.standard" . | indent 4 }}
|
||||
{{- range $key, $value := .Values.extraLabels }}
|
||||
{{ $key }}: {{ $value | quote }}
|
||||
{{- end }}
|
||||
spec:
|
||||
{{- with .Values.haproxy.deploymentStrategy }}
|
||||
strategy:
|
||||
{{- toYaml . | nindent 4 }}
|
||||
{{- end }}
|
||||
revisionHistoryLimit: 1
|
||||
replicas: {{ .Values.haproxy.replicas }}
|
||||
selector:
|
||||
matchLabels:
|
||||
app: {{ template "redis-ha.name" . }}-haproxy
|
||||
release: {{ .Release.Name }}
|
||||
template:
|
||||
metadata:
|
||||
name: {{ template "redis-ha.fullname" . }}-haproxy
|
||||
labels:
|
||||
app: {{ template "redis-ha.name" . }}-haproxy
|
||||
release: {{ .Release.Name }}
|
||||
{{- range $key, $value := .Values.haproxy.labels }}
|
||||
{{ $key }}: {{ $value | toString }}
|
||||
{{- end }}
|
||||
{{- range $key, $value := .Values.extraLabels }}
|
||||
{{ $key }}: {{ $value | quote }}
|
||||
{{- end }}
|
||||
annotations:
|
||||
{{- if and (.Values.haproxy.metrics.enabled) (not .Values.haproxy.metrics.serviceMonitor.enabled) }}
|
||||
prometheus.io/port: "{{ .Values.haproxy.metrics.port }}"
|
||||
prometheus.io/scrape: "true"
|
||||
prometheus.io/path: "{{ .Values.haproxy.metrics.scrapePath }}"
|
||||
{{- end }}
|
||||
checksum/config: {{ print (include "config-haproxy.cfg" .) (include "config-haproxy_init.sh" .) | sha256sum }}
|
||||
{{- if .Values.haproxy.annotations }}
|
||||
{{ toYaml .Values.haproxy.annotations | indent 8 }}
|
||||
{{- end }}
|
||||
spec:
|
||||
# Needed when using unmodified rbac-setup.yml
|
||||
{{ if .Values.haproxy.serviceAccount.create }}
|
||||
serviceAccountName: {{ template "redis-ha.serviceAccountName" . }}-haproxy
|
||||
{{- else }}
|
||||
serviceAccountName: {{ .Values.haproxy.serviceAccountName }}
|
||||
{{- end }}
|
||||
securityContext: {{- include "compatibility.renderSecurityContext" (dict "secContext" .Values.haproxy.securityContext "context" $) | nindent 8 }}
|
||||
automountServiceAccountToken: {{ .Values.haproxy.serviceAccount.automountToken }}
|
||||
nodeSelector:
|
||||
{{ toYaml .Values.nodeSelector | indent 8 }}
|
||||
tolerations:
|
||||
{{ toYaml .Values.tolerations | indent 8 }}
|
||||
affinity:
|
||||
{{- if .Values.haproxy.affinity }}
|
||||
{{- with .Values.haproxy.affinity }}
|
||||
{{ tpl . $ | indent 8 }}
|
||||
{{- end }}
|
||||
{{- else }}
|
||||
{{- if .Values.haproxy.additionalAffinities }}
|
||||
{{ toYaml .Values.haproxy.additionalAffinities | indent 8 }}
|
||||
{{- end }}
|
||||
podAntiAffinity:
|
||||
{{- if .Values.haproxy.hardAntiAffinity }}
|
||||
requiredDuringSchedulingIgnoredDuringExecution:
|
||||
- labelSelector:
|
||||
matchLabels:
|
||||
app: {{ template "redis-ha.name" . }}-haproxy
|
||||
release: {{ .Release.Name }}
|
||||
topologyKey: kubernetes.io/hostname
|
||||
{{- else }}
|
||||
preferredDuringSchedulingIgnoredDuringExecution:
|
||||
- weight: 100
|
||||
podAffinityTerm:
|
||||
labelSelector:
|
||||
matchLabels:
|
||||
app: {{ template "redis-ha.name" . }}-haproxy
|
||||
release: {{ .Release.Name }}
|
||||
topologyKey: kubernetes.io/hostname
|
||||
{{- end }}
|
||||
{{- end }}
|
||||
{{- if .Values.topologySpreadConstraints.enabled }}
|
||||
topologySpreadConstraints:
|
||||
- maxSkew: {{ .Values.topologySpreadConstraints.maxSkew | default 1 }}
|
||||
topologyKey: {{ .Values.topologySpreadConstraints.topologyKey | default "topology.kubernetes.io/zone" }}
|
||||
whenUnsatisfiable: {{ .Values.topologySpreadConstraints.whenUnsatisfiable | default "ScheduleAnyway" }}
|
||||
labelSelector:
|
||||
matchLabels:
|
||||
app: {{ template "redis-ha.name" . }}-haproxy
|
||||
release: {{ .Release.Name }}
|
||||
{{- end }}
|
||||
initContainers:
|
||||
- name: config-init
|
||||
image: {{ .Values.haproxy.image.repository }}:{{ .Values.haproxy.image.tag }}
|
||||
imagePullPolicy: {{ .Values.haproxy.image.pullPolicy }}
|
||||
resources:
|
||||
{{ toYaml .Values.haproxy.init.resources | indent 10 }}
|
||||
command:
|
||||
- sh
|
||||
args:
|
||||
- /readonly/haproxy_init.sh
|
||||
securityContext: {{- include "compatibility.renderSecurityContext" (dict "secContext" .Values.haproxy.containerSecurityContext "context" $) | nindent 10 }}
|
||||
volumeMounts:
|
||||
- name: config-volume
|
||||
mountPath: /readonly
|
||||
readOnly: true
|
||||
- name: data
|
||||
mountPath: /data
|
||||
{{- if .Values.haproxy.imagePullSecrets }}
|
||||
imagePullSecrets: {{ toYaml .Values.haproxy.imagePullSecrets | nindent 8 }}
|
||||
{{- end }}
|
||||
containers:
|
||||
- name: haproxy
|
||||
image: {{ .Values.haproxy.image.repository }}:{{ .Values.haproxy.image.tag }}
|
||||
imagePullPolicy: {{ .Values.haproxy.image.pullPolicy }}
|
||||
securityContext: {{- include "compatibility.renderSecurityContext" (dict "secContext" .Values.haproxy.containerSecurityContext "context" $) | nindent 10 }}
|
||||
{{- if or .Values.auth .Values.sentinel.auth}}
|
||||
env:
|
||||
{{- if .Values.auth }}
|
||||
- name: AUTH
|
||||
valueFrom:
|
||||
secretKeyRef:
|
||||
{{- if .Values.existingSecret }}
|
||||
name: {{ .Values.existingSecret }}
|
||||
{{- else }}
|
||||
name: {{ template "redis-ha.fullname" . }}
|
||||
{{- end }}
|
||||
key: {{ .Values.authKey }}
|
||||
{{- end }}
|
||||
{{- if .Values.sentinel.auth }}
|
||||
- name: SENTINELAUTH
|
||||
valueFrom:
|
||||
secretKeyRef:
|
||||
{{- if .Values.sentinel.existingSecret }}
|
||||
name: {{ .Values.sentinel.existingSecret }}
|
||||
{{- else }}
|
||||
name: {{ template "redis-ha.fullname" . }}-sentinel
|
||||
{{- end }}
|
||||
key: {{ .Values.sentinel.authKey }}
|
||||
{{- end }}
|
||||
{{- end }}
|
||||
livenessProbe:
|
||||
httpGet:
|
||||
path: /healthz
|
||||
port: probe
|
||||
initialDelaySeconds: 5
|
||||
periodSeconds: 3
|
||||
readinessProbe:
|
||||
httpGet:
|
||||
path: /healthz
|
||||
port: probe
|
||||
initialDelaySeconds: 5
|
||||
periodSeconds: 3
|
||||
ports:
|
||||
- name: probe
|
||||
containerPort: 8888
|
||||
- name: redis
|
||||
containerPort: {{ default "6379" .Values.haproxy.containerPort }}
|
||||
{{- if .Values.haproxy.readOnly.enabled }}
|
||||
- name: readonlyport
|
||||
containerPort: {{ default "6380" .Values.haproxy.readOnly.port }}
|
||||
{{- end }}
|
||||
{{- if .Values.haproxy.metrics.enabled }}
|
||||
- name: metrics-port
|
||||
containerPort: {{ default "9101" .Values.haproxy.metrics.port }}
|
||||
{{- end }}
|
||||
resources:
|
||||
{{ toYaml .Values.haproxy.resources | indent 10 }}
|
||||
volumeMounts:
|
||||
- name: data
|
||||
mountPath: /usr/local/etc/haproxy
|
||||
- name: shared-socket
|
||||
mountPath: /run/haproxy
|
||||
{{- if .Values.haproxy.tls.enabled }}
|
||||
- name: pemfile
|
||||
mountPath: {{ .Values.haproxy.tls.certMountPath }}
|
||||
{{- end }}
|
||||
lifecycle:
|
||||
{{ toYaml .Values.haproxy.lifecycle | indent 10 }}
|
||||
{{- with .Values.haproxy.priorityClassName | default .Values.global.priorityClassName }}
|
||||
priorityClassName: {{ . }}
|
||||
{{- end }}
|
||||
volumes:
|
||||
{{- if .Values.haproxy.tls.enabled }}
|
||||
- name: pemfile
|
||||
secret:
|
||||
secretName: {{ .Values.haproxy.tls.secretName }}
|
||||
{{- end }}
|
||||
- name: config-volume
|
||||
configMap:
|
||||
name: {{ template "redis-ha.fullname" . }}-configmap
|
||||
- name: shared-socket
|
||||
emptyDir:
|
||||
{{ toYaml .Values.haproxy.emptyDir | indent 10 }}
|
||||
- name: data
|
||||
emptyDir:
|
||||
{{ toYaml .Values.haproxy.emptyDir | indent 10 }}
|
||||
{{- end }}
|
||||
+74
@@ -0,0 +1,74 @@
|
||||
{{- if and .Values.haproxy.enabled .Values.haproxy.networkPolicy.enabled }}
|
||||
{{- $root := . }}
|
||||
kind: NetworkPolicy
|
||||
apiVersion: networking.k8s.io/v1
|
||||
metadata:
|
||||
name: {{ template "redis-ha.fullname" . }}-haproxy-network-policy
|
||||
namespace: {{ .Release.Namespace | quote }}
|
||||
{{- if .Values.haproxy.networkPolicy.annotations }}
|
||||
annotations:
|
||||
{{- range $key, $value := .Values.haproxy.networkPolicy.annotations }}
|
||||
{{ $key }}: {{ $value | quote }}
|
||||
{{- end }}
|
||||
{{- end }}
|
||||
labels:
|
||||
{{- include "labels.standard" . | nindent 4 }}
|
||||
{{- range $key, $value := .Values.haproxy.networkPolicy.labels }}
|
||||
{{ $key }}: {{ $value | quote }}
|
||||
{{- end }}
|
||||
spec:
|
||||
podSelector:
|
||||
matchLabels:
|
||||
release: {{ .Release.Name }}
|
||||
app: {{ template "redis-ha.name" . }}-haproxy
|
||||
policyTypes:
|
||||
- Ingress
|
||||
- Egress
|
||||
egress:
|
||||
- to:
|
||||
- podSelector:
|
||||
matchLabels:
|
||||
release: {{ .Release.Name }}
|
||||
app: {{ template "redis-ha.name" . }}
|
||||
ports:
|
||||
- port: {{ .Values.redis.port }}
|
||||
protocol: TCP
|
||||
- port: {{ .Values.sentinel.port }}
|
||||
protocol: TCP
|
||||
- to:
|
||||
- namespaceSelector: {}
|
||||
ports:
|
||||
- port: 53
|
||||
protocol: UDP
|
||||
- port: 53
|
||||
protocol: TCP
|
||||
{{- range $rule := .Values.haproxy.networkPolicy.egressRules }}
|
||||
- to:
|
||||
{{- (tpl (toYaml $rule.selectors) $) | nindent 8 }}
|
||||
ports:
|
||||
{{- toYaml $rule.ports | nindent 8 }}
|
||||
{{- end }}
|
||||
ingress:
|
||||
- from:
|
||||
- podSelector:
|
||||
matchLabels:
|
||||
release: {{ .Release.Name }}
|
||||
app: {{ template "redis-ha.name" . }}
|
||||
ports:
|
||||
- port: {{ .Values.redis.port }}
|
||||
protocol: TCP
|
||||
- port: {{ .Values.sentinel.port }}
|
||||
protocol: TCP
|
||||
{{- range $rule := .Values.haproxy.networkPolicy.ingressRules }}
|
||||
- from:
|
||||
{{- (tpl (toYaml $rule.selectors) $) | nindent 8 }}
|
||||
ports:
|
||||
{{- if $rule.ports }}
|
||||
{{- toYaml $rule.ports | nindent 8 }}
|
||||
{{- end }}
|
||||
- port: {{ $root.Values.redis.port }}
|
||||
protocol: TCP
|
||||
- port: {{ $root.Values.sentinel.port }}
|
||||
protocol: TCP
|
||||
{{- end }}
|
||||
{{- end }}
|
||||
@@ -0,0 +1,18 @@
|
||||
{{- if .Values.haproxy.podDisruptionBudget -}}
|
||||
apiVersion: {{ template "redis-ha.podDisruptionBudget.apiVersion" . }}
|
||||
kind: PodDisruptionBudget
|
||||
metadata:
|
||||
name: {{ template "redis-ha.fullname" . }}-haproxy-pdb
|
||||
namespace: {{ .Release.Namespace | quote }}
|
||||
labels:
|
||||
{{ include "labels.standard" . | indent 4 }}
|
||||
{{- range $key, $value := .Values.extraLabels }}
|
||||
{{ $key }}: {{ $value | quote }}
|
||||
{{- end }}
|
||||
spec:
|
||||
selector:
|
||||
matchLabels:
|
||||
release: {{ .Release.Name }}
|
||||
app: {{ template "redis-ha.name" . }}-haproxy
|
||||
{{ toYaml .Values.haproxy.podDisruptionBudget | indent 2 }}
|
||||
{{- end -}}
|
||||
@@ -0,0 +1,22 @@
|
||||
{{- if .Values.haproxy.enabled }}
|
||||
{{- if and .Values.haproxy.serviceAccount.create .Values.rbac.create }}
|
||||
apiVersion: rbac.authorization.k8s.io/v1
|
||||
kind: Role
|
||||
metadata:
|
||||
name: {{ template "redis-ha.fullname" . }}-haproxy
|
||||
namespace: {{ .Release.Namespace | quote }}
|
||||
labels:
|
||||
{{ include "labels.standard" . | indent 4 }}
|
||||
component: {{ template "redis-ha.fullname" . }}-haproxy
|
||||
{{- range $key, $value := .Values.extraLabels }}
|
||||
{{ $key }}: {{ $value | quote }}
|
||||
{{- end }}
|
||||
rules:
|
||||
- apiGroups:
|
||||
- ""
|
||||
resources:
|
||||
- endpoints
|
||||
verbs:
|
||||
- get
|
||||
{{- end }}
|
||||
{{- end }}
|
||||
+22
@@ -0,0 +1,22 @@
|
||||
{{- if .Values.haproxy.enabled }}
|
||||
{{- if and .Values.haproxy.serviceAccount.create .Values.rbac.create }}
|
||||
apiVersion: rbac.authorization.k8s.io/v1
|
||||
kind: RoleBinding
|
||||
metadata:
|
||||
name: {{ template "redis-ha.fullname" . }}-haproxy
|
||||
namespace: {{ .Release.Namespace | quote }}
|
||||
labels:
|
||||
{{ include "labels.standard" . | indent 4 }}
|
||||
component: {{ template "redis-ha.fullname" . }}-haproxy
|
||||
{{- range $key, $value := .Values.extraLabels }}
|
||||
{{ $key }}: {{ $value | quote }}
|
||||
{{- end }}
|
||||
subjects:
|
||||
- kind: ServiceAccount
|
||||
name: {{ template "redis-ha.serviceAccountName" . }}-haproxy
|
||||
roleRef:
|
||||
apiGroup: rbac.authorization.k8s.io
|
||||
kind: Role
|
||||
name: {{ template "redis-ha.fullname" . }}-haproxy
|
||||
{{- end }}
|
||||
{{- end }}
|
||||
@@ -0,0 +1,60 @@
|
||||
{{- if .Values.haproxy.enabled }}
|
||||
apiVersion: v1
|
||||
kind: Service
|
||||
metadata:
|
||||
name: {{ template "redis-ha.fullname" . }}-haproxy
|
||||
namespace: {{ .Release.Namespace | quote }}
|
||||
labels:
|
||||
{{ include "labels.standard" . | indent 4 }}
|
||||
component: {{ template "redis-ha.fullname" . }}-haproxy
|
||||
{{- range $key, $value := .Values.extraLabels }}
|
||||
{{ $key }}: {{ $value | quote }}
|
||||
{{- end }}
|
||||
{{- range $key, $value := .Values.haproxy.service.labels }}
|
||||
{{ $key }}: {{ $value | quote }}
|
||||
{{- end }}
|
||||
annotations:
|
||||
{{- if .Values.haproxy.service.annotations }}
|
||||
{{ toYaml .Values.haproxy.service.annotations | indent 4 }}
|
||||
{{- end }}
|
||||
spec:
|
||||
type: {{ default "ClusterIP" .Values.haproxy.service.type }}
|
||||
{{- if and (eq .Values.haproxy.service.type "LoadBalancer") .Values.haproxy.service.loadBalancerIP }}
|
||||
loadBalancerIP: {{ .Values.haproxy.service.loadBalancerIP }}
|
||||
{{- end }}
|
||||
{{- if and (eq .Values.haproxy.service.type "LoadBalancer") .Values.haproxy.service.externalTrafficPolicy }}
|
||||
externalTrafficPolicy: {{ .Values.haproxy.service.externalTrafficPolicy }}
|
||||
{{- end }}
|
||||
{{- if and (eq .Values.haproxy.service.type "LoadBalancer") .Values.haproxy.service.loadBalancerSourceRanges }}
|
||||
loadBalancerSourceRanges: {{ toYaml .Values.haproxy.service.loadBalancerSourceRanges | nindent 2 }}
|
||||
{{- end }}
|
||||
{{- if .Values.haproxy.service.externalIPs }}
|
||||
externalIPs:
|
||||
{{- range $key, $value := .Values.haproxy.service.externalIPs }}
|
||||
- {{ $value }}
|
||||
{{- end }}
|
||||
{{- end }}
|
||||
ports:
|
||||
- name: tcp-haproxy
|
||||
port: {{ .Values.haproxy.servicePort }}
|
||||
protocol: TCP
|
||||
targetPort: redis
|
||||
{{- if and (eq .Values.haproxy.service.type "NodePort") .Values.haproxy.service.nodePort }}
|
||||
nodePort: {{ .Values.haproxy.service.nodePort }}
|
||||
{{- end }}
|
||||
{{- if .Values.haproxy.readOnly.enabled }}
|
||||
- name: tcp-haproxyreadonly
|
||||
port: {{ .Values.haproxy.readOnly.port }}
|
||||
protocol: TCP
|
||||
targetPort: {{ .Values.haproxy.readOnly.port }}
|
||||
{{- end }}
|
||||
{{- if .Values.haproxy.metrics.enabled }}
|
||||
- name: {{ .Values.haproxy.metrics.portName }}
|
||||
port: {{ .Values.haproxy.metrics.port }}
|
||||
protocol: TCP
|
||||
targetPort: metrics-port
|
||||
{{- end }}
|
||||
selector:
|
||||
release: {{ .Release.Name }}
|
||||
app: {{ template "redis-ha.name" . }}-haproxy
|
||||
{{- end }}
|
||||
+15
@@ -0,0 +1,15 @@
|
||||
{{- if and .Values.haproxy.serviceAccount.create .Values.haproxy.enabled }}
|
||||
apiVersion: v1
|
||||
kind: ServiceAccount
|
||||
metadata:
|
||||
name: {{ template "redis-ha.serviceAccountName" . }}-haproxy
|
||||
namespace: {{ .Release.Namespace | quote }}
|
||||
labels:
|
||||
heritage: {{ .Release.Service }}
|
||||
release: {{ .Release.Name }}
|
||||
chart: {{ .Chart.Name }}-{{ .Chart.Version }}
|
||||
app: {{ template "redis-ha.fullname" . }}
|
||||
{{- range $key, $value := .Values.extraLabels }}
|
||||
{{ $key }}: {{ $value | quote }}
|
||||
{{- end }}
|
||||
{{- end }}
|
||||
+39
@@ -0,0 +1,39 @@
|
||||
{{- if and ( or .Values.haproxy.metrics.serviceMonitor.disableAPICheck ( .Capabilities.APIVersions.Has "monitoring.coreos.com/v1" ) ) ( .Values.haproxy.metrics.serviceMonitor.enabled ) ( .Values.haproxy.metrics.enabled ) }}
|
||||
apiVersion: monitoring.coreos.com/v1
|
||||
kind: ServiceMonitor
|
||||
metadata:
|
||||
name: {{ template "redis-ha.fullname" . }}-haproxy
|
||||
namespace: {{ .Values.haproxy.metrics.serviceMonitor.namespace | default .Release.Namespace | quote }}
|
||||
labels:
|
||||
{{ include "labels.standard" . | indent 4 }}
|
||||
{{- range $key, $value := .Values.extraLabels }}
|
||||
{{ $key }}: {{ $value | quote }}
|
||||
{{- end }}
|
||||
{{- range $key, $value := .Values.haproxy.metrics.serviceMonitor.labels }}
|
||||
{{ $key }}: {{ $value | quote }}
|
||||
{{- end }}
|
||||
spec:
|
||||
endpoints:
|
||||
- targetPort: {{ .Values.haproxy.metrics.port }}
|
||||
{{- if .Values.haproxy.metrics.serviceMonitor.interval }}
|
||||
interval: {{ .Values.haproxy.metrics.serviceMonitor.interval }}
|
||||
{{- end }}
|
||||
{{- if .Values.haproxy.metrics.serviceMonitor.telemetryPath }}
|
||||
path: {{ .Values.haproxy.metrics.serviceMonitor.telemetryPath }}
|
||||
{{- end }}
|
||||
{{- if .Values.haproxy.metrics.serviceMonitor.timeout }}
|
||||
scrapeTimeout: {{ .Values.haproxy.metrics.serviceMonitor.timeout }}
|
||||
{{- end }}
|
||||
{{- with .Values.haproxy.metrics.serviceMonitor.endpointAdditionalProperties }}
|
||||
{{- toYaml . | nindent 4 }}
|
||||
{{- end }}
|
||||
jobLabel: {{ template "redis-ha.fullname" . }}-haproxy
|
||||
namespaceSelector:
|
||||
matchNames:
|
||||
- {{ .Release.Namespace | quote }}
|
||||
selector:
|
||||
matchLabels:
|
||||
app: {{ template "redis-ha.name" . }}
|
||||
release: {{ .Release.Name }}
|
||||
component: {{ template "redis-ha.fullname" . }}-haproxy
|
||||
{{- end }}
|
||||
@@ -0,0 +1,27 @@
|
||||
{{- if and .Values.redis.tlsPort (not .Values.tls.secretName) -}}
|
||||
apiVersion: v1
|
||||
kind: Secret
|
||||
metadata:
|
||||
metadata:
|
||||
name: {{ template "redis-ha.fullname" . }}-tls-secret
|
||||
namespace: {{ .Release.Namespace | quote }}
|
||||
labels:
|
||||
{{ include "labels.standard" . | indent 4 }}
|
||||
{{- range $key, $value := .Values.extraLabels }}
|
||||
{{ $key }}: {{ $value | quote }}
|
||||
{{- end }}
|
||||
type: Opaque
|
||||
data:
|
||||
{{- if .Values.tls.caCertFile }}
|
||||
{{ .Values.tls.caCertFile }}: {{ .Files.Get "certs/ca.crt" | b64enc }}
|
||||
{{- end }}
|
||||
{{- if .Values.tls.certFile }}
|
||||
{{ .Values.tls.certFile }}: {{ .Files.Get "certs/redis.crt" | b64enc }}
|
||||
{{- end }}
|
||||
{{- if .Values.tls.keyFile }}
|
||||
{{ .Values.tls.keyFile }}: {{ .Files.Get "certs/redis.key" | b64enc }}
|
||||
{{- end }}
|
||||
{{- if .Values.tls.dhParamsFile }}
|
||||
{{ .Values.tls.dhParamsFile }}: {{ .Files.Get "certs/redis.dh" | b64enc }}
|
||||
{{- end }}
|
||||
{{- end }}
|
||||
@@ -0,0 +1,15 @@
|
||||
{{- if and .Values.sentinel.auth (not .Values.sentinel.existingSecret) -}}
|
||||
apiVersion: v1
|
||||
kind: Secret
|
||||
metadata:
|
||||
name: {{ template "redis-ha.fullname" . }}-sentinel
|
||||
namespace: {{ .Release.Namespace | quote }}
|
||||
labels:
|
||||
{{ include "labels.standard" . | indent 4 }}
|
||||
{{- range $key, $value := .Values.extraLabels }}
|
||||
{{ $key }}: {{ $value | quote }}
|
||||
{{- end }}
|
||||
type: Opaque
|
||||
data:
|
||||
{{ .Values.sentinel.authKey }}: {{ .Values.sentinel.password | b64enc | quote }}
|
||||
{{- end -}}
|
||||
+32
@@ -0,0 +1,32 @@
|
||||
apiVersion: v1
|
||||
kind: Pod
|
||||
metadata:
|
||||
name: {{ template "redis-ha.fullname" . }}-configmap-test
|
||||
namespace: {{ .Release.Namespace | quote }}
|
||||
labels:
|
||||
{{ include "labels.standard" . | indent 4 }}
|
||||
annotations:
|
||||
"helm.sh/hook": test-success
|
||||
spec:
|
||||
nodeSelector: {{ toYaml .Values.nodeSelector | nindent 4 }}
|
||||
tolerations: {{ toYaml .Values.tolerations | nindent 4 }}
|
||||
containers:
|
||||
- name: check-init
|
||||
image: {{ .Values.configmapTest.image.repository }}:{{ .Values.configmapTest.image.tag }}
|
||||
args:
|
||||
- --shell=sh
|
||||
- /readonly-config/init.sh
|
||||
volumeMounts:
|
||||
- name: config
|
||||
mountPath: /readonly-config
|
||||
readOnly: true
|
||||
resources: {{ toYaml .Values.configmapTest.resources | nindent 6 }}
|
||||
securityContext: {{- include "compatibility.renderSecurityContext" (dict "secContext" .Values.containerSecurityContext "context" $) | nindent 6 }}
|
||||
{{- if .Values.imagePullSecrets }}
|
||||
imagePullSecrets: {{ toYaml .Values.imagePullSecrets | nindent 4 }}
|
||||
{{- end }}
|
||||
restartPolicy: Never
|
||||
volumes:
|
||||
- name: config
|
||||
configMap:
|
||||
name: {{ template "redis-ha.fullname" . }}-configmap
|
||||
@@ -0,0 +1,29 @@
|
||||
{{- if .Values.haproxy.enabled }}
|
||||
apiVersion: v1
|
||||
kind: Pod
|
||||
metadata:
|
||||
name: {{ template "redis-ha.fullname" . }}-service-test
|
||||
namespace: {{ .Release.Namespace | quote }}
|
||||
labels:
|
||||
{{ include "labels.standard" . | indent 4 }}
|
||||
annotations:
|
||||
"helm.sh/hook": test-success
|
||||
spec:
|
||||
nodeSelector:
|
||||
{{ toYaml .Values.nodeSelector | indent 4 }}
|
||||
tolerations:
|
||||
{{ toYaml .Values.tolerations | indent 4 }}
|
||||
containers:
|
||||
- name: "{{ .Release.Name }}-service-test"
|
||||
image: {{ .Values.image.repository }}:{{ .Values.image.tag }}
|
||||
command:
|
||||
- sh
|
||||
- -c
|
||||
- redis-cli -h {{ template "redis-ha.fullname" . }}-haproxy -p {{ .Values.redis.port }} info server
|
||||
resources: {{ toYaml .Values.haproxy.tests.resources | nindent 6 }}
|
||||
securityContext: {{- include "compatibility.renderSecurityContext" (dict "secContext" .Values.containerSecurityContext "context" $) | nindent 6 }}
|
||||
{{- if .Values.imagePullSecrets }}
|
||||
imagePullSecrets: {{ toYaml .Values.imagePullSecrets | nindent 4 }}
|
||||
{{- end }}
|
||||
restartPolicy: Never
|
||||
{{- end }}
|
||||
Reference in New Issue
Block a user