Some checks failed
ci/woodpecker/push/woodpecker Pipeline failed
- deploying.md: Add Woodpecker CI section, update constraints - releasing.md: Add automated releases via Woodpecker, Zot registry - RELEASE_CHECKLIST.md: Update build/deploy commands - CLAUDE.md: Update quick reference for automated deploys Images now at registry.threesix.ai/rdev/* instead of ghcr.io Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
216 lines
5.3 KiB
Markdown
216 lines
5.3 KiB
Markdown
# Deploying to k3s
|
|
|
|
**When to use:** Deploying rdev-api or claudebox pods to the k3s cluster.
|
|
|
|
## Prerequisites
|
|
|
|
- Access to orchard9 k3s cluster
|
|
- kubectl installed
|
|
- kubeconfig file at `~/.kube/orchard9-k3sf.yaml`
|
|
|
|
## Quick Deploy
|
|
|
|
```bash
|
|
# CRITICAL: Always set kubeconfig first
|
|
export KUBECONFIG=~/.kube/orchard9-k3sf.yaml
|
|
|
|
# Deploy all resources
|
|
kubectl apply -k deployments/k8s/base
|
|
|
|
# Verify deployment
|
|
kubectl get pods -n rdev
|
|
kubectl get svc -n rdev
|
|
```
|
|
|
|
## What Gets Deployed
|
|
|
|
The Kustomize base deploys:
|
|
|
|
| Resource | Name | Purpose |
|
|
|----------|------|---------|
|
|
| Namespace | `rdev` | Isolation |
|
|
| Deployment | `rdev-api` | API server |
|
|
| StatefulSet | `claudebox` | Claude Code pods |
|
|
| Service | `rdev-api` | Internal service |
|
|
| ServiceAccount | `rdev-api` | RBAC identity |
|
|
| Role/RoleBinding | `rdev-api` | Namespace permissions |
|
|
| ClusterRole/Binding | `rdev-api` | Cluster-wide permissions |
|
|
| PVC | `workspace-pvc` | Shared workspace volume |
|
|
| Secret | `claude-credentials` | Claude auth (manual) |
|
|
|
|
## Deployment Steps
|
|
|
|
### 1. Set Kubeconfig
|
|
|
|
```bash
|
|
export KUBECONFIG=~/.kube/orchard9-k3sf.yaml
|
|
|
|
# Verify connection
|
|
kubectl cluster-info
|
|
```
|
|
|
|
### 2. Create Secrets (First Time Only)
|
|
|
|
```bash
|
|
# Claude credentials secret
|
|
kubectl create secret generic claude-credentials \
|
|
-n rdev \
|
|
--from-file=credentials.json=/path/to/credentials.json
|
|
|
|
# Database credentials (if using external postgres)
|
|
kubectl create secret generic rdev-db \
|
|
-n rdev \
|
|
--from-literal=host=postgres.example.com \
|
|
--from-literal=password=secret
|
|
```
|
|
|
|
### 3. Apply Manifests
|
|
|
|
```bash
|
|
# Full deployment
|
|
kubectl apply -k deployments/k8s/base
|
|
|
|
# Or apply individually
|
|
kubectl apply -f deployments/k8s/base/namespace.yaml
|
|
kubectl apply -f deployments/k8s/base/rdev-api.yaml
|
|
kubectl apply -f deployments/k8s/base/claudebox.yaml
|
|
```
|
|
|
|
### 4. Verify
|
|
|
|
```bash
|
|
# Check pods
|
|
kubectl get pods -n rdev
|
|
# Expected: rdev-api-xxx Running, claudebox-0 Running
|
|
|
|
# Check logs
|
|
kubectl logs -n rdev deployment/rdev-api
|
|
|
|
# Test API
|
|
kubectl port-forward -n rdev svc/rdev-api 8080:8080
|
|
curl http://localhost:8080/health
|
|
```
|
|
|
|
## Updating Deployments
|
|
|
|
### Rolling Update
|
|
|
|
```bash
|
|
# Update image tag in manifests, then:
|
|
kubectl apply -k deployments/k8s/base
|
|
|
|
# Or force rollout
|
|
kubectl rollout restart deployment/rdev-api -n rdev
|
|
```
|
|
|
|
### Watch Rollout
|
|
|
|
```bash
|
|
kubectl rollout status deployment/rdev-api -n rdev
|
|
```
|
|
|
|
## Manifest Structure
|
|
|
|
```
|
|
deployments/k8s/
|
|
└── base/
|
|
├── kustomization.yaml # Kustomize config
|
|
├── namespace.yaml # rdev namespace
|
|
├── rdev-api.yaml # API deployment + RBAC
|
|
├── claudebox.yaml # StatefulSet for Claude pods
|
|
└── pvc-workspace.yaml # Shared workspace PVC
|
|
```
|
|
|
|
## RBAC Permissions
|
|
|
|
rdev-api requires:
|
|
- **Namespace-scoped:** Pod exec, ConfigMap read
|
|
- **Cluster-scoped:** Deployments, Services, Ingresses (for project deployment feature)
|
|
|
|
### Woodpecker CI Deployer RBAC
|
|
|
|
The `woodpecker-deployer-rbac.yaml` manifest grants Woodpecker CI permission to deploy projects. Without this, deploy steps fail with permission errors.
|
|
|
|
**Why it's needed:** Woodpecker pipeline steps run as the `default` ServiceAccount in the `threesix` namespace, but need to `kubectl set image` on deployments in the `projects` namespace.
|
|
|
|
**Permissions granted:**
|
|
- `get`, `list`, `patch` on `deployments` (apps API group)
|
|
|
|
This follows least-privilege principles - only the minimum permissions needed for `kubectl set image` to work.
|
|
|
|
## Troubleshooting
|
|
|
|
### Pod not starting
|
|
|
|
```bash
|
|
kubectl describe pod -n rdev <pod-name>
|
|
kubectl logs -n rdev <pod-name> --previous
|
|
```
|
|
|
|
### Permission denied
|
|
|
|
Check RBAC:
|
|
```bash
|
|
kubectl auth can-i exec pods -n rdev --as=system:serviceaccount:rdev:rdev-api
|
|
```
|
|
|
|
### Image pull error
|
|
|
|
Verify registry access:
|
|
```bash
|
|
kubectl get events -n rdev --sort-by='.lastTimestamp'
|
|
```
|
|
|
|
### Database connection failed
|
|
|
|
Check secret and network policy:
|
|
```bash
|
|
kubectl get secret rdev-db -n rdev -o yaml
|
|
kubectl exec -n rdev deployment/rdev-api -- env | grep DB_
|
|
```
|
|
|
|
## Automated CI/CD via Woodpecker
|
|
|
|
rdev now uses Woodpecker CI for automated builds and deploys:
|
|
|
|
```
|
|
git push → Gitea → Woodpecker → kaniko → registry.threesix.ai → kubectl deploy
|
|
```
|
|
|
|
### How It Works
|
|
|
|
1. Push to `git.threesix.ai/jordan/rdev` triggers Woodpecker
|
|
2. Woodpecker runs `.woodpecker.yml`:
|
|
- Tests with `go test ./...`
|
|
- Builds images via `woodpeckerci/plugin-kaniko`
|
|
- Pushes to `registry.threesix.ai/rdev/{api,worker,claudebox}`
|
|
- Deploys via `kubectl set image`
|
|
|
|
### Manual Deploy (if needed)
|
|
|
|
```bash
|
|
export KUBECONFIG=~/.kube/orchard9-k3sf.yaml
|
|
kubectl apply -f deployments/k8s/base/rdev-api.yaml
|
|
kubectl rollout restart -n rdev deployment/rdev-api
|
|
```
|
|
|
|
### Image Registry
|
|
|
|
Images are stored in Zot at `registry.threesix.ai/rdev/`:
|
|
- `rdev/api:latest` - API server
|
|
- `rdev/worker:latest` - Worker pool
|
|
- `rdev/claudebox:latest` - Claude Code container
|
|
|
|
## Constraints
|
|
|
|
- **ON-PREM k3s** - Not GKE/EKS, always use local kubeconfig
|
|
- **Kustomize only** - No ArgoCD or Helm
|
|
- **Woodpecker CI** - Automated builds on push to main
|
|
|
|
## Related
|
|
|
|
- [Releasing](./releasing.md) - Build and publish new versions
|
|
- [Database Guide](./database.md)
|
|
- [Kubernetes Adapter](../services/kubernetes.md)
|
|
- [External Health Diagnostics](./external-health-diagnostics.md) - Debug registry/CI/git issues
|