apiVersion: apps/v1 kind: StatefulSet metadata: name: {{ .Release.Name }}-{{ .Chart.Name }}-sfs labels: app: {{ .Release.Name }}-{{ .Chart.Name }}-sfs spec: replicas: {{ include "voucher-vault.replicas" (dict "scaleDown" .Values.scaleDown "replicas" .Values.voucherVault.replicas) }} serviceName: {{ .Release.Name }}-{{ .Chart.Name }}-service selector: matchLabels: app: {{ .Release.Name }}-{{ .Chart.Name }}-sfs template: metadata: name: {{ .Release.Name }}-{{ .Chart.Name }}-sfs labels: app: {{ .Release.Name }}-{{ .Chart.Name }}-sfs spec: automountServiceAccountToken: false securityContext: {{- include "voucher-vault.podSecurityContext" .Values.voucherVault.securityContext | nindent 8 }} initContainers: # STATIC_ROOT (/opt/app/myapp/static) doubles as the app's own static # source directory, so it cannot simply be shadowed by an empty # volume: this init container seeds the static-files emptyDir with # the assets shipped in the image (cp -a preserves timestamps, so the # entrypoint's collectstatic only adds what is missing, e.g. the # Django admin static files). See securityContext in values.yaml. - name: init-static image: "docker.io/l4rm4nd/vouchervault:{{ .Chart.AppVersion }}" imagePullPolicy: IfNotPresent # Copies the children (not ".") so cp never tries to set metadata # on the mountpoint itself, which the non-root uid may not own. command: ["sh", "-c", "cp -a /opt/app/myapp/static/* /static-seed/"] securityContext: {{- include "voucher-vault.containerSecurityContext" .Values.voucherVault.securityContext | nindent 12 }} volumeMounts: - name: static-files mountPath: /static-seed resources: requests: cpu: 10m memory: 16Mi ephemeral-storage: 1Mi limits: cpu: 200m memory: 64Mi ephemeral-storage: 10Mi containers: - name: {{ .Release.Name }}-{{ .Chart.Name }}-sfs image: "docker.io/l4rm4nd/vouchervault:{{ .Chart.AppVersion }}" imagePullPolicy: IfNotPresent env: {{- range $value := .Values.voucherVault.env }} {{- if $value.value }} - name: {{ $value.name | quote }} value: {{ tpl $value.value $ | quote }} {{- else if $value.valueFrom }} {{- if $value.valueFrom.secretKeyRef }} - name: {{ $value.name }} valueFrom: secretKeyRef: name: {{ tpl $value.valueFrom.secretKeyRef.name $ | quote }} key: {{ tpl $value.valueFrom.secretKeyRef.key $ | quote }} {{- else if $value.valueFrom.configMapKeyRef }} - name: {{ $value.name }} valueFrom: configMapKeyRef: name: {{ tpl $value.valueFrom.configMapKeyRef.name $ | quote }} key: {{ tpl $value.valueFrom.configMapKeyRef.key $ | quote }} {{- end }} {{- end }} {{- end }} ports: {{- toYaml .Values.voucherVault.ports | nindent 12 }} # No "if" guards here any more: an erased probe block used to omit the # probe entirely and silently. It now falls back to the chart # defaults (#99), so the workload keeps its probes. livenessProbe: {{- include "voucher-vault.livenessProbe" .Values.voucherVault.livenessProbe | nindent 12 }} readinessProbe: {{- include "voucher-vault.readinessProbe" .Values.voucherVault.readinessProbe | nindent 12 }} startupProbe: {{- include "voucher-vault.startupProbe" .Values.voucherVault.startupProbe | nindent 12 }} resources: {{- include "voucher-vault.effectiveResources" .Values.voucherVault.resources | nindent 12 }} securityContext: {{- include "voucher-vault.containerSecurityContext" .Values.voucherVault.securityContext | nindent 12 }} volumeMounts: # Writable emptyDirs over the paths the image writes at runtime, # so the root filesystem can stay read-only (see securityContext # in values.yaml). - name: tmp mountPath: /tmp - name: logs mountPath: /opt/app/logs - name: static-files mountPath: /opt/app/myapp/static {{- range $value := .Values.voucherVault.storage.volumeMounts }} - name: {{ tpl $value.name $ | quote }} mountPath: {{ tpl $value.mountPath $ | quote }} {{- if $value.subPath }} subPath: {{ tpl $value.subPath $ | quote }} {{- end }} {{- if $value.subPathExpr }} subPathExpr: {{ tpl $value.subPathExpr $ | quote }} {{- end }} {{- if $value.readOnly }} readOnly: {{ tpl $value.readOnly $ | quote }} {{- end }} {{- end }} restartPolicy: Always volumes: # Writable emptyDirs backing the read-only root filesystem (see # securityContext in values.yaml). - name: tmp emptyDir: {} - name: logs emptyDir: {} - name: static-files emptyDir: {} {{- range $value := .Values.voucherVault.storage.volumes }} - name: {{ tpl $value.name $ | quote }} {{- if $value.persistentVolumeClaim }} persistentVolumeClaim: claimName: {{ tpl $value.persistentVolumeClaim.claimName $ | quote }} {{- if $value.persistentVolumeClaim.readOnly }} readOnly: {{ tpl $value.persistentVolumeClaim.readOnly $ | quote }} {{- end }} {{- else if $value.configMap }} configMap: name: {{ tpl $value.configMap.name $ | quote }} {{- if $value.configMap.defaultMode }} defaultMode: {{ tpl $value.configMap.defaultMode $ | quote }} {{- end }} {{- else if $value.secret }} secret: secretName: {{ tpl $value.secret.secretName $ | quote }} {{- if $value.secret.defaultMode }} defaultMode: {{ tpl $value.secret.defaultMode $ | quote }} {{- end }} {{- if $value.secret.optional }} optional: {{ tpl $value.secret.optional $ | quote }} {{- end }} {{- if $value.secret.items }} items: {{ range $item := $value.secret.items }} - key: {{ tpl $item.key $ | quote }} {{- if $item.path }} path: {{ tpl $item.path $ | quote }} {{- end }} {{- if $item.mode }} mode: {{ tpl $item.mode $ | quote }} {{- end }} {{- end }} {{- end }} {{- else if $value.emptyDir }} emptyDir: {{- if $value.emptyDir.medium }} medium: {{ tpl $value.emptyDir.medium $ | quote }} {{- end }} {{- if $value.emptyDir.sizeLimit }} sizeLimit: {{ tpl $value.emptyDir.sizeLimit $ | quote }} {{- end }} {{- end }} {{- end }}