# Quickstart: Kubernetes Production Deployment

## Before You Apply

1. 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
   ```

2. 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>
   ```

3. Create a Vault Kubernetes auth role bound to the `default` service account in the `reactbin` namespace with read access to both paths above.

4. Confirm DNS resolves to the cluster ingress IP and the `letsencrypt-prod` ClusterIssuer exists.

## Deploy

```bash
# 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

```bash
# 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

```bash
# 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

```bash
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:

```bash
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
```
