Kubernetes Deployment

Ferro provides two Kubernetes deployment options: a lightweight single-manifest setup via K3s and a full Kustomize-based production deployment.

K3s (Lightweight)

Deploy

kubectl apply -f deploy/k3s/ferro.yaml

With Traefik (K3s default)

K3s ships with Traefik. Add to /etc/hosts:

127.0.0.1 ferro.local

The Ingress is pre-configured for ferro.local.

With PostgreSQL

helm repo add bitnami https://charts.bitnami.com/bitnami
helm install postgres bitnami/postgresql \
  --set auth.postgresPassword=ferro \
  --namespace ferro

Then set FERRO_DATABASE_URL in the Deployment.

Cleanup

kubectl delete -f deploy/k3s/ferro.yaml

Production (Kustomize)

Deploy base

kubectl apply -k deploy/kubernetes/base

What's included

The production deployment includes:

ResourceDescription
NamespaceDedicated ferro namespace
DeploymentFerro pods with resource limits
ServiceClusterIP service
IngressIngress with configurable class
PVCPersistent volume claim for data
SecretAdmin credentials
ConfigMapServer configuration
PDBPod disruption budget
NetworkPolicyNetwork policies (deny, DNS, external, ingress)

Network Policies

The base deployment includes restrictive network policies:

  • networkpolicy-deny.yaml -- Deny all ingress/egress by default
  • networkpolicy-dns.yaml -- Allow DNS egress
  • networkpolicy-external.yaml -- Allow external egress (for S3, OIDC, etc.)
  • networkpolicy-ingress.yaml -- Allow ingress on service ports

Helm

Install

helm install ferro deploy/helm/ferro

Custom values

helm install ferro deploy/helm/ferro \
  --set replicaCount=2 \
  --set persistence.size=10Gi \
  --set auth.adminUser=admin \
  --set auth.adminPassword=changeme \
  --set ingress.enabled=true \
  --set ingress.className=nginx

Helm chart values

ValueDefaultDescription
replicaCount1Number of replicas
persistence.enabledtrueEnable persistent volume
persistence.size5GiVolume size
ingress.enabledfalseEnable Ingress
ingress.className""Ingress class name
networkPolicy.enabledtrueEnable network policies
auth.adminUseradminAdmin username
auth.adminPassword""Admin password
image.repositoryghcr.io/wyattau/ferroContainer image
image.taglatestImage tag

Tips

  • Use PDBs to ensure availability during rolling updates
  • Network policies provide defense-in-depth
  • Set FERRO_LOG_FORMAT=json for structured logging
  • Use the Helm chart for complex deployments with custom values