---
name: k8s-manifests
description: Use when creating or modifying Kubernetes manifests (Deployment, Service, migration Job) or nginx configuration. Describes namespace convention, ConfigMap/Secret pattern, service deployment pattern, migration Job lifecycle settings, and nginx reverse proxy routing rules. Load from Solution Spec Writer, Execution Planner, and Implementation agents whenever a feature involves deployment or infrastructure work.
---

# Kubernetes Manifests

Applies to files under `k8s/{infrastructure|migrations|services}/` and the nginx ingress ConfigMap.

## Namespace

All application resources live in a single project-scoped namespace, typically named after the project (lowercase).

## Shared Config

- **ConfigMap** `{project}-config` — host/port for SQL Server and RabbitMQ, non-secret environment vars
- **Secret** `{project}-secrets` — DB passwords, API keys, other credentials
- Connection strings assembled from ConfigMap values in each service's environment

## Service Deployment Pattern

Each API service gets a Deployment + Service pair under `k8s/services/`.
See `references/templates.md` for the full YAML.

## Migration Jobs

Schema migrations run as K8S Jobs (not Deployments) under `k8s/migrations/`:

- `restartPolicy: Never` and `backoffLimit: 3`
- `activeDeadlineSeconds: 300` — prevents a hung Job from blocking deployments indefinitely
- `ttlSecondsAfterFinished: 600` — auto-cleans completed/failed Jobs after 10 minutes
- Dedicated image per service (e.g. `{project}-{service}-migrations`)

**Database creation:** SQL Server does NOT auto-create the application database. Every migration Job must include an `initContainers` entry that waits for SQL Server readiness and creates the database if it does not exist. See `references/templates.md` for the full YAML.

## Nginx Reverse Proxy (Not a K8S Ingress Controller)

The nginx ingress is a plain `nginx:alpine` reverse proxy (NOT a k8s Ingress Controller).
Each service gets an `upstream` block and a `location` block in the nginx ConfigMap:

```nginx
upstream {service}_api {
    server {service}-api:{port};
}

location /api/{service} {
    proxy_pass http://{service}_api/api/{service};
    proxy_set_header Host $host;
    proxy_set_header X-Real-IP $remote_addr;
    proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
    add_header Cache-Control "no-cache, no-store, must-revalidate" always;
    add_header Pragma "no-cache" always;
}
```

No trailing slashes on `location` paths or `proxy_pass` URIs.