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>
112 lines
3.8 KiB
YAML
112 lines
3.8 KiB
YAML
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
|