feat: example helm charts for zddc-server (production + dev)
Two charts under helm/, both compile zddc-server from source via an
init container — no container image registry, no pre-built binary.
The init container clones the repo at a configured git ref, runs
`go build`, and writes the binary into a shared emptyDir; the main
container is alpine + the freshly built static binary.
helm/zddc-server-prod/ Production-shaped:
- gitRef pinned to a stable tag in
values.yaml.example (zddc-server-v0.0.7).
- imagePullPolicy IfNotPresent.
- Slower probe cadence (30s liveness, 10s
readiness).
- ZDDC_LOG_LEVEL=info.
- replicaCount: 1 (operators raise as needed
when backed by a shared filesystem).
helm/zddc-server-dev/ Dev/soak-shaped:
- gitRef defaults to "main" (rebuilt every pod
restart). build-time annotation forces
recreate on every helm upgrade.
- imagePullPolicy Always on the build image
so the latest golang:1.24-alpine is pulled.
- Faster probe cadence (10s liveness, 5s
readiness) — fail-fast in dev.
- ZDDC_LOG_LEVEL=debug. NOTE: debug logs every
request's full header map (includes auth
tokens / cookies) — this chart is for
private dev namespaces only.
- Strategy: Recreate (single replica racing
on different SHAs would be a mess).
Both charts:
- Wire the ZDDC_* env-var contract (ZDDC_ROOT, ZDDC_ADDR,
ZDDC_TLS_CERT=none, ZDDC_INSECURE_DIRECT=1, ZDDC_EMAIL_HEADER,
ZDDC_CORS_ORIGIN, ZDDC_LOG_LEVEL, ZDDC_INDEX_PATH).
- Mount a caller-supplied PVC at ZDDC_ROOT (chart does not create the
PVC; operators provision storage themselves).
- Optional Ingress (ingress.enabled: true). TLS is expected to be
terminated upstream of the pod; the pod listens on plain HTTP.
- No secrets in values.yaml.example. ACL email lists go in .zddc files
inside the data volume; image-pull and TLS secrets are referenced by
name only.
helm/README.md documents the design rationale (why build from source
instead of using a registry image), a quick-start example, and the
explicit list of what the charts do and don't do.
Note: `helm lint` cannot be run in this dev environment (helm isn't
installed). YAML syntax of Chart.yaml and values.yaml.example
verified via `python3 -c "yaml.safe_load(...)"`. Operators should
run `helm lint` and `helm template` before installing.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
parent
d37ff58e11
commit
607121a9ea
13 changed files with 696 additions and 0 deletions
108
helm/README.md
Normal file
108
helm/README.md
Normal file
|
|
@ -0,0 +1,108 @@
|
||||||
|
# Helm charts
|
||||||
|
|
||||||
|
Two example charts for deploying [zddc-server](../zddc/) on Kubernetes.
|
||||||
|
Both compile zddc-server from source via an init container — no
|
||||||
|
container image needs to be pulled from a registry, and no binary needs
|
||||||
|
to be built ahead of time. The init container clones the repo at a
|
||||||
|
configured git ref and runs `go build`; the main container is plain
|
||||||
|
alpine + the freshly built static binary.
|
||||||
|
|
||||||
|
## Charts
|
||||||
|
|
||||||
|
| Chart | When to use |
|
||||||
|
|---|---|
|
||||||
|
| **`zddc-server-prod/`** | Production. Pin `zddc.gitRef` to a stable tag (`zddc-server-vX.Y.Z`). Slower probe cadence; image-pull policy `IfNotPresent`. |
|
||||||
|
| **`zddc-server-dev/`** | Development / soak. Tracks `main` by default; `helm upgrade` triggers a pod recreate so each rollout pulls the latest commit. Faster probes; debug-level logging (request headers logged — sensitive). |
|
||||||
|
|
||||||
|
The chart values are nearly identical between the two; the differences
|
||||||
|
are encoded as defaults in each chart's `values.yaml.example`.
|
||||||
|
|
||||||
|
## Quick start
|
||||||
|
|
||||||
|
```sh
|
||||||
|
# Pre-requisite: a PersistentVolumeClaim for ZDDC_ROOT data
|
||||||
|
kubectl apply -f - <<'EOF'
|
||||||
|
apiVersion: v1
|
||||||
|
kind: PersistentVolumeClaim
|
||||||
|
metadata:
|
||||||
|
name: zddc-root
|
||||||
|
spec:
|
||||||
|
accessModes: [ReadWriteMany] # or RWO if single replica is fine
|
||||||
|
resources: { requests: { storage: 100Gi } }
|
||||||
|
storageClassName: your-shared-fs # NFS, CephFS, SMB, etc.
|
||||||
|
EOF
|
||||||
|
|
||||||
|
# Production install
|
||||||
|
cp helm/zddc-server-prod/values.yaml.example my-prod-values.yaml
|
||||||
|
$EDITOR my-prod-values.yaml # set zddc.gitRef, hostnames, etc.
|
||||||
|
helm install zddc-server-prod helm/zddc-server-prod/ -f my-prod-values.yaml
|
||||||
|
|
||||||
|
# Dev install (tracks main HEAD)
|
||||||
|
cp helm/zddc-server-dev/values.yaml.example my-dev-values.yaml
|
||||||
|
$EDITOR my-dev-values.yaml
|
||||||
|
helm install zddc-server-dev helm/zddc-server-dev/ -f my-dev-values.yaml
|
||||||
|
|
||||||
|
# Trigger a rebuild from latest main HEAD (dev chart)
|
||||||
|
helm upgrade zddc-server-dev helm/zddc-server-dev/ -f my-dev-values.yaml
|
||||||
|
```
|
||||||
|
|
||||||
|
## What the chart does and doesn't do
|
||||||
|
|
||||||
|
**Does:**
|
||||||
|
|
||||||
|
- Clones the configured `zddc.gitRepo` at `zddc.gitRef` in an init
|
||||||
|
container, builds the Go binary, copies it to a shared `emptyDir`,
|
||||||
|
and starts the main container against that binary.
|
||||||
|
- Wires the `ZDDC_*` environment-variable contract (root path, addr,
|
||||||
|
email header, CORS allowlist, log level, index path).
|
||||||
|
- Mounts a caller-supplied PersistentVolumeClaim at `ZDDC_ROOT`.
|
||||||
|
- Optionally creates an Ingress (`ingress.enabled: true`).
|
||||||
|
|
||||||
|
**Does not:**
|
||||||
|
|
||||||
|
- Create the PVC. Operators provision storage themselves; the chart
|
||||||
|
only references it by name.
|
||||||
|
- Manage TLS for the pod. zddc-server runs in plain HTTP mode behind
|
||||||
|
whatever ingress / authenticating reverse proxy the cluster already
|
||||||
|
has. `ZDDC_TLS_CERT=none` and `ZDDC_INSECURE_DIRECT=1` are hardcoded
|
||||||
|
in the templates because the chart is opinionated about the
|
||||||
|
TLS-terminated-upstream deployment shape.
|
||||||
|
- Authenticate users. zddc-server reads the user's email from a header
|
||||||
|
set by the upstream proxy (`X-Auth-Request-Email` by default). The
|
||||||
|
chart does not deploy oauth2-proxy / nginx-auth-request / Pomerium /
|
||||||
|
etc. — bring your own.
|
||||||
|
- Manage secrets. `values.yaml.example` contains no secrets and never
|
||||||
|
should. ACL email lists belong in `.zddc` files inside the data
|
||||||
|
volume; image-pull credentials and TLS certs (if you enable ingress
|
||||||
|
TLS) reference Kubernetes secrets you've created separately.
|
||||||
|
|
||||||
|
## Why build from source instead of using a registry image
|
||||||
|
|
||||||
|
Three reasons:
|
||||||
|
|
||||||
|
1. **Reproducibility.** The init container's logs show exactly which
|
||||||
|
git ref was built. There's no opaque "what did I deploy" question
|
||||||
|
that a registry tag can introduce.
|
||||||
|
2. **One distribution channel.** Codeberg release-asset binaries
|
||||||
|
already exist for direct downloads; the chart compiles its own
|
||||||
|
binary from the same source git ref so there's nothing extra to
|
||||||
|
maintain (no separate image registry, no image-promotion pipeline).
|
||||||
|
3. **Smaller blast radius.** A compromised build image affects only
|
||||||
|
pods that pull during the compromise window. A compromised registry
|
||||||
|
image stays compromised across rollbacks until the digest is rotated.
|
||||||
|
|
||||||
|
The cost: every pod start takes 30-60s to clone + `go build` instead
|
||||||
|
of pulling a pre-baked image. Acceptable for both chart audiences
|
||||||
|
(production rollouts are infrequent; dev rollouts trade build time
|
||||||
|
for tracking-main convenience).
|
||||||
|
|
||||||
|
## Linting
|
||||||
|
|
||||||
|
```sh
|
||||||
|
helm lint helm/zddc-server-prod/
|
||||||
|
helm lint helm/zddc-server-dev/
|
||||||
|
|
||||||
|
# Render to inspect (uses default values from values.yaml.example):
|
||||||
|
helm template test-prod helm/zddc-server-prod/ \
|
||||||
|
--values helm/zddc-server-prod/values.yaml.example
|
||||||
|
```
|
||||||
20
helm/zddc-server-dev/Chart.yaml
Normal file
20
helm/zddc-server-dev/Chart.yaml
Normal file
|
|
@ -0,0 +1,20 @@
|
||||||
|
apiVersion: v2
|
||||||
|
name: zddc-server-dev
|
||||||
|
description: |
|
||||||
|
Development deployment of zddc-server. Same shape as zddc-server-prod
|
||||||
|
but tracks main HEAD (rebuilt on every pod restart), runs at debug
|
||||||
|
log level, has faster probe cadence for quick feedback, and uses
|
||||||
|
smaller resource limits. Intended for ephemeral / soak / preview
|
||||||
|
environments — not for production traffic.
|
||||||
|
type: application
|
||||||
|
version: 0.1.0
|
||||||
|
appVersion: "main"
|
||||||
|
home: https://zddc.varasys.io/
|
||||||
|
sources:
|
||||||
|
- https://codeberg.org/VARASYS/ZDDC
|
||||||
|
maintainers:
|
||||||
|
- name: VARASYS
|
||||||
|
keywords:
|
||||||
|
- zddc
|
||||||
|
- file-server
|
||||||
|
- development
|
||||||
31
helm/zddc-server-dev/templates/_helpers.tpl
Normal file
31
helm/zddc-server-dev/templates/_helpers.tpl
Normal file
|
|
@ -0,0 +1,31 @@
|
||||||
|
{{/*
|
||||||
|
Common labels and the fullname helper. Stays minimal; chart consumers
|
||||||
|
who want richer labels can override via metadata.labels in their
|
||||||
|
values.yaml or post-render kustomize.
|
||||||
|
*/}}
|
||||||
|
|
||||||
|
{{- define "zddc-server.name" -}}
|
||||||
|
{{- default .Chart.Name .Values.nameOverride | trunc 63 | trimSuffix "-" -}}
|
||||||
|
{{- end -}}
|
||||||
|
|
||||||
|
{{- define "zddc-server.fullname" -}}
|
||||||
|
{{- if .Values.fullnameOverride -}}
|
||||||
|
{{- .Values.fullnameOverride | trunc 63 | trimSuffix "-" -}}
|
||||||
|
{{- else -}}
|
||||||
|
{{- $name := default .Chart.Name .Values.nameOverride -}}
|
||||||
|
{{- printf "%s-%s" .Release.Name $name | trunc 63 | trimSuffix "-" -}}
|
||||||
|
{{- end -}}
|
||||||
|
{{- end -}}
|
||||||
|
|
||||||
|
{{- define "zddc-server.labels" -}}
|
||||||
|
app.kubernetes.io/name: {{ include "zddc-server.name" . }}
|
||||||
|
app.kubernetes.io/instance: {{ .Release.Name }}
|
||||||
|
app.kubernetes.io/version: {{ .Values.zddc.gitRef | quote }}
|
||||||
|
app.kubernetes.io/managed-by: {{ .Release.Service }}
|
||||||
|
helm.sh/chart: {{ printf "%s-%s" .Chart.Name .Chart.Version | replace "+" "_" }}
|
||||||
|
{{- end -}}
|
||||||
|
|
||||||
|
{{- define "zddc-server.selectorLabels" -}}
|
||||||
|
app.kubernetes.io/name: {{ include "zddc-server.name" . }}
|
||||||
|
app.kubernetes.io/instance: {{ .Release.Name }}
|
||||||
|
{{- end -}}
|
||||||
120
helm/zddc-server-dev/templates/deployment.yaml
Normal file
120
helm/zddc-server-dev/templates/deployment.yaml
Normal file
|
|
@ -0,0 +1,120 @@
|
||||||
|
apiVersion: apps/v1
|
||||||
|
kind: Deployment
|
||||||
|
metadata:
|
||||||
|
name: {{ include "zddc-server.fullname" . }}
|
||||||
|
labels:
|
||||||
|
{{- include "zddc-server.labels" . | nindent 4 }}
|
||||||
|
spec:
|
||||||
|
replicas: {{ .Values.replicaCount }}
|
||||||
|
# Dev: always re-pull the build image and re-clone source, so a kubectl
|
||||||
|
# rollout restart picks up new commits on the tracked ref.
|
||||||
|
strategy:
|
||||||
|
type: Recreate
|
||||||
|
selector:
|
||||||
|
matchLabels:
|
||||||
|
{{- include "zddc-server.selectorLabels" . | nindent 6 }}
|
||||||
|
template:
|
||||||
|
metadata:
|
||||||
|
labels:
|
||||||
|
{{- include "zddc-server.selectorLabels" . | nindent 8 }}
|
||||||
|
annotations:
|
||||||
|
# Forces pod recreation on every helm upgrade, ensuring the init
|
||||||
|
# container re-clones the tracked ref. Useful in dev where you
|
||||||
|
# want `helm upgrade` to pick up new main HEAD without changing
|
||||||
|
# values.
|
||||||
|
zddc.varasys.io/build-time: {{ now | quote }}
|
||||||
|
spec:
|
||||||
|
{{- with .Values.imagePullSecrets }}
|
||||||
|
imagePullSecrets:
|
||||||
|
{{- toYaml . | nindent 8 }}
|
||||||
|
{{- end }}
|
||||||
|
volumes:
|
||||||
|
- name: zddc-bin
|
||||||
|
emptyDir: {}
|
||||||
|
- name: data
|
||||||
|
persistentVolumeClaim:
|
||||||
|
claimName: {{ .Values.data.pvcName }}
|
||||||
|
initContainers:
|
||||||
|
- name: build-zddc-server
|
||||||
|
image: {{ printf "%s:%s" .Values.buildImage.repository .Values.buildImage.tag | quote }}
|
||||||
|
imagePullPolicy: Always
|
||||||
|
command: ["/bin/sh", "-c"]
|
||||||
|
args:
|
||||||
|
- |
|
||||||
|
set -eu
|
||||||
|
apk add --no-cache git
|
||||||
|
git clone --depth 1 --branch "$GIT_REF" "$GIT_REPO" /workspace
|
||||||
|
cd /workspace/zddc
|
||||||
|
CGO_ENABLED=0 GOOS=linux GOARCH=amd64 \
|
||||||
|
go build -trimpath \
|
||||||
|
-ldflags="-s -w -X main.version=$GIT_REF" \
|
||||||
|
-o /out/zddc-server \
|
||||||
|
./cmd/zddc-server
|
||||||
|
echo "built /out/zddc-server from $GIT_REF ($(git -C /workspace rev-parse --short HEAD))"
|
||||||
|
env:
|
||||||
|
- name: GIT_REPO
|
||||||
|
value: {{ .Values.zddc.gitRepo | quote }}
|
||||||
|
- name: GIT_REF
|
||||||
|
value: {{ .Values.zddc.gitRef | quote }}
|
||||||
|
volumeMounts:
|
||||||
|
- name: zddc-bin
|
||||||
|
mountPath: /out
|
||||||
|
resources:
|
||||||
|
requests:
|
||||||
|
cpu: 100m
|
||||||
|
memory: 128Mi
|
||||||
|
limits:
|
||||||
|
cpu: 1000m
|
||||||
|
memory: 512Mi
|
||||||
|
containers:
|
||||||
|
- name: zddc-server
|
||||||
|
image: {{ printf "%s:%s" .Values.runtimeImage.repository .Values.runtimeImage.tag | quote }}
|
||||||
|
imagePullPolicy: IfNotPresent
|
||||||
|
command: ["/zddc/zddc-server"]
|
||||||
|
ports:
|
||||||
|
- name: http
|
||||||
|
containerPort: 8080
|
||||||
|
protocol: TCP
|
||||||
|
env:
|
||||||
|
- name: ZDDC_ROOT
|
||||||
|
value: {{ .Values.zddc.env.rootPath | quote }}
|
||||||
|
- name: ZDDC_ADDR
|
||||||
|
value: {{ .Values.zddc.env.addr | quote }}
|
||||||
|
- name: ZDDC_TLS_CERT
|
||||||
|
value: "none"
|
||||||
|
- name: ZDDC_INSECURE_DIRECT
|
||||||
|
value: "1"
|
||||||
|
- name: ZDDC_EMAIL_HEADER
|
||||||
|
value: {{ .Values.zddc.env.emailHeader | quote }}
|
||||||
|
- name: ZDDC_CORS_ORIGIN
|
||||||
|
value: {{ .Values.zddc.env.corsOrigin | quote }}
|
||||||
|
- name: ZDDC_LOG_LEVEL
|
||||||
|
value: {{ .Values.zddc.env.logLevel | quote }}
|
||||||
|
- name: ZDDC_INDEX_PATH
|
||||||
|
value: {{ .Values.zddc.env.indexPath | quote }}
|
||||||
|
volumeMounts:
|
||||||
|
- name: zddc-bin
|
||||||
|
mountPath: /zddc
|
||||||
|
- name: data
|
||||||
|
mountPath: {{ .Values.zddc.env.rootPath }}
|
||||||
|
{{- with .Values.data.subPath }}
|
||||||
|
subPath: {{ . | quote }}
|
||||||
|
{{- end }}
|
||||||
|
resources:
|
||||||
|
{{- toYaml .Values.resources | nindent 12 }}
|
||||||
|
# Tighter probe cadence than prod — fail fast in dev so issues
|
||||||
|
# surface immediately during testing.
|
||||||
|
livenessProbe:
|
||||||
|
httpGet:
|
||||||
|
path: /
|
||||||
|
port: http
|
||||||
|
initialDelaySeconds: 3
|
||||||
|
periodSeconds: 10
|
||||||
|
timeoutSeconds: 3
|
||||||
|
readinessProbe:
|
||||||
|
httpGet:
|
||||||
|
path: /
|
||||||
|
port: http
|
||||||
|
initialDelaySeconds: 1
|
||||||
|
periodSeconds: 5
|
||||||
|
timeoutSeconds: 2
|
||||||
29
helm/zddc-server-dev/templates/ingress.yaml
Normal file
29
helm/zddc-server-dev/templates/ingress.yaml
Normal file
|
|
@ -0,0 +1,29 @@
|
||||||
|
{{- if .Values.ingress.enabled -}}
|
||||||
|
apiVersion: networking.k8s.io/v1
|
||||||
|
kind: Ingress
|
||||||
|
metadata:
|
||||||
|
name: {{ include "zddc-server.fullname" . }}
|
||||||
|
labels:
|
||||||
|
{{- include "zddc-server.labels" . | nindent 4 }}
|
||||||
|
spec:
|
||||||
|
{{- with .Values.ingress.className }}
|
||||||
|
ingressClassName: {{ . }}
|
||||||
|
{{- end }}
|
||||||
|
{{- if .Values.ingress.tls.enabled }}
|
||||||
|
tls:
|
||||||
|
- hosts:
|
||||||
|
- {{ .Values.ingress.host }}
|
||||||
|
secretName: {{ .Values.ingress.tls.secretName }}
|
||||||
|
{{- end }}
|
||||||
|
rules:
|
||||||
|
- host: {{ .Values.ingress.host }}
|
||||||
|
http:
|
||||||
|
paths:
|
||||||
|
- path: /
|
||||||
|
pathType: Prefix
|
||||||
|
backend:
|
||||||
|
service:
|
||||||
|
name: {{ include "zddc-server.fullname" . }}
|
||||||
|
port:
|
||||||
|
number: {{ .Values.service.port }}
|
||||||
|
{{- end }}
|
||||||
15
helm/zddc-server-dev/templates/service.yaml
Normal file
15
helm/zddc-server-dev/templates/service.yaml
Normal file
|
|
@ -0,0 +1,15 @@
|
||||||
|
apiVersion: v1
|
||||||
|
kind: Service
|
||||||
|
metadata:
|
||||||
|
name: {{ include "zddc-server.fullname" . }}
|
||||||
|
labels:
|
||||||
|
{{- include "zddc-server.labels" . | nindent 4 }}
|
||||||
|
spec:
|
||||||
|
type: {{ .Values.service.type }}
|
||||||
|
ports:
|
||||||
|
- name: http
|
||||||
|
port: {{ .Values.service.port }}
|
||||||
|
targetPort: http
|
||||||
|
protocol: TCP
|
||||||
|
selector:
|
||||||
|
{{- include "zddc-server.selectorLabels" . | nindent 4 }}
|
||||||
66
helm/zddc-server-dev/values.yaml.example
Normal file
66
helm/zddc-server-dev/values.yaml.example
Normal file
|
|
@ -0,0 +1,66 @@
|
||||||
|
# values.yaml.example — zddc-server-dev
|
||||||
|
#
|
||||||
|
# Copy to values.yaml (or pass via --values) and customize for your
|
||||||
|
# environment. Same as the prod chart's example, but defaults are
|
||||||
|
# tuned for active development:
|
||||||
|
#
|
||||||
|
# - gitRef defaults to "main" (rebuilt on every pod restart)
|
||||||
|
# - ZDDC_LOG_LEVEL=debug (every request's full header map gets logged
|
||||||
|
# — this includes auth tokens and cookies; debug builds belong in
|
||||||
|
# trusted/private namespaces only)
|
||||||
|
# - Faster liveness/readiness probes
|
||||||
|
# - Smaller resource limits (single-developer test cluster)
|
||||||
|
#
|
||||||
|
# Contains NO secrets — see helm/zddc-server-prod/values.yaml.example
|
||||||
|
# for the secrets-management note.
|
||||||
|
|
||||||
|
zddc:
|
||||||
|
gitRepo: https://codeberg.org/VARASYS/ZDDC.git
|
||||||
|
gitRef: main # tracks the latest commit; rebuilt on pod restart
|
||||||
|
|
||||||
|
env:
|
||||||
|
rootPath: /srv
|
||||||
|
addr: ":8080"
|
||||||
|
emailHeader: X-Auth-Request-Email
|
||||||
|
corsOrigin: "https://zddc.varasys.io,http://localhost:8000"
|
||||||
|
logLevel: debug # full request headers logged; sensitive!
|
||||||
|
indexPath: ".archive"
|
||||||
|
|
||||||
|
data:
|
||||||
|
pvcName: zddc-root-dev # name of an existing PVC in your dev namespace
|
||||||
|
subPath: ""
|
||||||
|
|
||||||
|
service:
|
||||||
|
type: ClusterIP
|
||||||
|
port: 8080
|
||||||
|
|
||||||
|
ingress:
|
||||||
|
enabled: false
|
||||||
|
className: ""
|
||||||
|
host: zddc-dev.example.com
|
||||||
|
tls:
|
||||||
|
enabled: false
|
||||||
|
secretName: zddc-dev-tls
|
||||||
|
|
||||||
|
# Smaller than prod — dev clusters are usually resource-constrained.
|
||||||
|
resources:
|
||||||
|
requests:
|
||||||
|
cpu: 50m
|
||||||
|
memory: 64Mi
|
||||||
|
limits:
|
||||||
|
cpu: 250m
|
||||||
|
memory: 256Mi
|
||||||
|
|
||||||
|
# Dev runs single-replica. The init container always pulls main HEAD,
|
||||||
|
# so two replicas would race on different SHAs.
|
||||||
|
replicaCount: 1
|
||||||
|
|
||||||
|
buildImage:
|
||||||
|
repository: docker.io/golang
|
||||||
|
tag: 1.24-alpine
|
||||||
|
|
||||||
|
runtimeImage:
|
||||||
|
repository: docker.io/alpine
|
||||||
|
tag: "3.19"
|
||||||
|
|
||||||
|
imagePullSecrets: []
|
||||||
20
helm/zddc-server-prod/Chart.yaml
Normal file
20
helm/zddc-server-prod/Chart.yaml
Normal file
|
|
@ -0,0 +1,20 @@
|
||||||
|
apiVersion: v2
|
||||||
|
name: zddc-server-prod
|
||||||
|
description: |
|
||||||
|
Production deployment of zddc-server. Compiles from source via an
|
||||||
|
init container at deploy time (no image pull from a registry); the
|
||||||
|
main container is alpine + the freshly-built binary. TLS is expected
|
||||||
|
to be terminated upstream (ingress / sidecar / load balancer); the
|
||||||
|
pod listens on plain HTTP and requires ZDDC_INSECURE_DIRECT=1.
|
||||||
|
type: application
|
||||||
|
version: 0.1.0
|
||||||
|
appVersion: "0.0.7" # zddc-server git tag this chart was last verified against
|
||||||
|
home: https://zddc.varasys.io/
|
||||||
|
sources:
|
||||||
|
- https://codeberg.org/VARASYS/ZDDC
|
||||||
|
maintainers:
|
||||||
|
- name: VARASYS
|
||||||
|
keywords:
|
||||||
|
- zddc
|
||||||
|
- file-server
|
||||||
|
- document-control
|
||||||
31
helm/zddc-server-prod/templates/_helpers.tpl
Normal file
31
helm/zddc-server-prod/templates/_helpers.tpl
Normal file
|
|
@ -0,0 +1,31 @@
|
||||||
|
{{/*
|
||||||
|
Common labels and the fullname helper. Stays minimal; chart consumers
|
||||||
|
who want richer labels can override via metadata.labels in their
|
||||||
|
values.yaml or post-render kustomize.
|
||||||
|
*/}}
|
||||||
|
|
||||||
|
{{- define "zddc-server.name" -}}
|
||||||
|
{{- default .Chart.Name .Values.nameOverride | trunc 63 | trimSuffix "-" -}}
|
||||||
|
{{- end -}}
|
||||||
|
|
||||||
|
{{- define "zddc-server.fullname" -}}
|
||||||
|
{{- if .Values.fullnameOverride -}}
|
||||||
|
{{- .Values.fullnameOverride | trunc 63 | trimSuffix "-" -}}
|
||||||
|
{{- else -}}
|
||||||
|
{{- $name := default .Chart.Name .Values.nameOverride -}}
|
||||||
|
{{- printf "%s-%s" .Release.Name $name | trunc 63 | trimSuffix "-" -}}
|
||||||
|
{{- end -}}
|
||||||
|
{{- end -}}
|
||||||
|
|
||||||
|
{{- define "zddc-server.labels" -}}
|
||||||
|
app.kubernetes.io/name: {{ include "zddc-server.name" . }}
|
||||||
|
app.kubernetes.io/instance: {{ .Release.Name }}
|
||||||
|
app.kubernetes.io/version: {{ .Values.zddc.gitRef | quote }}
|
||||||
|
app.kubernetes.io/managed-by: {{ .Release.Service }}
|
||||||
|
helm.sh/chart: {{ printf "%s-%s" .Chart.Name .Chart.Version | replace "+" "_" }}
|
||||||
|
{{- end -}}
|
||||||
|
|
||||||
|
{{- define "zddc-server.selectorLabels" -}}
|
||||||
|
app.kubernetes.io/name: {{ include "zddc-server.name" . }}
|
||||||
|
app.kubernetes.io/instance: {{ .Release.Name }}
|
||||||
|
{{- end -}}
|
||||||
112
helm/zddc-server-prod/templates/deployment.yaml
Normal file
112
helm/zddc-server-prod/templates/deployment.yaml
Normal file
|
|
@ -0,0 +1,112 @@
|
||||||
|
apiVersion: apps/v1
|
||||||
|
kind: Deployment
|
||||||
|
metadata:
|
||||||
|
name: {{ include "zddc-server.fullname" . }}
|
||||||
|
labels:
|
||||||
|
{{- include "zddc-server.labels" . | nindent 4 }}
|
||||||
|
spec:
|
||||||
|
replicas: {{ .Values.replicaCount }}
|
||||||
|
selector:
|
||||||
|
matchLabels:
|
||||||
|
{{- include "zddc-server.selectorLabels" . | nindent 6 }}
|
||||||
|
template:
|
||||||
|
metadata:
|
||||||
|
labels:
|
||||||
|
{{- include "zddc-server.selectorLabels" . | nindent 8 }}
|
||||||
|
spec:
|
||||||
|
{{- with .Values.imagePullSecrets }}
|
||||||
|
imagePullSecrets:
|
||||||
|
{{- toYaml . | nindent 8 }}
|
||||||
|
{{- end }}
|
||||||
|
volumes:
|
||||||
|
- name: zddc-bin
|
||||||
|
emptyDir: {}
|
||||||
|
- name: data
|
||||||
|
persistentVolumeClaim:
|
||||||
|
claimName: {{ .Values.data.pvcName }}
|
||||||
|
initContainers:
|
||||||
|
# Build zddc-server from the pinned git ref. The static binary
|
||||||
|
# lands in the shared zddc-bin volume that the main container
|
||||||
|
# mounts. No image pull from a custom registry — the build
|
||||||
|
# image is golang upstream + the runtime image is alpine.
|
||||||
|
- name: build-zddc-server
|
||||||
|
image: {{ printf "%s:%s" .Values.buildImage.repository .Values.buildImage.tag | quote }}
|
||||||
|
imagePullPolicy: IfNotPresent
|
||||||
|
command: ["/bin/sh", "-c"]
|
||||||
|
args:
|
||||||
|
- |
|
||||||
|
set -eu
|
||||||
|
apk add --no-cache git
|
||||||
|
git clone --depth 1 --branch "$GIT_REF" "$GIT_REPO" /workspace
|
||||||
|
cd /workspace/zddc
|
||||||
|
CGO_ENABLED=0 GOOS=linux GOARCH=amd64 \
|
||||||
|
go build -trimpath \
|
||||||
|
-ldflags="-s -w -X main.version=$GIT_REF" \
|
||||||
|
-o /out/zddc-server \
|
||||||
|
./cmd/zddc-server
|
||||||
|
echo "built /out/zddc-server from $GIT_REF"
|
||||||
|
env:
|
||||||
|
- name: GIT_REPO
|
||||||
|
value: {{ .Values.zddc.gitRepo | quote }}
|
||||||
|
- name: GIT_REF
|
||||||
|
value: {{ .Values.zddc.gitRef | quote }}
|
||||||
|
volumeMounts:
|
||||||
|
- name: zddc-bin
|
||||||
|
mountPath: /out
|
||||||
|
resources:
|
||||||
|
requests:
|
||||||
|
cpu: 200m
|
||||||
|
memory: 256Mi
|
||||||
|
limits:
|
||||||
|
cpu: 1000m
|
||||||
|
memory: 512Mi
|
||||||
|
containers:
|
||||||
|
- name: zddc-server
|
||||||
|
image: {{ printf "%s:%s" .Values.runtimeImage.repository .Values.runtimeImage.tag | quote }}
|
||||||
|
imagePullPolicy: IfNotPresent
|
||||||
|
command: ["/zddc/zddc-server"]
|
||||||
|
ports:
|
||||||
|
- name: http
|
||||||
|
containerPort: 8080
|
||||||
|
protocol: TCP
|
||||||
|
env:
|
||||||
|
- name: ZDDC_ROOT
|
||||||
|
value: {{ .Values.zddc.env.rootPath | quote }}
|
||||||
|
- name: ZDDC_ADDR
|
||||||
|
value: {{ .Values.zddc.env.addr | quote }}
|
||||||
|
- name: ZDDC_TLS_CERT
|
||||||
|
value: "none"
|
||||||
|
- name: ZDDC_INSECURE_DIRECT
|
||||||
|
value: "1"
|
||||||
|
- name: ZDDC_EMAIL_HEADER
|
||||||
|
value: {{ .Values.zddc.env.emailHeader | quote }}
|
||||||
|
- name: ZDDC_CORS_ORIGIN
|
||||||
|
value: {{ .Values.zddc.env.corsOrigin | quote }}
|
||||||
|
- name: ZDDC_LOG_LEVEL
|
||||||
|
value: {{ .Values.zddc.env.logLevel | quote }}
|
||||||
|
- name: ZDDC_INDEX_PATH
|
||||||
|
value: {{ .Values.zddc.env.indexPath | quote }}
|
||||||
|
volumeMounts:
|
||||||
|
- name: zddc-bin
|
||||||
|
mountPath: /zddc
|
||||||
|
- name: data
|
||||||
|
mountPath: {{ .Values.zddc.env.rootPath }}
|
||||||
|
{{- with .Values.data.subPath }}
|
||||||
|
subPath: {{ . | quote }}
|
||||||
|
{{- end }}
|
||||||
|
resources:
|
||||||
|
{{- toYaml .Values.resources | nindent 12 }}
|
||||||
|
livenessProbe:
|
||||||
|
httpGet:
|
||||||
|
path: /
|
||||||
|
port: http
|
||||||
|
initialDelaySeconds: 5
|
||||||
|
periodSeconds: 30
|
||||||
|
timeoutSeconds: 5
|
||||||
|
readinessProbe:
|
||||||
|
httpGet:
|
||||||
|
path: /
|
||||||
|
port: http
|
||||||
|
initialDelaySeconds: 2
|
||||||
|
periodSeconds: 10
|
||||||
|
timeoutSeconds: 3
|
||||||
29
helm/zddc-server-prod/templates/ingress.yaml
Normal file
29
helm/zddc-server-prod/templates/ingress.yaml
Normal file
|
|
@ -0,0 +1,29 @@
|
||||||
|
{{- if .Values.ingress.enabled -}}
|
||||||
|
apiVersion: networking.k8s.io/v1
|
||||||
|
kind: Ingress
|
||||||
|
metadata:
|
||||||
|
name: {{ include "zddc-server.fullname" . }}
|
||||||
|
labels:
|
||||||
|
{{- include "zddc-server.labels" . | nindent 4 }}
|
||||||
|
spec:
|
||||||
|
{{- with .Values.ingress.className }}
|
||||||
|
ingressClassName: {{ . }}
|
||||||
|
{{- end }}
|
||||||
|
{{- if .Values.ingress.tls.enabled }}
|
||||||
|
tls:
|
||||||
|
- hosts:
|
||||||
|
- {{ .Values.ingress.host }}
|
||||||
|
secretName: {{ .Values.ingress.tls.secretName }}
|
||||||
|
{{- end }}
|
||||||
|
rules:
|
||||||
|
- host: {{ .Values.ingress.host }}
|
||||||
|
http:
|
||||||
|
paths:
|
||||||
|
- path: /
|
||||||
|
pathType: Prefix
|
||||||
|
backend:
|
||||||
|
service:
|
||||||
|
name: {{ include "zddc-server.fullname" . }}
|
||||||
|
port:
|
||||||
|
number: {{ .Values.service.port }}
|
||||||
|
{{- end }}
|
||||||
15
helm/zddc-server-prod/templates/service.yaml
Normal file
15
helm/zddc-server-prod/templates/service.yaml
Normal file
|
|
@ -0,0 +1,15 @@
|
||||||
|
apiVersion: v1
|
||||||
|
kind: Service
|
||||||
|
metadata:
|
||||||
|
name: {{ include "zddc-server.fullname" . }}
|
||||||
|
labels:
|
||||||
|
{{- include "zddc-server.labels" . | nindent 4 }}
|
||||||
|
spec:
|
||||||
|
type: {{ .Values.service.type }}
|
||||||
|
ports:
|
||||||
|
- name: http
|
||||||
|
port: {{ .Values.service.port }}
|
||||||
|
targetPort: http
|
||||||
|
protocol: TCP
|
||||||
|
selector:
|
||||||
|
{{- include "zddc-server.selectorLabels" . | nindent 4 }}
|
||||||
100
helm/zddc-server-prod/values.yaml.example
Normal file
100
helm/zddc-server-prod/values.yaml.example
Normal file
|
|
@ -0,0 +1,100 @@
|
||||||
|
# values.yaml.example — zddc-server-prod
|
||||||
|
#
|
||||||
|
# Copy to values.yaml (or pass via --values) and customize for your
|
||||||
|
# environment. Contains NO secrets — secrets like the .zddc admin email
|
||||||
|
# list, TLS certs (if used), and image-pull credentials must be
|
||||||
|
# materialised from your secret-management system (sealed-secrets,
|
||||||
|
# external-secrets, kubectl create secret, etc.) and referenced by name
|
||||||
|
# below.
|
||||||
|
|
||||||
|
# Source-build configuration. The init container clones the repo at
|
||||||
|
# `gitRef` and compiles cmd/zddc-server. Pin gitRef to a stable tag
|
||||||
|
# (zddc-server-vX.Y.Z) for production; trying main HEAD risks pulling
|
||||||
|
# unreleased changes.
|
||||||
|
zddc:
|
||||||
|
gitRepo: https://codeberg.org/VARASYS/ZDDC.git
|
||||||
|
gitRef: zddc-server-v0.0.7 # pin to a stable tag
|
||||||
|
|
||||||
|
# ZDDC environment-variable contract — see zddc/README.md
|
||||||
|
env:
|
||||||
|
# Path inside the container where ZDDC_ROOT data is mounted.
|
||||||
|
# The chart wires the data PVC to this path automatically.
|
||||||
|
rootPath: /srv
|
||||||
|
|
||||||
|
# Listening address (plain HTTP — ingress terminates TLS).
|
||||||
|
addr: ":8080"
|
||||||
|
|
||||||
|
# Email-header convention from your authenticating reverse proxy.
|
||||||
|
emailHeader: X-Auth-Request-Email
|
||||||
|
|
||||||
|
# Comma-separated CORS allowlist. Set to your tools host, or empty
|
||||||
|
# to disable CORS entirely (when tools are same-origin).
|
||||||
|
corsOrigin: "https://zddc.varasys.io"
|
||||||
|
|
||||||
|
# info / warn / error / debug. Production stays on info; debug logs
|
||||||
|
# every request's full header map (includes cookies/auth tokens).
|
||||||
|
logLevel: info
|
||||||
|
|
||||||
|
# Index URL segment for the virtual archive index. Default fits
|
||||||
|
# most deployments; only change if you have a tracking-number
|
||||||
|
# collision with a real directory named ".archive".
|
||||||
|
indexPath: ".archive"
|
||||||
|
|
||||||
|
# Persistent storage for ZDDC_ROOT. Operators provide their own PVC,
|
||||||
|
# typically backed by a shared filesystem (NFS, CephFS, SMB) so multiple
|
||||||
|
# replicas of zddc-server (and your sync tooling) see the same tree.
|
||||||
|
# This chart does NOT create the PVC — it only references it by name.
|
||||||
|
data:
|
||||||
|
pvcName: zddc-root # name of an existing PersistentVolumeClaim
|
||||||
|
subPath: "" # optional subPath within the PVC
|
||||||
|
|
||||||
|
# Service exposure. zddc-server listens on a plain HTTP port; ingress
|
||||||
|
# (or whatever reverse proxy you put in front) terminates TLS and
|
||||||
|
# enforces authentication, then forwards to this service.
|
||||||
|
service:
|
||||||
|
type: ClusterIP
|
||||||
|
port: 8080
|
||||||
|
|
||||||
|
# Ingress is optional — disabled by default since most deployments wire
|
||||||
|
# zddc-server into an existing ingress / auth-proxy stack. Enable here
|
||||||
|
# only if this chart is the only thing in front of the pod.
|
||||||
|
ingress:
|
||||||
|
enabled: false
|
||||||
|
className: ""
|
||||||
|
host: zddc.example.com
|
||||||
|
tls:
|
||||||
|
enabled: false
|
||||||
|
secretName: zddc-tls # secret you create separately
|
||||||
|
|
||||||
|
# Pod resource limits. Sized for a small/medium archive (~10k files).
|
||||||
|
resources:
|
||||||
|
requests:
|
||||||
|
cpu: 100m
|
||||||
|
memory: 128Mi
|
||||||
|
limits:
|
||||||
|
cpu: 500m
|
||||||
|
memory: 512Mi
|
||||||
|
|
||||||
|
# Replicas. zddc-server is read-only stateless given a shared filesystem
|
||||||
|
# behind it, so multiple replicas are safe.
|
||||||
|
replicaCount: 1
|
||||||
|
|
||||||
|
# Build-stage Go image (init container). Pinned digest is recommended
|
||||||
|
# in production for reproducibility; using a tag means upstream changes
|
||||||
|
# break your deploy.
|
||||||
|
buildImage:
|
||||||
|
repository: docker.io/golang
|
||||||
|
tag: 1.24-alpine
|
||||||
|
# digest: sha256:...
|
||||||
|
|
||||||
|
# Runtime image (main container). Must contain a basic shell + libc;
|
||||||
|
# the static binary is copied in by the init container. Alpine is fine.
|
||||||
|
runtimeImage:
|
||||||
|
repository: docker.io/alpine
|
||||||
|
tag: "3.19"
|
||||||
|
# digest: sha256:...
|
||||||
|
|
||||||
|
# Image pull credentials, if your registry requires them. Reference a
|
||||||
|
# secret you've created separately; do not put credentials in values.
|
||||||
|
imagePullSecrets: []
|
||||||
|
# - name: regcred
|
||||||
Loading…
Reference in a new issue