Appearance
Offline K8s Kind Runbook
Build Local Images
bash
cd go-platform
make docker-build IMAGE_TAG=localThis builds all Go-platform service images, hoctapaz/migrator:local, and the read-only legacy parser runtime image hoctapaz/go-formula-docx:local.
Create Kind Cluster
bash
make kind-create KIND_CLUSTER=hoctapaz-goLoad Images
Before offline use, make sure base infrastructure and observability images are already available in the local Docker image cache:
bash
for image in postgres:16-alpine redis:7-alpine nats:2-alpine minio/minio:RELEASE.2024-05-10T01-41-38Z prom/prometheus:v2.53.0; do
docker pull "$image"
donebash
make kind-load-images KIND_CLUSTER=hoctapaz-go IMAGE_TAG=localkind-load-images loads all hoctapaz/<service>:<IMAGE_TAG> service images, the hoctapaz/go-formula-docx:<IMAGE_TAG> runtime image, the migrator image, and the pinned base images listed in scripts/dev/services.sh.
Deploy
bash
make k8s-deploy IMAGE_TAG=localk8s-deploy applies namespace/config/secret manifests, brings up the local Postgres Deployment, waits for it to become available, runs schema migration Jobs, then applies Redis, NATS, MinIO, gateway, service, runtime, observability, and ingress manifests. It finally updates the image tag for every deployment listed in SERVICES plus every runtime image listed in RUNTIME_IMAGES. This keeps make docker-build IMAGE_TAG=<tag>, make kind-load-images IMAGE_TAG=<tag>, and make k8s-deploy IMAGE_TAG=<tag> aligned.
The local Postgres manifest mounts postgres-init-scripts into /docker-entrypoint-initdb.d and stores data in the postgres-local-data PVC. On a brand-new PVC, the init scripts create each service database and the IAM/Profile service-owned roles used by the runtime and migration jobs.
Observability
Prometheus runs in the same namespace and scrapes every service /metrics endpoint. Inspect targets with:
bash
kubectl -n hoctapaz-go port-forward svc/prometheus 9090:9090Then open http://localhost:9090/targets.
Migrate
bash
make k8s-migrate IMAGE_TAG=localk8s-migrate runs target schema migration Jobs for every service with SQL files under services/{service}/migrations. The jobs use hoctapaz/migrator:<IMAGE_TAG>, wait for all schema Jobs to complete, and apply only target service schemas. Legacy data backfill remains separate.
Check Status
bash
make k8s-statusValidate Manifest Coverage
Before a kind deploy, verify that each locally built service image has a matching offline Deployment/Service manifest:
bash
make test-runtime-foundationEquivalent individual checks:
bash
docker compose -f deploy/docker-compose.yml config --quiet
scripts/test/service-task-pack-coverage.sh
scripts/test/service-readme-coverage.sh
scripts/test/k8s-service-coverage.sh
scripts/test/k8s-migration-job-coverage.sh
scripts/test/k8s-observability-coverage.sh
scripts/test/go-formula-runtime-coverage.sh
scripts/test/helm-render-coverage.shThe coverage check verifies:
- every service in
scripts/dev/services.shhas a K8s manifest - manifests use
hoctapaz/<service>:local - manifests use
imagePullPolicy: Never - manifests include
/healthzand/readyzprobes - every service with SQL migrations has a schema migration Job
- migration Jobs use
imagePullPolicy: Neverand the local migrator image - migration Jobs wait for completion before dependent services are deployed
- local Postgres mounts init scripts and persists data with
postgres-local-data - IAM/Profile static K8s and Helm renders use service-owned database roles
- Prometheus scrapes every service
/metricstarget - observability manifests use
imagePullPolicy: Neverand the pinned local image - Helm renders every local service image, Prometheus target, and optional schema migration Job
- Go Formula DOCX is rendered as a runtime dependency with
imagePullPolicy: Never docx-import-servicepoints athttp://go-formula-docx:8080in raw K8s and Helm
Destroy
bash
make k8s-destroy
make kind-delete KIND_CLUSTER=hoctapaz-goThe baseline uses imagePullPolicy: Never for local images and does not require a cloud registry.