Manifests & Helm¶
This page covers the cluster node reference and manual kubectl / helm escape hatches.
For the canonical GitOps workflow - how services are deployed, updated, and reconciled - see
gitops-flux.md and new-service.md.
Cluster Overview¶
| Node | Local IP | Tailscale IP | Role |
|---|---|---|---|
| k3s-server | control-plane | ||
| k3s-agent-1 | worker | ||
| k3s-agent-2 | worker |
k3s version: v1.34.5+k3s1
Flannel networking: Flannel uses Tailscale IPs as the overlay backend - see flannel-over-tailscale.md for details.
Installed components¶
| Component | Namespace | How installed |
|---|---|---|
| Traefik (ingress) | kube-system |
k3s built-in |
| MetalLB | metallb-system |
Flux GitOps (HelmRelease + Kustomization) |
| CloudNativePG operator | cnpg-system |
Flux GitOps (HelmRelease) |
| Tailscale operator | tailscale |
Flux GitOps (HelmRelease) |
| cert-manager | cert-manager |
Flux GitOps (HelmRelease) |
| Longhorn | longhorn-system |
Flux GitOps (HelmRelease) |
| Authentik | authentik |
Flux GitOps (HelmRelease) |
Manual Deployment (Escape Hatches)¶
Normal deployments go through Flux GitOps (commit → push → reconcile). The following manual methods are available for bootstrapping, one-off operations, or debugging - not for day-to-day service management.
kubectl apply - one-off manifest¶
# Apply a single manifest file directly (bypasses Flux)
kubectl apply -f k3s/manifests/myapp/deployment.yaml
# Apply a whole directory
kubectl apply -f k3s/manifests/myapp/
Use kubectl patch for secrets, not kubectl apply
Flux uses Server-Side Apply (SSA). Running kubectl apply on a resource that Flux
already owns will cause field-manager conflicts. For secrets in particular, always use
kubectl patch --type=merge. See gitops-flux.md.
GitHub Actions - k3s Manifests workflow¶
Use the k3s - Deploy Manifests workflow dispatch for operations outside normal GitOps (e.g., applying a manifest on a feature branch or force-deleting resources):
- Go to Actions → k3s - Deploy Manifests → Run workflow.
- Set action to
applyordelete. - Set manifest_path to a file or directory relative to
k3s/manifests/. - Set target_host (defaults to
k3s-server).
Helm (manual install)¶
Use manual helm install only for bootstrapping or debugging. For production services,
use a HelmRelease in k3s/flux/apps/ so Flux manages lifecycle.
# Add a repo
helm repo add my-repo https://charts.example.com
helm repo update
# Install
helm install my-release my-repo/my-chart \
--namespace my-namespace \
--create-namespace \
--values my-values.yaml
# Upgrade
helm upgrade my-release my-repo/my-chart --values my-values.yaml
# Uninstall
helm uninstall my-release -n my-namespace
Tailscale Operator¶
Full documentation: see tailscale-operator.md for the complete guide covering OAuth credential management, all three exposure methods (annotated Service, LoadBalancer, Tailscale Ingress), the
prodProxyClass, proxy naming, and troubleshooting.
The Tailscale operator runs in the tailscale namespace, deployed via Flux using the
official Helm chart (tailscale-operator v1.94.2 from https://pkgs.tailscale.com/helmcharts).
It provisions proxy StatefulSets that join the your-tailnet tailnet on behalf of
your Services and Ingresses.
Quick reference¶
# Expose a ClusterIP Service
metadata:
annotations:
tailscale.com/expose: "true"
tailscale.com/hostname: "my-service"
tailscale.com/proxy-class: "prod"
# Tailscale Ingress (HTTP - recommended for web services)
spec:
ingressClassName: tailscale
tls:
- hosts:
- my-service # becomes my-service.tailnet.ts.net
MetalLB Configuration¶
The MetalLB IP address pool and L2 advertisement are managed as a Flux Kustomization
pointing at k3s/manifests/metallb-config/. To change the IP range, edit the addresses
field and push to main. Flux applies the change automatically.