Convention: Kustomize Overlay for Deployments

convention-kustomize-overlay Convention

active convention

Purpose

Standard pattern for deploying services from a centralized deployment repo (pal-e-deployments) using kustomize overlays with ArgoCD Image Updater write-back.

Base Structure

  • Location: pal-e-deployments/bases/standard/
  • Resources: deployment.yaml, service.yaml, hpa.yaml, servicemonitor.yaml
  • Placeholder name: app (Deployment, Service, HPA, ServiceMonitor all use name: app)
  • Placeholder image: app-image (in Deployment container)
  • Default port: 8000
  • Default probes: /healthz on port 8000
  • Default resources: 10m CPU, 32Mi mem request, 128Mi mem limit

Overlay Structure

  • Location: pal-e-deployments/overlays/{service-name}/prod/
  • Required files:
  • Optional files: service-specific resources (postgres.yaml, pvc.yaml, ingress.yaml, SOPS encrypted secrets)

Rename Pattern

JSON6902 patches in kustomization.yaml rename all base resources from app to the service name:
  • Deployment: name, selector/matchLabels, template/labels, container name
  • Service: name, labels, selector
  • HPA: name, scaleTargetRef/name
  • ServiceMonitor: name, selector/matchLabels

Customization Pattern

  • Env vars: Strategic merge patch in deployment-patch.yaml targeting metadata.name: app (BEFORE rename)
  • Port override: JSON6902 patch for containerPort (in Deployment rename patch) + Service port/targetPort
  • Strategy override: Strategic merge in deployment-patch.yaml (e.g., Recreate)
  • Resources override: Strategic merge in deployment-patch.yaml
  • Extra resources: Added to resources: list in kustomization.yaml

Image Management

  • images: transformer in kustomization.yaml
  • First entry: name: app-image, newName: harbor.../project/repo, newTag: <sha>
  • Second entry (added by Image Updater): name: harbor.../project/repo, newTag: <sha>
  • Image Updater writes newTag to overlay kustomization.yaml via write-back-target: kustomization
  • Tag format: full commit SHA matching regexp ^[0-9a-f]{7,40}$

Terraform Integration

  • source_repo and source_path optional fields in var.services (k3s.tfvars)
  • When source_repo is set, terraform automatically adds write-back-target: kustomization annotation
  • coalesce(source_repo, forgejo_repo) for repo URL, coalesce(source_path, "k8s") for path
  • Rollback: remove source_repo/source_path → ArgoCD reverts to service repo’s k8s/ directory

Migrated Services

Service Overlay Path Status
pal-e-docs overlays/pal-e-docs/prod ACTIVE
basketball-api overlays/basketball-api/prod ACTIVE
westsidekingsandqueens overlays/westsidekingsandqueens/prod ACTIVE
platform-validation (not yet migrated) PENDING
pal-e-app (not yet migrated) PENDING

Gotchas

  • Base doesn’t have newTag — Image Updater must write one or you must bootstrap manually on first deploy
  • Strategic merge on ports array adds entries instead of replacing (use JSON6902 for port changes)
  • SOPS encrypted secrets need CMP sidecar on ArgoCD repo-server for decryption
  • Terraform funnel Ingress uses tfvars key as service name — may not match k8s resource names
  • create_type=False in sa.Enum doesn’t prevent DDL events — use postgresql.ENUM for idempotent migrations