Kubernetes HA with kube-vip as API Server Load Balancer (AlmaLinux 10.1)
Share the post "Kubernetes HA with kube-vip as API Server Load Balancer (AlmaLinux 10.1)"

If you’re running a multi-master Kubernetes cluster, having a highly available control plane endpoint is critical. In this guide, I’ll walk through how to use kube-vip as a lightweight, ARP-based load balancer for the Kubernetes API server.
Cluster Overview
We are running a 3-node control plane:
| Node | Role | IP Address |
|---|---|---|
| master-01 | control-plane | 192.168.20.81 |
| master-02 | control-plane | 192.168.20.82 |
| master-03 | control-plane | 192.168.20.83 |
- OS: AlmaLinux 10.1
- Kubernetes: v1.35.2
- Container Runtime: containerd
- Virtual IP (VIP): 192.168.20.80
What is kube-vip?
kube-vip provides a virtual IP (VIP) that floats between control-plane nodes using leader election.
👉 It ensures:
- A single stable endpoint for the API server
- Automatic failover if a master node goes down
- No need for external load balancers
How kube-vip Works
- kube-vip runs as a static pod on each control-plane node
- One node becomes the leader via Kubernetes leader election
- The leader:
- Owns the VIP (
192.168.20.80) - Responds to ARP requests
- Owns the VIP (
- If the leader fails:
- Another node takes over the VIP automatically
Architecture Flow
kubectl / clients
↓
192.168.20.80 (VIP)
↓
Active kube-vip leader node
↓
Local kube-apiserver (6443)
kubeadm Configuration
Your kubeadm-config.yaml defines the VIP as the control plane endpoint:
apiVersion: kubeadm.k8s.io/v1beta4
kind: ClusterConfiguration
kubernetesVersion: stable
controlPlaneEndpoint: "192.168.20.80:6443"
networking:
podSubnet: "10.244.0.0/16"
apiServer:
certSANs:
- "192.168.20.80"
- "192.168.20.81"
- "192.168.20.82"
- "192.168.20.83"
✅ Important: The VIP must be included in certSANs.
kube-vip Static Pod Manifest
Place this file on each control-plane node:
sudo tee /etc/kubernetes/manifests/kube-vip.yaml << 'EOF'
apiVersion: v1
kind: Pod
metadata:
name: kube-vip
namespace: kube-system
spec:
hostNetwork: true
containers:
- name: kube-vip
image: ghcr.io/kube-vip/kube-vip:v0.8.0
imagePullPolicy: IfNotPresent
args:
- manager
env:
- name: vip_arp
value: "true"
- name: port
value: "6443"
- name: vip_interface
value: "ens33"
- name: cp_enable
value: "true"
- name: cp_namespace
value: "kube-system"
- name: vip_ddns
value: "false"
- name: svc_enable
value: "false"
- name: vip_leaderelection
value: "true"
- name: vip_leaseduration
value: "5"
- name: vip_renewdeadline
value: "3"
- name: vip_retryperiod
value: "1"
- name: address
value: "192.168.20.80"
- name: kubernetes_addr
value: "https://192.168.20.81:6443"
securityContext:
capabilities:
add:
- NET_ADMIN
- NET_RAW
volumeMounts:
- mountPath: /etc/kubernetes/admin.conf
name: kubeconfig
readOnly: true
volumes:
- name: kubeconfig
hostPath:
path: /etc/kubernetes/admin.conf
type: File
EOF
Key Configuration Explained
vip_arp=true→ Uses ARP to advertise VIP on the networkcp_enable=true→ Enables control-plane load balancingsvc_enable=false→ Disables service load balancingvip_leaderelection=true→ Ensures only one active VIP owneraddress=192.168.20.80→ Your virtual IPkubernetes_addr→ Bootstrap API endpoint
SELinux Fix (Important)
Ensure kube-vip can read the kubeconfig:
ls -Z /etc/kubernetes/admin.conf
sudo chcon -t container_file_t /etc/kubernetes/admin.conf
ls -Z /etc/kubernetes/admin.conf
Expected output:
system_u:object_r:container_file_t:s0 /etc/kubernetes/admin.conf
Verification Commands
Check kube-vip pod
crictl ps | grep kube-vip
Check VIP ownership
ip addr show | grep 192.168.20.80
Test API via VIP
kubectl --server=https://192.168.20.80:6443 get nodes
Failover Test
- Identify current leader node
- Stop kubelet or power off that node
- Watch VIP move:
watch -n1 ip addr show
✅ VIP should migrate to another master within seconds
Best Practices
- Use dedicated interface (
ens33) correctly - Ensure L2 network allows ARP broadcasts
- Keep
vip_leasedurationlow for fast failover - Always test failover before production
Conclusion
kube-vip is a simple yet powerful solution for Kubernetes HA control planes:
✔ No external load balancer needed
✔ Fast failover using ARP
✔ Native Kubernetes leader election
Perfect for on-prem, lab, and edge clusters.
If you found this helpful, feel free to share or drop questions! 🚀
