First Commit
This commit is contained in:
311
templates/statefulset.yaml
Normal file
311
templates/statefulset.yaml
Normal file
@@ -0,0 +1,311 @@
|
||||
{{- $root := . -}}
|
||||
{{- $fullname := include "redis-cluster.fullname" . -}}
|
||||
{{- if gt (len $fullname) 53 -}}
|
||||
{{- fail (printf "release fullname %q is too long; use fullnameOverride with at most 53 characters" $fullname) -}}
|
||||
{{- end -}}
|
||||
{{- if ge (int .Values.cluster.replicasPerShard) (int .Values.cluster.shards) -}}
|
||||
{{- fail "cluster.replicasPerShard must be lower than cluster.shards so crossed placement never puts a shard replica with its own primary" -}}
|
||||
{{- end -}}
|
||||
{{- $headless := include "redis-cluster.headlessFqdn" . -}}
|
||||
{{- $nodeCount := include "redis-cluster.nodeCount" . -}}
|
||||
{{- $allHosts := list -}}
|
||||
{{- $primaryHosts := list -}}
|
||||
{{- $assignments := list -}}
|
||||
{{- $addressAssignments := list -}}
|
||||
{{- range $shard := until (int .Values.cluster.shards) -}}
|
||||
{{- range $member := until (int (add (int $.Values.cluster.replicasPerShard) 1)) -}}
|
||||
{{- $memberName := printf "%s-s%d-n%d" $fullname $shard $member | trunc 63 | trimSuffix "-" -}}
|
||||
{{- $podName := printf "%s-0" $memberName -}}
|
||||
{{- $host := printf "%s-0.%s" $memberName $headless -}}
|
||||
{{- $allHosts = append $allHosts $host -}}
|
||||
{{- $addressAssignments = append $addressAssignments (printf "%s=%s" $podName $host) -}}
|
||||
{{- if eq $member 0 -}}
|
||||
{{- $primaryHosts = append $primaryHosts $host -}}
|
||||
{{- else -}}
|
||||
{{- $primaryName := printf "%s-s%d-n0" $fullname $shard | trunc 63 | trimSuffix "-" -}}
|
||||
{{- $primaryHost := printf "%s-0.%s" $primaryName $headless -}}
|
||||
{{- $assignments = append $assignments (printf "%s=%s" $host $primaryHost) -}}
|
||||
{{- end -}}
|
||||
{{- end -}}
|
||||
{{- end -}}
|
||||
{{- $coordinator := first $primaryHosts -}}
|
||||
{{- range $shard := until (int .Values.cluster.shards) }}
|
||||
{{- range $member := until (int (add (int $.Values.cluster.replicasPerShard) 1)) }}
|
||||
{{- $memberName := printf "%s-s%d-n%d" $fullname $shard $member | trunc 63 | trimSuffix "-" }}
|
||||
{{- $memberIndex := add (mul $shard (add (int $.Values.cluster.replicasPerShard) 1)) $member }}
|
||||
{{- $announceHostname := printf "%s-0.%s" $memberName $headless }}
|
||||
{{- $externalServiceName := printf "%s-x" $memberName }}
|
||||
---
|
||||
apiVersion: apps/v1
|
||||
kind: StatefulSet
|
||||
metadata:
|
||||
name: {{ $memberName }}
|
||||
namespace: {{ $.Release.Namespace }}
|
||||
labels:
|
||||
{{- include "redis-cluster.labels" $root | nindent 4 }}
|
||||
redis-cluster.shard: {{ $shard | quote }}
|
||||
redis-cluster.member: {{ $member | quote }}
|
||||
spec:
|
||||
serviceName: {{ $fullname }}-headless
|
||||
replicas: 1
|
||||
podManagementPolicy: Parallel
|
||||
# Separate one-member StatefulSets would otherwise all roll concurrently.
|
||||
# OnDelete makes upgrades explicit and safe; see README.md.
|
||||
updateStrategy:
|
||||
type: OnDelete
|
||||
selector:
|
||||
matchLabels:
|
||||
{{- include "redis-cluster.selectorLabels" $root | nindent 6 }}
|
||||
redis-cluster.shard: {{ $shard | quote }}
|
||||
redis-cluster.member: {{ $member | quote }}
|
||||
template:
|
||||
metadata:
|
||||
labels:
|
||||
{{- include "redis-cluster.selectorLabels" $root | nindent 8 }}
|
||||
redis-cluster.shard: {{ $shard | quote }}
|
||||
redis-cluster.member: {{ $member | quote }}
|
||||
{{- with $.Values.podLabels }}
|
||||
{{- toYaml . | nindent 8 }}
|
||||
{{- end }}
|
||||
annotations:
|
||||
checksum/config: {{ include (print $.Template.BasePath "/configmap.yaml") $root | sha256sum }}
|
||||
{{- if not $.Values.istio.injectSidecar }}
|
||||
sidecar.istio.io/inject: "false"
|
||||
{{- else }}
|
||||
proxy.istio.io/config: '{ "holdApplicationUntilProxyStarts": true }'
|
||||
{{- end }}
|
||||
{{- with $.Values.podAnnotations }}
|
||||
{{- toYaml . | nindent 8 }}
|
||||
{{- end }}
|
||||
spec:
|
||||
serviceAccountName: {{ include "redis-cluster.serviceAccountName" $root }}
|
||||
automountServiceAccountToken: false
|
||||
terminationGracePeriodSeconds: {{ $.Values.terminationGracePeriodSeconds }}
|
||||
{{- with $.Values.imagePullSecrets }}
|
||||
imagePullSecrets:
|
||||
{{- toYaml . | nindent 8 }}
|
||||
{{- end }}
|
||||
{{- with $.Values.priorityClassName }}
|
||||
priorityClassName: {{ . }}
|
||||
{{- end }}
|
||||
securityContext:
|
||||
{{- toYaml $.Values.podSecurityContext | nindent 8 }}
|
||||
affinity:
|
||||
{{- if gt $member 0 }}
|
||||
# Cross replicas onto the worker holding another shard's canonical
|
||||
# primary. For 3x1 this produces A:P0+R2, B:P1+R0, C:P2+R1.
|
||||
podAffinity:
|
||||
requiredDuringSchedulingIgnoredDuringExecution:
|
||||
- labelSelector:
|
||||
matchLabels:
|
||||
{{- include "redis-cluster.selectorLabels" $root | nindent 18 }}
|
||||
redis-cluster.shard: {{ mod (add $shard $member) (int $.Values.cluster.shards) | quote }}
|
||||
redis-cluster.member: "0"
|
||||
topologyKey: kubernetes.io/hostname
|
||||
{{- end }}
|
||||
podAntiAffinity:
|
||||
# Hard invariants: copies of one shard never share a worker, and
|
||||
# equivalent member identities are spread across workers. In the
|
||||
# canonical topology, this permits at most one primary per worker.
|
||||
requiredDuringSchedulingIgnoredDuringExecution:
|
||||
- labelSelector:
|
||||
matchLabels:
|
||||
{{- include "redis-cluster.selectorLabels" $root | nindent 18 }}
|
||||
redis-cluster.shard: {{ $shard | quote }}
|
||||
topologyKey: kubernetes.io/hostname
|
||||
- labelSelector:
|
||||
matchLabels:
|
||||
{{- include "redis-cluster.selectorLabels" $root | nindent 18 }}
|
||||
redis-cluster.member: {{ $member | quote }}
|
||||
topologyKey: kubernetes.io/hostname
|
||||
{{- with $.Values.nodeSelector }}
|
||||
nodeSelector:
|
||||
{{- toYaml . | nindent 8 }}
|
||||
{{- end }}
|
||||
{{- with $.Values.tolerations }}
|
||||
tolerations:
|
||||
{{- toYaml . | nindent 8 }}
|
||||
{{- end }}
|
||||
{{- with $.Values.topologySpreadConstraints }}
|
||||
topologySpreadConstraints:
|
||||
{{- toYaml . | nindent 8 }}
|
||||
{{- end }}
|
||||
{{- if $.Values.externalAccess.enabled }}
|
||||
initContainers:
|
||||
- name: discover-external-endpoint
|
||||
image: "{{ $.Values.externalAccess.endpointDiscovery.image.repository }}:{{ $.Values.externalAccess.endpointDiscovery.image.tag }}"
|
||||
imagePullPolicy: {{ $.Values.externalAccess.endpointDiscovery.image.pullPolicy }}
|
||||
command: ["/bin/sh", "/scripts/discover-external-endpoint.sh"]
|
||||
securityContext:
|
||||
{{- toYaml $.Values.containerSecurityContext | nindent 12 }}
|
||||
env:
|
||||
- name: POD_NAMESPACE
|
||||
valueFrom:
|
||||
fieldRef:
|
||||
fieldPath: metadata.namespace
|
||||
- name: EXTERNAL_SERVICE_NAME
|
||||
value: {{ $externalServiceName | quote }}
|
||||
resources:
|
||||
{{- toYaml $.Values.externalAccess.endpointDiscovery.resources | nindent 12 }}
|
||||
volumeMounts:
|
||||
- name: scripts
|
||||
mountPath: /scripts
|
||||
- name: external-endpoint
|
||||
mountPath: /external-endpoint
|
||||
- name: kube-api-access
|
||||
mountPath: /var/run/secrets/kubernetes.io/serviceaccount
|
||||
readOnly: true
|
||||
{{- end }}
|
||||
containers:
|
||||
- name: redis
|
||||
image: "{{ $.Values.image.repository }}:{{ $.Values.image.tag }}"
|
||||
imagePullPolicy: {{ $.Values.image.pullPolicy }}
|
||||
command: ["/bin/sh", "/scripts/start-redis.sh"]
|
||||
securityContext:
|
||||
{{- toYaml $.Values.containerSecurityContext | nindent 12 }}
|
||||
env:
|
||||
{{- include "redis-cluster.commonEnv" $root | nindent 12 }}
|
||||
- name: COORDINATOR_HOST
|
||||
value: {{ $coordinator | quote }}
|
||||
- name: ALL_NODE_HOSTS
|
||||
value: {{ join "," $allHosts | quote }}
|
||||
- name: PRIMARY_HOSTS
|
||||
value: {{ join "," $primaryHosts | quote }}
|
||||
- name: REPLICA_ASSIGNMENTS
|
||||
value: {{ join "," $assignments | quote }}
|
||||
- name: NODE_ADDRESS_ASSIGNMENTS
|
||||
value: {{ join "," $addressAssignments | quote }}
|
||||
- name: ANNOUNCE_HOSTNAME
|
||||
value: {{ $announceHostname | quote }}
|
||||
- name: ANNOUNCE_PORT
|
||||
value: {{ ternary $.Values.externalAccess.port $.Values.redis.port $.Values.externalAccess.enabled | quote }}
|
||||
- name: EXTERNAL_ACCESS_ENABLED
|
||||
value: {{ $.Values.externalAccess.enabled | quote }}
|
||||
ports:
|
||||
- name: tcp-redis
|
||||
containerPort: {{ $.Values.redis.port }}
|
||||
- name: tcp-cluster
|
||||
containerPort: {{ $.Values.cluster.busPort }}
|
||||
startupProbe:
|
||||
exec:
|
||||
command: ["/bin/sh", "/scripts/startup-redis.sh"]
|
||||
initialDelaySeconds: {{ $.Values.probes.redis.startup.initialDelaySeconds }}
|
||||
periodSeconds: {{ $.Values.probes.redis.startup.periodSeconds }}
|
||||
timeoutSeconds: {{ $.Values.probes.redis.startup.timeoutSeconds }}
|
||||
failureThreshold: {{ $.Values.probes.redis.startup.failureThreshold }}
|
||||
livenessProbe:
|
||||
exec:
|
||||
command: ["/bin/sh", "/scripts/liveness-redis.sh"]
|
||||
periodSeconds: {{ $.Values.probes.redis.liveness.periodSeconds }}
|
||||
timeoutSeconds: {{ $.Values.probes.redis.liveness.timeoutSeconds }}
|
||||
failureThreshold: {{ $.Values.probes.redis.liveness.failureThreshold }}
|
||||
readinessProbe:
|
||||
exec:
|
||||
command: ["/bin/sh", "/scripts/readiness-redis.sh"]
|
||||
periodSeconds: {{ $.Values.probes.redis.readiness.periodSeconds }}
|
||||
timeoutSeconds: {{ $.Values.probes.redis.readiness.timeoutSeconds }}
|
||||
failureThreshold: {{ $.Values.probes.redis.readiness.failureThreshold }}
|
||||
lifecycle:
|
||||
preStop:
|
||||
exec:
|
||||
command: ["/bin/sh", "/scripts/prestop-redis.sh"]
|
||||
resources:
|
||||
{{- toYaml $.Values.redis.resources | nindent 12 }}
|
||||
volumeMounts:
|
||||
- name: data
|
||||
mountPath: /data
|
||||
- name: scripts
|
||||
mountPath: /scripts
|
||||
- name: config
|
||||
mountPath: /etc/redis-ro
|
||||
- name: redis-runtime
|
||||
mountPath: /etc/redis-runtime
|
||||
{{- if $.Values.externalAccess.enabled }}
|
||||
- name: external-endpoint
|
||||
mountPath: /external-endpoint
|
||||
readOnly: true
|
||||
{{- end }}
|
||||
{{- if $.Values.metrics.enabled }}
|
||||
- name: metrics
|
||||
image: "{{ $.Values.metrics.image.repository }}:{{ $.Values.metrics.image.tag }}"
|
||||
imagePullPolicy: {{ $.Values.metrics.image.pullPolicy }}
|
||||
securityContext:
|
||||
{{- toYaml $.Values.containerSecurityContext | nindent 12 }}
|
||||
env:
|
||||
- name: REDIS_ADDR
|
||||
value: "redis://localhost:{{ $.Values.redis.port }}"
|
||||
{{- if $.Values.auth.enabled }}
|
||||
- name: REDIS_PASSWORD
|
||||
valueFrom:
|
||||
secretKeyRef:
|
||||
name: {{ include "redis-cluster.secretName" $root }}
|
||||
key: {{ include "redis-cluster.secretKey" $root }}
|
||||
{{- end }}
|
||||
ports:
|
||||
- name: http-metrics
|
||||
containerPort: {{ $.Values.metrics.port }}
|
||||
livenessProbe:
|
||||
tcpSocket:
|
||||
port: http-metrics
|
||||
initialDelaySeconds: 10
|
||||
periodSeconds: 15
|
||||
readinessProbe:
|
||||
tcpSocket:
|
||||
port: http-metrics
|
||||
periodSeconds: 15
|
||||
resources:
|
||||
{{- toYaml $.Values.metrics.resources | nindent 12 }}
|
||||
{{- end }}
|
||||
volumes:
|
||||
- name: scripts
|
||||
configMap:
|
||||
name: {{ $fullname }}
|
||||
defaultMode: 0555
|
||||
- name: config
|
||||
configMap:
|
||||
name: {{ $fullname }}
|
||||
items:
|
||||
- key: redis.conf
|
||||
path: redis.conf
|
||||
- name: redis-runtime
|
||||
emptyDir: {}
|
||||
{{- if $.Values.externalAccess.enabled }}
|
||||
- name: external-endpoint
|
||||
emptyDir: {}
|
||||
- name: kube-api-access
|
||||
projected:
|
||||
defaultMode: 0444
|
||||
sources:
|
||||
- serviceAccountToken:
|
||||
path: token
|
||||
expirationSeconds: 3600
|
||||
- configMap:
|
||||
name: kube-root-ca.crt
|
||||
items:
|
||||
- key: ca.crt
|
||||
path: ca.crt
|
||||
{{- end }}
|
||||
{{- if not $.Values.persistence.enabled }}
|
||||
- name: data
|
||||
emptyDir: {}
|
||||
{{- end }}
|
||||
{{- if $.Values.persistence.enabled }}
|
||||
volumeClaimTemplates:
|
||||
- metadata:
|
||||
name: data
|
||||
{{- with $.Values.persistence.annotations }}
|
||||
annotations:
|
||||
{{- toYaml . | nindent 10 }}
|
||||
{{- end }}
|
||||
spec:
|
||||
accessModes:
|
||||
{{- toYaml $.Values.persistence.accessModes | nindent 10 }}
|
||||
{{- with $.Values.persistence.storageClass }}
|
||||
storageClassName: {{ . | quote }}
|
||||
{{- end }}
|
||||
resources:
|
||||
requests:
|
||||
storage: {{ $.Values.persistence.size }}
|
||||
{{- end }}
|
||||
{{- end }}
|
||||
{{- end }}
|
||||
Reference in New Issue
Block a user