jina verze
This commit is contained in:
@@ -0,0 +1,416 @@
|
||||
{{- if .Values.redisHelm }}
|
||||
|
||||
---
|
||||
apiVersion: v1
|
||||
kind: ConfigMap
|
||||
metadata: { name: "{{ .Values.redis }}-config", namespace: "{{ .Values.namespace }}" }
|
||||
data:
|
||||
redis.conf: |
|
||||
bind 0.0.0.0
|
||||
port 6379
|
||||
dir /data
|
||||
|
||||
# --- ACL ---
|
||||
aclfile /data-acl/{{ .Values.redisFileUsersAcl }}
|
||||
|
||||
# --- all in one DB ---
|
||||
databases 1
|
||||
|
||||
# --- network ---
|
||||
protected-mode yes
|
||||
tcp-backlog 1024
|
||||
tcp-keepalive 300
|
||||
timeout 0
|
||||
|
||||
# --- connections ---
|
||||
maxclients {{ .Values.profiles.redis.maxClients }}
|
||||
|
||||
# --- memory (tune) ---
|
||||
maxmemory {{ .Values.profiles.redis.maxmemory }}
|
||||
maxmemory-policy allkeys-lfu
|
||||
maxmemory-samples 5
|
||||
maxmemory-eviction-tenacity 10
|
||||
maxmemory-clients 5%
|
||||
client-query-buffer-limit 256mb
|
||||
client-output-buffer-limit normal 0 0 0
|
||||
client-output-buffer-limit replica 256mb 64mb 60
|
||||
client-output-buffer-limit pubsub 32mb 8mb 60
|
||||
|
||||
# --- replication ---
|
||||
replica-serve-stale-data yes
|
||||
replica-read-only yes
|
||||
repl-backlog-size 64mb
|
||||
repl-backlog-ttl 3600
|
||||
min-replicas-to-write 0
|
||||
#min-replicas-max-lag 10
|
||||
|
||||
# --- persistence ---
|
||||
appendonly yes
|
||||
appendfsync everysec
|
||||
aof-rewrite-incremental-fsync yes
|
||||
rdb-save-incremental-fsync yes
|
||||
save ""
|
||||
|
||||
# --- log ---
|
||||
slowlog-log-slower-than 10000
|
||||
slowlog-max-len 128
|
||||
latency-monitor-threshold 0
|
||||
|
||||
---
|
||||
apiVersion: v1
|
||||
kind: PersistentVolume
|
||||
metadata: { name: "{{ .Values.redis }}-users-pv" }
|
||||
spec:
|
||||
capacity: { storage: 1Gi }
|
||||
volumeMode: Filesystem
|
||||
accessModes: [ ReadWriteMany ]
|
||||
persistentVolumeReclaimPolicy: Retain
|
||||
hostPath: { path: "{{ .Values.redisPath }}", type: DirectoryOrCreate }
|
||||
|
||||
---
|
||||
apiVersion: v1
|
||||
kind: PersistentVolumeClaim
|
||||
metadata: { name: "{{ .Values.redis }}-users-pvc", namespace: "{{ .Values.namespace }}" }
|
||||
spec:
|
||||
volumeName: "{{ .Values.redis }}-users-pv"
|
||||
volumeMode: Filesystem
|
||||
accessModes: [ ReadWriteMany ]
|
||||
resources: { requests: { storage: 1Gi } }
|
||||
storageClassName: ""
|
||||
|
||||
---
|
||||
apiVersion: apps/v1
|
||||
kind: StatefulSet
|
||||
metadata: { name: "{{ .Values.redis }}", namespace: "{{ .Values.namespace }}" }
|
||||
spec:
|
||||
serviceName: "{{ .Values.redis }}"
|
||||
replicas: 2
|
||||
selector: { matchLabels: { app: "{{ .Values.redis }}" } }
|
||||
persistentVolumeClaimRetentionPolicy: { whenDeleted: Delete, whenScaled: Retain }
|
||||
template:
|
||||
metadata: { labels: { app: "{{ .Values.redis }}" } }
|
||||
spec:
|
||||
terminationGracePeriodSeconds: 30
|
||||
initContainers:
|
||||
- name: init-redis-acl
|
||||
image: redis:8.6-alpine
|
||||
resources:
|
||||
requests: { cpu: "10m", memory: "32Mi" }
|
||||
limits: { cpu: "100m", memory: "128Mi" }
|
||||
env:
|
||||
- { name: POD_NAME, valueFrom: { fieldRef: { fieldPath: metadata.name } } }
|
||||
- { name: REDIS_PASSWORD, valueFrom: { secretKeyRef: { name: "{{ .Values.redis }}-secret", key: root-password } } }
|
||||
command: ["/bin/sh","-c"]
|
||||
args:
|
||||
- |
|
||||
set -eu
|
||||
ACL="/data-acl/{{ .Values.redisFileUsersAcl }}"
|
||||
HASH=$(printf '%s' "$REDIS_PASSWORD" | sha256sum | awk '{print $1}')
|
||||
mkdir -p /data-acl
|
||||
|
||||
if [ "$POD_NAME" = "{{ .Values.redis }}-0" ]; then
|
||||
tmp="${ACL}.tmp"
|
||||
|
||||
if [ -f "$ACL" ]; then
|
||||
awk '!(tolower($1)=="user" && $2=="default")' "$ACL" > "$tmp"
|
||||
else
|
||||
: > "$tmp"
|
||||
fi
|
||||
|
||||
# default user is used by replication auth and HAProxy health checks
|
||||
printf 'user default on sanitize-payload #%s ~* &* +@all\n' "$HASH" >> "$tmp"
|
||||
mv "$tmp" "$ACL"
|
||||
chmod 600 "$ACL"
|
||||
else
|
||||
i=0
|
||||
while [ ! -f "$ACL" ] && [ $i -lt 300 ]; do
|
||||
sleep 1
|
||||
i=$((i+1))
|
||||
done
|
||||
[ -f "$ACL" ] || exit 1
|
||||
fi
|
||||
volumeMounts:
|
||||
- { name: "{{ .Values.redis }}-users-volume", mountPath: /data-acl }
|
||||
containers:
|
||||
- name: "{{ .Values.redis }}"
|
||||
image: redis:8.6-alpine
|
||||
resources:
|
||||
requests: { cpu: "{{ .Values.profiles.redis.cpuRequest }}", memory: "{{ .Values.profiles.redis.memoryRequest }}" }
|
||||
limits: { cpu: "{{ .Values.profiles.redis.cpuLimit }}", memory: "{{ .Values.profiles.redis.memoryLimit }}" }
|
||||
ports:
|
||||
- { name: redis, containerPort: 6379 }
|
||||
env:
|
||||
- { name: POD_NAME, valueFrom: { fieldRef: { fieldPath: metadata.name } } }
|
||||
- { name: POD_IP, valueFrom: { fieldRef: { fieldPath: status.podIP } } }
|
||||
- { name: REDIS_PASSWORD, valueFrom: { secretKeyRef: { name: "{{ .Values.redis }}-secret", key: root-password } } }
|
||||
- { name: SENTINEL_HOST, value: "{{ .Values.redisSentinel }}" }
|
||||
- { name: SENTINEL_PORT, value: "26379" }
|
||||
- { name: MASTER_NAME, value: "mymaster" }
|
||||
command: ["/bin/sh","-c"]
|
||||
args:
|
||||
- |
|
||||
set -eu
|
||||
|
||||
POD_DNS_SHORT="${POD_NAME}.{{ .Values.redis }}"
|
||||
POD_DNS_FQDN="${POD_NAME}.{{ .Values.redis }}.{{ .Values.namespace }}.svc.cluster.local"
|
||||
|
||||
get_master() {
|
||||
REDISCLI_AUTH="$REDIS_PASSWORD" \
|
||||
redis-cli -h "$SENTINEL_HOST" -p "$SENTINEL_PORT" \
|
||||
SENTINEL get-master-addr-by-name "$MASTER_NAME" 2>/dev/null | tr -d '\r'
|
||||
}
|
||||
|
||||
out=""
|
||||
i=0
|
||||
while [ $i -lt 20 ]; do
|
||||
out="$(get_master || true)"
|
||||
[ -n "$out" ] && break
|
||||
i=$((i+1))
|
||||
sleep 1
|
||||
done
|
||||
|
||||
master_host="$(printf '%s\n' "$out" | sed -n '1p')"
|
||||
master_port="$(printf '%s\n' "$out" | sed -n '2p')"
|
||||
[ -n "$master_port" ] || master_port="6379"
|
||||
|
||||
is_me_master() {
|
||||
[ "$master_host" = "$POD_IP" ] || [ "$master_host" = "$POD_DNS_SHORT" ] || [ "$master_host" = "$POD_DNS_FQDN" ]
|
||||
}
|
||||
|
||||
if [ -n "$master_host" ]; then
|
||||
if is_me_master; then
|
||||
exec redis-server /etc/redis/redis.conf --masteruser default --masterauth "$REDIS_PASSWORD"
|
||||
else
|
||||
exec redis-server /etc/redis/redis.conf --replicaof "$master_host" "$master_port" --masteruser default --masterauth "$REDIS_PASSWORD"
|
||||
fi
|
||||
else
|
||||
# bootstrap if sentinel is not ready yet
|
||||
if [ "$POD_NAME" = "{{ .Values.redis }}-0" ]; then
|
||||
exec redis-server /etc/redis/redis.conf
|
||||
else
|
||||
exec redis-server /etc/redis/redis.conf --replicaof {{ .Values.redis }}-0.{{ .Values.redis }} 6379 --masteruser default --masterauth "$REDIS_PASSWORD"
|
||||
fi
|
||||
fi
|
||||
volumeMounts:
|
||||
- { name: "{{ .Values.redis }}-data-volume", mountPath: /data }
|
||||
- { name: "{{ .Values.redis }}-config-volume", mountPath: /etc/redis }
|
||||
- { name: "{{ .Values.redis }}-users-volume", mountPath: /data-acl }
|
||||
volumes:
|
||||
- name: "{{ .Values.redis }}-config-volume"
|
||||
configMap: { name: "{{ .Values.redis }}-config" }
|
||||
- name: "{{ .Values.redis }}-users-volume"
|
||||
persistentVolumeClaim: { claimName: "{{ .Values.redis }}-users-pvc" }
|
||||
volumeClaimTemplates:
|
||||
- metadata: { name: "{{ .Values.redis }}-data-volume" }
|
||||
spec:
|
||||
accessModes: [ ReadWriteOnce ]
|
||||
resources: { requests: { storage: 10Gi } }
|
||||
|
||||
---
|
||||
apiVersion: v1
|
||||
kind: Service
|
||||
metadata: { name: "{{ .Values.redis }}", namespace: "{{ .Values.namespace }}" }
|
||||
spec:
|
||||
clusterIP: None
|
||||
selector: { app: "{{ .Values.redis }}" }
|
||||
ports:
|
||||
- { name: redis, protocol: TCP, port: 6379, targetPort: 6379 }
|
||||
|
||||
# -------------------------
|
||||
# Sentinel (1) with PVC
|
||||
# -------------------------
|
||||
---
|
||||
apiVersion: v1
|
||||
kind: ConfigMap
|
||||
metadata: { name: "{{ .Values.redisSentinel }}-config", namespace: "{{ .Values.namespace }}" }
|
||||
data:
|
||||
sentinel.conf.tmpl: |
|
||||
bind 0.0.0.0
|
||||
port 26379
|
||||
dir /data
|
||||
|
||||
sentinel deny-scripts-reconfig yes
|
||||
sentinel resolve-hostnames yes
|
||||
sentinel announce-hostnames yes
|
||||
|
||||
# quorum=1 (single sentinel)
|
||||
sentinel monitor mymaster {{ .Values.redis }}-0.{{ .Values.redis }} 6379 1
|
||||
sentinel down-after-milliseconds mymaster 5000
|
||||
sentinel failover-timeout mymaster 60000
|
||||
sentinel parallel-syncs mymaster 1
|
||||
|
||||
sentinel auth-user mymaster default
|
||||
sentinel auth-pass mymaster __PASSWORD__
|
||||
|
||||
requirepass __PASSWORD__
|
||||
|
||||
---
|
||||
apiVersion: apps/v1
|
||||
kind: StatefulSet
|
||||
metadata: { name: "{{ .Values.redisSentinel }}", namespace: "{{ .Values.namespace }}" }
|
||||
spec:
|
||||
replicas: 1
|
||||
serviceName: "{{ .Values.redisSentinel }}"
|
||||
selector: { matchLabels: { app: "{{ .Values.redisSentinel }}" } }
|
||||
persistentVolumeClaimRetentionPolicy: { whenDeleted: Delete, whenScaled: Retain }
|
||||
template:
|
||||
metadata: { labels: { app: "{{ .Values.redisSentinel }}" } }
|
||||
spec:
|
||||
containers:
|
||||
- name: "{{ .Values.redisSentinel }}"
|
||||
image: redis:8.6-alpine
|
||||
resources:
|
||||
requests: { cpu: "50m", memory: "128Mi" }
|
||||
limits: { cpu: "200m", memory: "256Mi" }
|
||||
ports:
|
||||
- { name: sentinel, containerPort: 26379 }
|
||||
env:
|
||||
- { name: REDIS_PASSWORD, valueFrom: { secretKeyRef: { name: "{{ .Values.redis }}-secret", key: root-password } } }
|
||||
command: ["/bin/sh","-c"]
|
||||
args:
|
||||
- |
|
||||
set -eu
|
||||
CONF=/data/sentinel.conf
|
||||
if [ ! -f "$CONF" ]; then
|
||||
pwd_escaped=$(printf '%s' "$REDIS_PASSWORD" | sed -e 's/[\/&]/\\&/g')
|
||||
sed "s/__PASSWORD__/${pwd_escaped}/g" /tmpl/sentinel.conf.tmpl > "$CONF"
|
||||
chmod 600 "$CONF"
|
||||
fi
|
||||
exec redis-server "$CONF" --sentinel
|
||||
volumeMounts:
|
||||
- { name: "{{ .Values.redisSentinel }}-tmpl", mountPath: /tmpl }
|
||||
- { name: "{{ .Values.redisSentinel }}-data", mountPath: /data }
|
||||
volumes:
|
||||
- name: "{{ .Values.redisSentinel }}-tmpl"
|
||||
configMap: { name: "{{ .Values.redisSentinel }}-config" }
|
||||
volumeClaimTemplates:
|
||||
- metadata: { name: "{{ .Values.redisSentinel }}-data" }
|
||||
spec:
|
||||
accessModes: [ ReadWriteOnce ]
|
||||
resources: { requests: { storage: 1Gi } }
|
||||
|
||||
---
|
||||
apiVersion: v1
|
||||
kind: Service
|
||||
metadata: { name: "{{ .Values.redisSentinel }}", namespace: "{{ .Values.namespace }}" }
|
||||
spec:
|
||||
selector: { app: "{{ .Values.redisSentinel }}" }
|
||||
ports:
|
||||
- { name: sentinel, port: 26379, targetPort: 26379 }
|
||||
|
||||
---
|
||||
apiVersion: networking.k8s.io/v1
|
||||
kind: NetworkPolicy
|
||||
metadata: { name: "{{ .Values.redisSentinel }}-allow-only-checker", namespace: "{{ .Values.namespace }}" }
|
||||
spec:
|
||||
podSelector: { matchLabels: { app: "{{ .Values.redisSentinel }}" } }
|
||||
policyTypes:
|
||||
- Ingress
|
||||
ingress:
|
||||
- from:
|
||||
- podSelector: { matchLabels: { app: "{{ .Values.redis }}" } }
|
||||
- podSelector: { matchLabels: { app: "{{ .Values.redisSentinel }}" } }
|
||||
ports:
|
||||
- { protocol: TCP, port: 26379 }
|
||||
|
||||
# -------------------------
|
||||
# HAProxy: single master endpoint
|
||||
# -------------------------
|
||||
---
|
||||
apiVersion: v1
|
||||
kind: ConfigMap
|
||||
metadata: { name: "{{ .Values.redis }}-haproxy-config", namespace: "{{ .Values.namespace }}" }
|
||||
data:
|
||||
haproxy.cfg: |
|
||||
global
|
||||
log stdout format raw local0
|
||||
maxconn 20000
|
||||
|
||||
resolvers kubedns
|
||||
nameserver dns1 10.43.0.10:53
|
||||
accepted_payload_size 8192
|
||||
resolve_retries 3
|
||||
timeout resolve 1s
|
||||
timeout retry 1s
|
||||
hold valid 10s
|
||||
hold obsolete 30s
|
||||
|
||||
defaults
|
||||
mode tcp
|
||||
log global
|
||||
option tcplog
|
||||
option log-health-checks
|
||||
timeout connect 5s
|
||||
timeout client 1m
|
||||
timeout server 1m
|
||||
timeout check 1s
|
||||
|
||||
frontend fe_redis_master
|
||||
bind *:6379
|
||||
default_backend be_redis_master
|
||||
|
||||
backend be_redis_master
|
||||
mode tcp
|
||||
balance first
|
||||
option tcp-check
|
||||
option srvtcpka
|
||||
timeout queue 2s
|
||||
timeout connect 2s
|
||||
timeout check 3s
|
||||
timeout server 10m
|
||||
tcp-check connect
|
||||
tcp-check send-lf "AUTH default $REDIS_PASSWORD\r\n"
|
||||
tcp-check expect string +OK
|
||||
tcp-check send INFO\ replication\r\n
|
||||
tcp-check expect string role:master
|
||||
tcp-check send QUIT\r\n
|
||||
tcp-check expect string +OK
|
||||
server redis0 {{ .Values.redis }}-0.{{ .Values.redis }}.{{ .Values.namespace }}.svc.cluster.local:6379 check resolvers kubedns resolve-prefer ipv4 init-addr libc,none inter 5s fall 2 rise 2
|
||||
server redis1 {{ .Values.redis }}-1.{{ .Values.redis }}.{{ .Values.namespace }}.svc.cluster.local:6379 check resolvers kubedns resolve-prefer ipv4 init-addr libc,none inter 5s fall 2 rise 2
|
||||
|
||||
---
|
||||
apiVersion: apps/v1
|
||||
kind: Deployment
|
||||
metadata: { name: "{{ .Values.redis }}-haproxy", namespace: "{{ .Values.namespace }}" }
|
||||
spec:
|
||||
replicas: 1
|
||||
selector: { matchLabels: { app: "{{ .Values.redis }}-haproxy" } }
|
||||
template:
|
||||
metadata:
|
||||
labels: { app: "{{ .Values.redis }}-haproxy" }
|
||||
spec:
|
||||
containers:
|
||||
- name: "{{ .Values.redis }}-haproxy"
|
||||
image: haproxy:2.9-alpine
|
||||
resources:
|
||||
requests: { cpu: "50m", memory: "64Mi" }
|
||||
limits: { cpu: "500m", memory: "256Mi" }
|
||||
ports:
|
||||
- { name: redis, containerPort: 6379 }
|
||||
env:
|
||||
- { name: REDIS_PASSWORD, valueFrom: { secretKeyRef: { name: "{{ .Values.redis }}-secret", key: root-password } } }
|
||||
command: ["/bin/sh","-c"]
|
||||
args:
|
||||
- |
|
||||
set -eu
|
||||
haproxy -c -f /usr/local/etc/haproxy/haproxy.cfg
|
||||
exec haproxy -f /usr/local/etc/haproxy/haproxy.cfg -db
|
||||
readinessProbe: { tcpSocket: { port: 6379 }, initialDelaySeconds: 1, periodSeconds: 2, failureThreshold: 3 }
|
||||
livenessProbe: { tcpSocket: { port: 6379 }, initialDelaySeconds: 10, periodSeconds: 10, failureThreshold: 3 }
|
||||
volumeMounts:
|
||||
# - { name: cfg, mountPath: /usr/local/etc/haproxy/haproxy.cfg, subPath: haproxy.cfg }
|
||||
- { name: cfg, mountPath: /usr/local/etc/haproxy }
|
||||
volumes:
|
||||
- name: cfg
|
||||
configMap: { name: "{{ .Values.redis }}-haproxy-config" }
|
||||
|
||||
---
|
||||
apiVersion: v1
|
||||
kind: Service
|
||||
metadata: { name: "{{ .Values.redis }}-master", namespace: "{{ .Values.namespace }}" }
|
||||
spec:
|
||||
selector: { app: "{{ .Values.redis }}-haproxy" }
|
||||
ports:
|
||||
- { name: redis, port: 6379, targetPort: 6379 }
|
||||
|
||||
{{- end }}
|
||||
Reference in New Issue
Block a user