Adds complete k8s/ manifest tree: Namespace, VaultAuth + VaultStaticSecret CRDs (VSO secret sync from Vault KV v2), API and UI Deployments and Services, nginx Ingress with cert-manager TLS, MinIO StatefulSet with PVC and init Job, and Alembic init container on the API Deployment for automatic schema migrations. Includes .yamllint.yml config and validate-k8s Makefile target. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2.9 KiB
2.9 KiB
Quickstart: Kubernetes Production Deployment
Before You Apply
-
Store API secrets in Vault at
reactbin/api/config(KV v2):DATABASE_URL = postgresql+asyncpg://reactbin:<pw>@<host>:5432/reactbin JWT_SECRET_KEY = <long-random-string> OWNER_USERNAME = <your-username> OWNER_PASSWORD = <your-password> S3_ENDPOINT_URL = http://minio.reactbin.svc.cluster.local:9000 S3_BUCKET_NAME = reactbin S3_ACCESS_KEY_ID = <same as MINIO_ROOT_USER> S3_SECRET_ACCESS_KEY = <same as MINIO_ROOT_PASSWORD> API_BASE_URL = https://<your-domain> API_DOCS_ENABLED = false -
Store MinIO credentials in Vault at
reactbin/minio/credentials(KV v2):MINIO_ROOT_USER = <choose a strong username> MINIO_ROOT_PASSWORD = <choose a strong password> -
Create a Vault Kubernetes auth role bound to the
defaultservice account in thereactbinnamespace with read access to both paths above. -
Confirm DNS resolves to the cluster ingress IP and the
letsencrypt-prodClusterIssuer exists.
Deploy
# Substitute the real image tags
sed -i 's|reactbin-api:latest|reactbin-api:v1.0.0|g' k8s/api/deployment.yaml
sed -i 's|reactbin-ui:latest|reactbin-ui:v1.0.0|g' k8s/ui/deployment.yaml
# Apply everything
kubectl apply -f k8s/
Verify
# Watch pods come up (init container runs first on the API pod)
kubectl get pods -n reactbin -w
# API health
curl -sf https://<your-domain>/api/v1/health && echo "API OK"
# UI reachable
curl -sf -o /dev/null -w "%{http_code}\n" https://<your-domain>/
# Docs correctly gated
curl -o /dev/null -w "%{http_code}\n" https://<your-domain>/docs # → 404
curl -o /dev/null -w "%{http_code}\n" https://<your-domain>/redoc # → 404
# Check migration init container ran
kubectl logs -n reactbin -l app=api -c alembic-migrate
Scenario: Migration fails on deploy
# Pod will be stuck in Init state
kubectl get pods -n reactbin
# NAME READY STATUS RESTARTS
# api-xxx-yyy 0/1 Init:CrashLoopBackOff 2
# See why
kubectl logs -n reactbin <pod-name> -c alembic-migrate
# Fix the issue (e.g. correct DATABASE_URL in Vault, wait for VSO to resync)
# Then delete the pod to force a fresh rollout
kubectl rollout restart deployment/api -n reactbin
Scenario: Update to a new image version
kubectl set image deployment/api api=reactbin-api:v1.1.0 -n reactbin
kubectl set image deployment/ui ui=reactbin-ui:v1.1.0 -n reactbin
# Kubernetes rolls out new pods; init container runs migrations before traffic switches
Scenario: Restore after MinIO pod restart
MinIO uses a PersistentVolumeClaim. Pod restarts do not affect stored data. Verify:
kubectl delete pod -n reactbin minio-0
kubectl get pods -n reactbin -w # minio-0 restarts, PVC reattaches
# Previously uploaded images should still be accessible via the API