Self-hosted Kubernetes platform
A highly available k3s platform for internal applications, with load-balanced ingress, TLS, and push-to-deploy CI/CD.
Problem
Internal applications, such as the production floor dashboard, needed a place to run. That platform had to keep serving if a load balancer went down, handle HTTPS cleanly, and ship new versions from a git push instead of by hand.
Approach
- Separate roles. A k3s cluster with a dedicated control plane and separate worker nodes, so cluster management and application workloads don't compete for the same machine.
- No single front door. Nginx load balancers sit in front of the cluster, with keepalived managing a shared virtual IP. Clients only ever see the VIP. If the active balancer fails, the standby takes the address over.
- One ingress. Traefik is the ingress controller, routing requests to the right service, with TLS termination for HTTPS.
- Push to deploy. GitHub Actions workflows run on self-hosted runners. A push builds the container image, publishes it to GitHub Container Registry, and rolls it out to the cluster.
- git pushapp repo
- GitHub Actionsworkflow triggers
- Self-hosted runnerbuilds the image
- GHCRstores the image
- k3srolls it out
Stack
Outcome
Internal applications, including the production floor dashboard, run on a platform with no single load balancer as a point of failure. Shipping a change is a git push: the pipeline handles the build, the registry, and the rollout.