Kubernetes: paldocs (k3s, Kustomize, NetworkPolicies, CNPG)

arch-k8s Architecture

architecture

Kubernetes: paldocs

How paldocs is deployed on k3s. Covers the three-repo model, Kustomize overlays, ArgoCD GitOps, and network policies.

Diagram

Components

Component Purpose Notes
pal-e-platform (Terraform) Cluster infrastructure: CNPG operator, network policies, namespaces (platform-level) Modules: database, networking, keycloak, monitoring, etc.
pal-e-services (Terraform) Per-service automation via <code>var.services</code> for_each Creates: Harbor project, robot accounts (CI push + pull), k8s namespace, ArgoCD app, Tailscale funnel. Paldocs entry: <code>port=3000, funnel=true, source_path=overlays/paldocs/prod</code>.
pal-e-deployments (Kustomize) App-level manifests: resource limits, env vars, probes, image tags Base: <code>bases/standard/</code> (deployment, service, servicemonitor). Overlay: <code>overlays/paldocs/prod/</code>.
ArgoCD + Image Updater GitOps continuous deployment Image Updater watches Harbor for tags matching <code>^[0-9a-f]{7,40}$</code> (git SHAs), writes new tag to kustomization. ArgoCD syncs with prune + self-heal.
paldocs Deployment Rails 8 / Puma container Port 3000, security context: runAsNonRoot (UID 1000), drop ALL caps, RuntimeDefault seccomp. Resources: 50m/128Mi request, 512Mi limit.
paldocs Service k8s service routing Port 3000 to 3000. No namespace in kustomization -- ArgoCD sets it.
CNPG Cluster PostgreSQL 17.4 managed by CloudNativePG operator Cluster name: <code>pal-e-postgres</code>, namespace: <code>postgres</code>. Single instance, 5Gi local-path, Barman backups to MinIO.

Key Decisions

  • No namespace in Kustomize overlays: ArgoCD controls namespace placement via the Application resource's destination.namespace. Hardcoding namespace in YAML would conflict.
  • Standard base with JSON patches: The paldocs overlay patches the generic bases/standard/ base using strategic merge and JSON patches. App name, port, and image are overridden; security context and probe patterns are inherited.
  • Default-deny network policies: Every namespace has a default-deny-ingress NetworkPolicy (managed in pal-e-platform/terraform/network-policies.tf). Paldocs namespace is already in the postgres allowlist. Must be added to keycloak allowlist for auth.
  • Env vars from k8s secrets: SECRET_KEY_BASE and PALDOCS_DATABASE_URL come from paldocs-secrets k8s secret. Keycloak env vars (KEYCLOAK_URL, KEYCLOAK_REALM, KEYCLOAK_CLIENT_ID, KEYCLOAK_CLIENT_SECRET) must be added.
  • Health probes on /up: Rails convention endpoint. Liveness: 30s initial delay, 30s period. Readiness: 5s initial delay, 10s period.
  • arch-infra -- How public traffic reaches the paldocs service
  • arch-rails-db -- Shared CNPG cluster and dual-migration pattern
  • arch-keycloak-paldocs -- Auth env vars that must be added to the deployment overlay
  • pal-e-deployments #224 -- Add KEYCLOAK env vars to paldocs overlay
  • pal-e-deployments/overlays/paldocs/prod/ -- Current overlay (deployment-patch.yaml, kustomization.yaml)
  • pal-e-deployments/bases/standard/ -- Shared Kustomize base