207 lines
6.1 KiB
Markdown
207 lines
6.1 KiB
Markdown
# Kubernetes Deployment Guide
|
|
|
|
This guide covers building the Kandev Docker image and deploying it to a Kubernetes cluster.
|
|
|
|
## Prerequisites
|
|
|
|
- Docker (for building the image)
|
|
- A container registry (Docker Hub, GHCR, ECR, etc.)
|
|
- A Kubernetes cluster with `kubectl` configured
|
|
- A StorageClass that supports `ReadWriteOnce` PVCs (for SQLite persistence)
|
|
|
|
## Building the Image
|
|
|
|
From the repository root:
|
|
|
|
```bash
|
|
# Build for your current architecture
|
|
docker build -t kandev:latest .
|
|
|
|
# Build for a specific architecture (e.g., for amd64 clusters)
|
|
docker build --platform linux/amd64 -t kandev:latest .
|
|
|
|
# Multi-arch build (requires buildx)
|
|
docker buildx build --platform linux/amd64,linux/arm64 -t kandev:latest .
|
|
```
|
|
|
|
### Using the Pre-built Image
|
|
|
|
Kandev publishes images to GitHub Container Registry. Pull directly:
|
|
|
|
```bash
|
|
docker pull ghcr.io/kdlbs/kandev:latest
|
|
```
|
|
|
|
Or reference it in your K8s deployment:
|
|
|
|
```yaml
|
|
image: ghcr.io/kdlbs/kandev:latest
|
|
```
|
|
|
|
## Deploying to Kubernetes
|
|
|
|
### Quick Start
|
|
|
|
```bash
|
|
# Apply all manifests
|
|
kubectl apply -f k8s/
|
|
|
|
# Check status
|
|
kubectl get pods -l app=kandev
|
|
kubectl logs -l app=kandev -f
|
|
```
|
|
|
|
### What Gets Created
|
|
|
|
| Resource | File | Purpose |
|
|
|----------|------|---------|
|
|
| Deployment | `deployment.yaml` | Single-replica pod running backend + web |
|
|
| Service | `service.yaml` | ClusterIP exposing port 8080 |
|
|
| ConfigMap | `configmap.yaml` | Non-sensitive environment configuration |
|
|
| PVC | `pvc.yaml` | 10Gi persistent volume for SQLite + worktrees |
|
|
| Ingress | `ingress.yaml` | Example ingress with WebSocket support |
|
|
|
|
### Accessing the UI
|
|
|
|
**Port-forward** (quickest for testing):
|
|
|
|
```bash
|
|
kubectl port-forward svc/kandev 8080:8080
|
|
# Open http://localhost:8080
|
|
```
|
|
|
|
**Ingress**: Edit `k8s/ingress.yaml` to set your domain, then apply. The ingress routes all traffic to the backend on port 8080 (the Go backend reverse-proxies the Next.js frontend internally).
|
|
|
|
### Custom Domain / Reverse Proxy
|
|
|
|
No extra configuration is needed. The frontend automatically uses `window.location.origin` to reach the API, which works with any domain, reverse proxy, or ingress setup.
|
|
|
|
## Configuration
|
|
|
|
Kandev reads configuration via `KANDEV_`-prefixed environment variables (Viper). Set these in `k8s/configmap.yaml` or as environment variables in the deployment.
|
|
|
|
### Core Settings
|
|
|
|
| Env Var | Default | Description |
|
|
|---------|---------|-------------|
|
|
| `KANDEV_SERVER_PORT` | `8080` | Server port (API + WebSocket + Web UI) |
|
|
| `KANDEV_DATA_DIR` | `/data` | Base directory for all data (DB, worktrees, sessions, etc.) |
|
|
| `KANDEV_DATABASE_DRIVER` | `sqlite` | Database driver (`sqlite` or `postgres`) |
|
|
| `KANDEV_DATABASE_PATH` | `$KANDEV_DATA_DIR/kandev.db` | SQLite database file path (override) |
|
|
| `KANDEV_DOCKER_ENABLED` | `false` | Enable Docker runtime for agents (requires DinD) |
|
|
| `KANDEV_LOG_LEVEL` | `info` | Log level: `debug`, `info`, `warn`, `error` |
|
|
| `KANDEV_LOGGING_FORMAT` | auto | Log format: `json` (auto-detected in K8s) or `text` |
|
|
|
|
### PostgreSQL Settings (when `KANDEV_DATABASE_DRIVER=postgres`)
|
|
|
|
| Env Var | Default | Description |
|
|
|---------|---------|-------------|
|
|
| `KANDEV_DATABASE_HOST` | `localhost` | PostgreSQL host |
|
|
| `KANDEV_DATABASE_PORT` | `5432` | PostgreSQL port |
|
|
| `KANDEV_DATABASE_USER` | `kandev` | Database user |
|
|
| `KANDEV_DATABASE_PASSWORD` | (empty) | Database password |
|
|
| `KANDEV_DATABASE_DBNAME` | `kandev` | Database name |
|
|
| `KANDEV_DATABASE_SSLMODE` | `disable` | SSL mode |
|
|
|
|
## Database: SQLite vs PostgreSQL
|
|
|
|
### SQLite (default)
|
|
|
|
- Zero-config, works out of the box
|
|
- Database stored at `/data/kandev.db` on the PV
|
|
- **Single replica only** (SQLite is single-writer)
|
|
- Deployment strategy is `Recreate` to prevent concurrent writes
|
|
- Good for small teams / personal use
|
|
|
|
### PostgreSQL (recommended for production)
|
|
|
|
- Supports multiple replicas for horizontal scaling
|
|
- Change deployment strategy to `RollingUpdate`
|
|
- Set via environment variables:
|
|
|
|
```yaml
|
|
# In configmap.yaml or a Secret
|
|
KANDEV_DATABASE_DRIVER: postgres
|
|
KANDEV_DATABASE_HOST: postgres.default.svc.cluster.local
|
|
KANDEV_DATABASE_PORT: "5432"
|
|
KANDEV_DATABASE_USER: kandev
|
|
KANDEV_DATABASE_PASSWORD: <from-secret>
|
|
KANDEV_DATABASE_DBNAME: kandev
|
|
```
|
|
|
|
When using Postgres, the PVC is still needed for worktree storage but the database itself is external.
|
|
|
|
## Persistent Storage
|
|
|
|
The PVC at `/data` stores:
|
|
|
|
- **SQLite database** (`/data/kandev.db`, `/data/kandev.db-wal`, `/data/kandev.db-shm`)
|
|
- **Git worktrees** (`/data/worktrees/`) for workspace isolation
|
|
|
|
The PVC uses `ReadWriteOnce` access mode. If your cluster requires a specific StorageClass, add it to `k8s/pvc.yaml`:
|
|
|
|
```yaml
|
|
spec:
|
|
storageClassName: your-storage-class
|
|
```
|
|
|
|
## Health Checks
|
|
|
|
The deployment includes both probes on the `/health` endpoint:
|
|
|
|
- **Liveness probe**: Restarts the pod if the backend becomes unresponsive (30s interval, 3 failures)
|
|
- **Readiness probe**: Removes the pod from service during startup or issues (10s interval, 3 failures)
|
|
|
|
The CLI launcher also performs an internal health check — it waits for the backend to be healthy before starting the web server.
|
|
|
|
## Scaling
|
|
|
|
**Single replica (SQLite)**: The default configuration uses `replicas: 1` with `Recreate` strategy. This ensures only one instance writes to SQLite at a time.
|
|
|
|
**Multiple replicas (PostgreSQL)**: Switch to Postgres, change the deployment strategy to `RollingUpdate`, and increase replicas:
|
|
|
|
```yaml
|
|
spec:
|
|
replicas: 3
|
|
strategy:
|
|
type: RollingUpdate
|
|
rollingUpdate:
|
|
maxSurge: 1
|
|
maxUnavailable: 0
|
|
```
|
|
|
|
## Upgrading
|
|
|
|
```bash
|
|
# Build and push new image
|
|
docker build -t your-registry.com/kandev:v1.1.0 .
|
|
docker push your-registry.com/kandev:v1.1.0
|
|
|
|
# Update deployment
|
|
kubectl set image deployment/kandev kandev=your-registry.com/kandev:v1.1.0
|
|
|
|
# Or edit the deployment directly
|
|
kubectl edit deployment kandev
|
|
```
|
|
|
|
SQLite migrations run automatically on startup — no manual migration step needed.
|
|
|
|
## Troubleshooting
|
|
|
|
```bash
|
|
# Check pod status
|
|
kubectl get pods -l app=kandev
|
|
|
|
# View logs
|
|
kubectl logs -l app=kandev -f
|
|
|
|
# Shell into the pod (if needed)
|
|
kubectl exec -it deployment/kandev -- /bin/bash
|
|
|
|
# Check PVC status
|
|
kubectl get pvc kandev-data
|
|
|
|
# Describe pod for events
|
|
kubectl describe pod -l app=kandev
|
|
```
|