Files
versitygw/chart/templates/deployment.yaml
Ben McClelland 568d4a25cc feat: add chart sidecar and versioning directory support
The Helm chart now supports dedicated sidecar metadata and versioning
directories alongside the primary data directory. For POSIX deployments,
users can configure a sidecar metadata path without forcing backend flags
through a single args string, and POSIX or ScoutFS deployments can expose
a persistent versioning directory through the chart as well.

This makes the chart usable for filesystem-backed setups that need
sidecar metadata storage or object versioning support, while keeping the
configuration aligned with the existing persistent data and IAM layout.
The chart version is bumped to reflect the new deployment behavior.

Fixes #2204
Fixes #2216
2026-07-03 14:51:20 -07:00

283 lines
11 KiB
YAML

{{- /* Safety check: multiple replicas with local state must have persistence enabled */}}
{{- if and (gt (int .Values.replicaCount) 1) (not .Values.persistence.enabled) }}
{{- if or (eq .Values.gateway.backend.type "posix") (and .Values.iam.enabled (eq .Values.iam.type "internal")) }}
{{- fail "Multiple replicas with POSIX backend or Internal IAM require persistence.enabled=true to prevent data loss and inconsistency across pods. If using a stateless backend (e.g. S3, Azure) and external IAM, set persistence.enabled=false." }}
{{- end }}
{{- end }}
{{- if and .Values.persistence.enabled (not .Values.persistence.create) (not .Values.persistence.claimName) (not .Values.persistence.hostPath) }}
{{- fail "persistence.claimName or persistence.hostPath is required when persistence.create is false" }}
{{- end }}
{{- if and .Values.persistence.claimName .Values.persistence.hostPath }}
{{- fail "only persistence.claimName or persistence.hostPath can be set" }}
{{- end }}
{{- if and .Values.persistence.create .Values.persistence.hostPath }}
{{- fail "persistence.create must be false for persistence.hostPath can be set" }}
{{- end }}
{{- if and .Values.gateway.backend.sidecarDir (ne .Values.gateway.backend.type "posix") }}
{{- fail "gateway.backend.sidecarDir is only supported with the posix backend" }}
{{- end }}
{{- if and .Values.gateway.backend.versioningDir (not (or (eq .Values.gateway.backend.type "posix") (eq .Values.gateway.backend.type "scoutfs"))) }}
{{- fail "gateway.backend.versioningDir is only supported with the posix and scoutfs backends" }}
{{- end }}
apiVersion: apps/v1
kind: Deployment
metadata:
name: {{ include "versitygw.fullname" . }}
labels:
{{- include "versitygw.labels" . | nindent 4 }}
spec:
replicas: {{ .Values.replicaCount }}
selector:
matchLabels:
{{- include "versitygw.selectorLabels" . | nindent 6 }}
{{- with .Values.strategy }}
strategy:
{{- toYaml . | nindent 4 }}
{{- end }}
template:
metadata:
annotations:
{{- if not .Values.auth.existingSecret }}
checksum/credentials: {{ cat .Release.Name .Values.auth.accessKey .Values.auth.secretKey | sha256sum | trunc 12 }}
{{- end }}
{{- with .Values.podAnnotations }}
{{- toYaml . | nindent 8 }}
{{- end }}
labels:
{{- include "versitygw.selectorLabels" . | nindent 8 }}
{{- with .Values.podLabels }}
{{- toYaml . | nindent 8 }}
{{- end }}
spec:
{{- with .Values.image.pullSecrets }}
imagePullSecrets:
{{- toYaml . | nindent 8 }}
{{- end }}
serviceAccountName: {{ include "versitygw.serviceAccountName" . }}
automountServiceAccountToken: false
securityContext:
{{- toYaml .Values.podSecurityContext | nindent 8 }}
containers:
- name: {{ .Chart.Name }}
image: "{{ .Values.image.repository }}:{{ .Values.image.tag }}"
imagePullPolicy: {{ .Values.image.pullPolicy }}
env:
# Backend selection — consumed by docker-entrypoint.sh
- name: VGW_BACKEND
value: {{ .Values.gateway.backend.type | quote }}
- name: VGW_BACKEND_ARGS
value: {{ .Values.gateway.backend.args | quote }}
{{- if .Values.gateway.backend.sidecarDir }}
- name: VGW_META_SIDECAR
value: {{ .Values.gateway.backend.sidecarDir | quote }}
{{- end }}
{{- if .Values.gateway.backend.versioningDir }}
- name: VGW_VERSIONING_DIR
value: {{ .Values.gateway.backend.versioningDir | quote }}
{{- end }}
# Root credentials — sourced from a Kubernetes Secret
- name: ROOT_ACCESS_KEY_ID
valueFrom:
secretKeyRef:
name: {{ include "versitygw.credentialsSecretName" . }}
key: rootAccessKeyId
- name: ROOT_SECRET_ACCESS_KEY
valueFrom:
secretKeyRef:
name: {{ include "versitygw.credentialsSecretName" . }}
key: rootSecretAccessKey
# Gateway server settings
- name: VGW_PORT
value: ":{{ .Values.gateway.port }}"
- name: VGW_REGION
value: {{ .Values.gateway.region | quote }}
- name: VGW_HEALTH
value: "/_/health"
{{- if .Values.gateway.virtualDomain }}
- name: VGW_VIRTUAL_DOMAIN
value: {{ .Values.gateway.virtualDomain | quote }}
{{- end }}
{{- if .Values.gateway.readOnly }}
- name: VGW_READ_ONLY
value: "true"
{{- end }}
{{- if .Values.gateway.quiet }}
- name: VGW_QUIET
value: "true"
{{- end }}
{{- if .Values.gateway.debug }}
- name: VGW_DEBUG
value: "true"
{{- end }}
{{- if .Values.gateway.accessLog }}
- name: VGW_ACCESS_LOG
value: {{ .Values.gateway.accessLog | quote }}
{{- end }}
{{- if .Values.gateway.corsAllowOrigin }}
- name: VGW_CORS_ALLOW_ORIGIN
value: {{ .Values.gateway.corsAllowOrigin | quote }}
{{- end }}
{{- if .Values.gateway.disableStrictBucketNames }}
- name: VGW_DISABLE_STRICT_BUCKET_NAMES
value: "true"
{{- end }}
# Admin API server
{{- if .Values.admin.enabled }}
- name: VGW_ADMIN_PORT
value: ":{{ .Values.admin.port }}"
- name: VGW_ADMIN_MAX_CONNECTIONS
value: {{ .Values.admin.maxConnections | quote }}
- name: VGW_ADMIN_MAX_REQUESTS
value: {{ .Values.admin.maxRequests | quote }}
{{- end }}
# WebUI
{{- if .Values.webui.enabled }}
- name: VGW_WEBUI_PORT
value: ":{{ .Values.webui.port }}"
{{- if .Values.webui.noTls }}
- name: VGW_WEBUI_NO_TLS
value: "true"
{{- end }}
{{- if .Values.webui.apiGateways }}
- name: VGW_WEBUI_GATEWAYS
value: {{ .Values.webui.apiGateways | join "," | quote }}
{{- end }}
{{- if .Values.webui.adminGateways }}
- name: VGW_WEBUI_ADMIN_GATEWAYS
value: {{ .Values.webui.adminGateways | join "," | quote }}
{{- end }}
{{- end }}
# Website Hosting
{{- if .Values.website.enabled }}
- name: VGW_WEBSITE_PORT
value: ":{{ .Values.website.port }}"
- name: VGW_WEBSITE_DOMAIN
value: {{ .Values.website.domain | quote }}
{{- if .Values.website.noTls }}
- name: VGW_WEBSITE_NO_TLS
value: "true"
{{- end }}
{{- end }}
{{- if .Values.iam.enabled }}
# IAM settings
{{- if eq .Values.iam.type "internal" }}
- name: VGW_IAM_DIR
value: "/mnt/iam"
{{- end }}
{{- if .Values.iam.cacheDisable }}
- name: VGW_IAM_CACHE_DISABLE
value: "true"
{{- end }}
- name: VGW_IAM_CACHE_TTL
value: {{ .Values.iam.cacheTtl | quote }}
- name: VGW_IAM_CACHE_PRUNE
value: {{ .Values.iam.cachePrune | quote }}
{{- if .Values.iam.debug }}
- name: VGW_IAM_DEBUG
value: "true"
{{- end }}
{{- end }}
# TLS
{{- if .Values.tls.enabled }}
- name: VGW_CERT
value: /certs/tls.crt
- name: VGW_KEY
value: /certs/tls.key
{{- end }}
# Extra user-provided environment variables
{{- with .Values.extraEnv }}
{{- toYaml . | nindent 12 }}
{{- end }}
ports:
- name: s3-api
containerPort: {{ .Values.gateway.port }}
protocol: TCP
{{- if .Values.admin.enabled }}
- name: admin
containerPort: {{ .Values.admin.port }}
protocol: TCP
{{- end }}
{{- if .Values.webui.enabled }}
- name: webui
containerPort: {{ .Values.webui.port }}
protocol: TCP
{{- end }}
{{- if .Values.website.enabled }}
- name: website
containerPort: {{ .Values.website.port }}
protocol: TCP
{{- end }}
readinessProbe:
httpGet:
path: "/_/health"
port: s3-api
initialDelaySeconds: 5
periodSeconds: 15
securityContext:
{{- toYaml .Values.securityContext | nindent 12 }}
resources:
{{- toYaml .Values.resources | nindent 12 }}
terminationMessagePolicy: FallbackToLogsOnError
volumeMounts:
- name: data
mountPath: /mnt/data
subPath: data
readOnly: false
{{- if .Values.gateway.backend.sidecarDir }}
- name: data
mountPath: {{ .Values.gateway.backend.sidecarDir }}
subPath: metadata
readOnly: false
{{- end }}
{{- if .Values.gateway.backend.versioningDir }}
- name: data
mountPath: {{ .Values.gateway.backend.versioningDir }}
subPath: versioning
readOnly: false
{{- end }}
- name: data
mountPath: /mnt/iam
subPath: iam
readOnly: false
{{- if .Values.tls.enabled }}
- name: certificates
mountPath: /certs
readOnly: true
{{- end }}
volumes:
- name: data
{{- if .Values.persistence.enabled }}
{{- if .Values.persistence.hostPath }}
hostPath:
path: {{ .Values.persistence.hostPath }}
type: DirectoryOrCreate
{{- else }}
persistentVolumeClaim:
claimName: {{ include "versitygw.pvcName" . }}
{{- end }}
{{- else }}
emptyDir: {}
{{- end }}
{{- if .Values.tls.enabled }}
- name: certificates
secret:
secretName: {{ include "versitygw.certificateSecretName" . }}
{{- end }}
{{- with .Values.nodeSelector }}
nodeSelector:
{{- toYaml . | nindent 8 }}
{{- end }}
{{- with .Values.affinity }}
affinity:
{{- toYaml . | nindent 8 }}
{{- end }}
{{- with .Values.topologySpreadConstraints }}
topologySpreadConstraints:
{{- toYaml . | nindent 8 }}
{{- end }}
{{- with .Values.tolerations }}
tolerations:
{{- toYaml . | nindent 8 }}
{{- end }}