charts/templates/statefulset.yaml
{{- if .Values.statefulset.enabled }}
{{- $fullName := include "backend-java-patterns.fullname" . -}}
kind: StatefulSet
apiVersion: {{ template "backend-java-patterns.statefulset.apiVersion" . }}
metadata:
name: {{ $fullName }}
namespace: {{ .Release.Namespace | quote }}
labels:
{{- include "backend-java-patterns.labels" . | nindent 4 }}
{{- if .Values.statefulset.labels }}
{{- with .Values.statefulset.labels }}
{{- toYaml . | nindent 4 }}
{{- end }}
{{- end }}
spec:
serviceName: {{ $fullName }}
replicas: {{ default 1 .Values.statefulset.replicas | int64 }}
updateStrategy:
type: {{ .Values.statefulset.updateStrategy.type | quote }}
{{- if (eq "Recreate" .Values.statefulset.updateStrategy.type) }}
rollingUpdate: null
{{- else if .Values.statefulset.rollingUpdatePartition }}
rollingUpdate:
partition: {{ .Values.statefulset.rollingUpdatePartition }}
{{- end }}
{{- if .Values.statefulset.podManagementPolicy }}
podManagementPolicy: {{ .Values.statefulset.podManagementPolicy | quote }}
{{- end }}
selector:
matchLabels:
{{- include "backend-java-patterns.selectorLabels" . | nindent 6 }}
{{- if .Values.statefulset.labels }}
{{- with .Values.statefulset.labels }}
{{- toYaml . | nindent 6 }}
{{- end }}
{{- end }}
template:
metadata:
labels:
{{- include "backend-java-patterns.selectorLabels" . | nindent 6 }}
{{- if .Values.statefulset.labels }}
{{- with .Values.statefulset.labels }}
{{- toYaml . | nindent 8 }}
{{- end }}
{{- end }}
{{- if .Values.statefulset.annotations }}
{{- with .Values.statefulset.annotations }}
annotations:
{{- toYaml . | nindent 8 }}
{{- end }}
{{- end }}
spec:
{{- if .Values.hostAliases }}
hostAliases:
{{- toYaml .Values.hostAliases | nindent 8 }}
{{- end }}
{{- if .Values.schedulerName }}
schedulerName: "{{ .Values.schedulerName }}"
{{- end }}
{{- if or .Values.deployment.container.image.credentials (and .Values.tls.enabled .Values.tls.init.image.credentials (not .Values.tls.certs.provided)) }}
imagePullSecrets:
{{- if .Values.deployment.container.image.credentials }}
- name: {{ $fullName }}.db.registry
{{- end }}
{{- if and .Values.tls.enabled .Values.tls.init.image.credentials (not .Values.tls.certs.provided) }}
- name: {{ $fullName }}.init-certs.registry
{{- end }}
{{- end }}
{{- if .Values.tls.enabled }}
serviceAccountName: {{ template "backend-java-patterns.tls.serviceAccountName" . }}
{{- if .Values.securityContext.enabled }}
securityContext:
{{- toYaml .Values.securityContext.config | nindent 8 }}
{{- end }}
{{- if not .Values.tls.certs.provided }}
initContainers:
# The init-certs container sends a CSR (certificate signing request) to
# the Kubernetes cluster.
# You can see pending requests using:
# kubectl get csr
# CSRs can be approved using:
# kubectl certificate approve <csr-name>
#
# All addresses used to contact a Node must be specified in the
# `--addresses` arg.
#
# In addition to the Node certificate and key, the init-certs entrypoint
# will symlink the cluster CA to the certs directory.
- name: init-certs
image: "{{ .Values.tls.init.image.repository }}:{{ .Values.tls.init.image.tag }}"
imagePullPolicy: {{ .Values.tls.init.image.pullPolicy | quote }}
command:
- /bin/ash
- -ecx
- >-
/request-cert
-namespace=${POD_NAMESPACE}
-certs-dir=/etc/certs/
-symlink-ca-from=/var/run/secrets/kubernetes.io/serviceaccount/ca.crt
-type=node
-addresses=localhost,127.0.0.1,$(hostname -f),$(hostname -f|cut -f 1-2 -d '.'),{{ $fullName }}-public,{{ $fullName }}-public.$(hostname -f|cut -f 3- -d '.')
env:
- name: POD_NAMESPACE
valueFrom:
fieldRef:
fieldPath: metadata.namespace
volumeMounts:
- name: certs
mountPath: /etc/certs/
{{- end }}
{{- end }}
{{- if or .Values.statefulset.nodeAffinity .Values.statefulset.podAffinity .Values.statefulset.podAntiAffinity }}
affinity:
{{- with .Values.statefulset.nodeAffinity }}
nodeAffinity: {{- toYaml . | nindent 10 }}
{{- end }}
{{- with .Values.statefulset.podAffinity }}
podAffinity: {{- toYaml . | nindent 10 }}
{{- end }}
{{- if .Values.statefulset.podAntiAffinity }}
podAntiAffinity:
{{- if .Values.statefulset.podAntiAffinity.type }}
{{- if eq .Values.statefulset.podAntiAffinity.type "hard" }}
requiredDuringSchedulingIgnoredDuringExecution:
- topologyKey: kubernetes.io/hostname
labelSelector:
matchLabels:
app.kubernetes.io/name: {{ template "backend-java-patterns.name" . }}
app.kubernetes.io/instance: {{ .Release.Name | quote }}
{{- with .Values.statefulset.labels }}
{{- toYaml . | nindent 18 }}
{{- end }}
{{- else if eq .Values.statefulset.podAntiAffinity.type "soft" }}
preferredDuringSchedulingIgnoredDuringExecution:
- weight: {{ .Values.statefulset.podAntiAffinity.weight | int64 }}
podAffinityTerm:
topologyKey: kubernetes.io/hostname
labelSelector:
matchLabels:
app.kubernetes.io/name: {{ template "backend-java-patterns.name" . }}
app.kubernetes.io/instance: {{ .Release.Name | quote }}
{{- with .Values.statefulset.labels }}
{{- toYaml . | nindent 20 }}
{{- end }}
{{- end }}
{{- else }}
{{- toYaml .Values.statefulset.podAntiAffinity | nindent 10 }}
{{- end }}
{{- end }}
{{- end }}
{{- with .Values.statefulset.nodeSelector }}
nodeSelector: {{- toYaml . | nindent 8 }}
{{- end }}
{{- with .Values.statefulset.tolerations }}
tolerations: {{- toYaml . | nindent 8 }}
{{- end }}
# No pre-stop hook is required, a SIGTERM plus some time is all that's
# needed for graceful shutdown of a node.
terminationGracePeriodSeconds: 60
containers:
- name: db
image: "{{ .Values.image.repository }}:{{ .Values.image.tag }}"
imagePullPolicy: {{ .Values.image.pullPolicy | quote }}
args:
- shell
- -ecx
# The use of qualified `hostname -f` is crucial:
# Other nodes aren't able to look up the unqualified hostname.
#
# `--join` CLI flag is hardcoded to exactly 3 Pods, because:
# 1. Having `--join` value depending on `statefulset.replicas`
# will trigger undesired restart of existing Pods when
# StatefulSet is scaled up/down. We want to scale without
# restarting existing Pods.
# 2. At least one Pod in `--join` is enough to successfully
# join cluster and gossip with all other existing
# Pods, even if there are 3 or more Pods.
# 3. It's harmless for `--join` to have 3 Pods even for 1-Pod
# clusters, while it gives us opportunity to scale up even if
# some Pods of existing cluster are down (for whatever reason).
# See details explained here:
# https://github.com/helm/charts/pull/18993#issuecomment-558795102
- >-
exec /bin/bash
{{- if index .Values.conf `single-node` }}
start-single-node
{{- else }}
start --join=
{{- if .Values.conf.join }}
{{- join `,` .Values.conf.join -}}
{{- else }}
{{- range $i, $_ := until 3 -}}
{{- if gt $i 0 -}},{{- end -}}
${STATEFULSET_NAME}-{{ $i }}.${STATEFULSET_FQDN}:{{ $.Values.service.ports.grpc.internal.port | int64 -}}
{{- end -}}
{{- end }}
--advertise-host=$(hostname).${STATEFULSET_FQDN}
{{- with index .Values.conf `cluster-name` }}
--cluster-name={{ . }}
{{- if index $.Values.conf `disable-cluster-name-verification` }}
--disable-cluster-name-verification
{{- end }}
{{- end }}
{{- end }}
--logtostderr={{ .Values.conf.logtostderr }}
{{- if .Values.tls.enabled }}
--certs-dir=/etc/certs/
{{- else }}
--insecure
{{- end }}
{{- with .Values.conf.attrs }}
--attrs={{ join `:` . }}
{{- end }}
--http-port={{ index .Values.conf `http-port` | int64 }}
--port={{ .Values.conf.port | int64 }}
--cache={{ .Values.conf.cache }}
--max-disk-temp-storage={{ index .Values.conf `max-disk-temp-storage` }}
--max-offset={{ index .Values.conf `max-offset` }}
--max-sql-memory={{ index .Values.conf `max-sql-memory` }}
{{- with .Values.conf.locality }}
--locality={{ . }}
{{- end }}
{{- with index .Values.conf `sql-audit-dir` }}
--sql-audit-dir={{ . }}
{{- end }}
{{- range .Values.statefulset.args }}
{{ . }}
{{- end }}
env:
- name: STATEFULSET_NAME
value: {{ $fullName }}
- name: STATEFULSET_FQDN
value: {{ $fullName }}.{{ .Release.Namespace }}.svc.{{ .Values.clusterDomain }}
{{- with .Values.statefulset.env }}
{{- toYaml . | nindent 12 }}
{{- end }}
ports:
- name: grpc
containerPort: {{ .Values.conf.port | int64 }}
protocol: TCP
- name: http
containerPort: {{ index .Values.conf `http-port` | int64 }}
protocol: TCP
volumeMounts:
- name: datadir
mountPath: /etc/data/
{{- if or (.Files.Glob "files/conf.d/*.conf") .Values.extendedConf .Values.extendedConfConfigMap }}
- name: postgresql-extended-config
mountPath: /bitnami/postgresql/conf/conf.d/
{{- end }}
{{- if .Values.extraVolumeMounts }}
{{- toYaml .Values.extraVolumeMounts | nindent 8 }}
{{- end }}
{{- if .Values.tls.enabled }}
- name: certs
mountPath: /etc/certs/
{{- end }}
{{- range .Values.statefulset.secretMounts }}
- name: {{ printf "secret-%s" . | quote }}
mountPath: {{ printf "/etc/secrets/%s" . | quote }}
readOnly: true
{{- end }}
livenessProbe:
httpGet:
path: /health
port: http
{{- if .Values.tls.enabled }}
scheme: HTTPS
{{- end }}
initialDelaySeconds: 30
periodSeconds: 5
readinessProbe:
httpGet:
path: /health?ready=1
port: http
{{- if .Values.tls.enabled }}
scheme: HTTPS
{{- end }}
initialDelaySeconds: 10
periodSeconds: 5
failureThreshold: 2
{{- with .Values.statefulset.resources }}
resources: {{- toYaml . | nindent 12 }}
{{- end }}
volumes:
- name: datadir
{{- if .Values.persistence.enabled }}
persistentVolumeClaim:
claimName: datadir
{{- else if .Values.persistence.hostPath }}
hostPath:
path: {{ .Values.persistence.hostPath | quote }}
{{- else }}
emptyDir: {}
{{- end }}
{{- if .Values.tls.enabled }}
- name: certs
{{- if .Values.tls.certs.provided }}
{{- if .Values.tls.certs.tlsSecret }}
projected:
sources:
- secret:
name: {{ .Values.tls.certs.nodeSecret }}
items:
- key: ca.crt
path: ca.crt
mode: 0400
- key: tls.crt
path: node.crt
mode: 0400
- key: tls.key
path: node.key
mode: 0400
{{- else }}
secret:
secretName: {{ .Values.tls.certs.nodeSecret }}
defaultMode: 0400
{{- end }}
{{- else }}
emptyDir: {}
{{- end }}
{{- end }}
{{- if .Values.extraVolumes }}
{{- toYaml .Values.extraVolumes | nindent 6}}
{{- end }}
{{- range .Values.statefulset.secretMounts }}
- name: {{ printf "secret-%s" . | quote }}
secret:
secretName: {{ . | quote }}
{{- end }}
{{- if .Values.persistence.enabled }}
volumeClaimTemplates:
- metadata:
name: datadir
labels:
{{- include "backend-java-patterns.labels" . | nindent 10 }}
{{- with .Values.persistence.labels }}
{{- toYaml . | nindent 10 }}
{{- end }}
{{- with .Values.persistence.annotations }}
annotations: {{- toYaml . | nindent 10 }}
{{- end }}
spec:
accessModes:
{{- range .Values.persistence.accessModes }}
- {{ . | quote }}
{{- end }}
{{- if .Values.persistence.storageClass }}
{{- if (eq "-" .Values.persistence.storageClass) }}
storageClassName: ""
{{- else }}
storageClassName: {{ .Values.persistence.storageClass | quote}}
{{- end }}
{{- end }}
resources:
requests:
storage: {{ .Values.persistence.size | quote }}
{{- end }}
{{- end }}