This guide explains how to configure HAProxy as a load balancer for Kubernetes clusters.
A load balancer is important for Kubernetes clusters because:
- High Availability: It ensures that if one control plane node fails, traffic is redirected to other working nodes.
- Better Performance: It distributes traffic evenly across multiple nodes, preventing overload on a single node.
- Simplified Access: Instead of connecting to individual control plane nodes, you can use a single entry point (the load balancer).
- Security: It hides the internal IP addresses of your control plane nodes, adding an extra layer of protection.
Before starting, make sure you can reach your control plane nodes using their DNS names or IP addresses.
Here is an example configuration file for HAProxy (haproxy.cfg):
global
daemon
maxconn 100000
defaults
mode tcp
timeout connect 5s
timeout client 50s
timeout server 50s
frontend kube-api
bind *:6443
default_backend kube-api-backend
backend kube-api-backend
mode tcp
option httpchk GET /healthz
server kube-control-1 <control-plane-1-ip>:6443 check
server kube-control-2 <control-plane-2-ip>:6443 check
- Frontend: Listens on port
6443(the default Kubernetes API port) and forwards traffic to the backend. - Backend: Contains the list of control plane nodes (
kube-control-1,kube-control-2) with their IPs and health checks. - Health Check: Ensures only healthy nodes receive traffic.
Save this file and restart HAProxy to apply the changes:
sudo systemctl restart haproxyTo ensure secure communication, update the Kubernetes certificates to include the load balancer's IP and DNS name.
First login into you control plane node and create a new YAML file (e.g., san-config.yaml) to regenerate certificates with the load balancer's details:
apiVersion: kubeadm.k8s.io/v1beta4
kind: ClusterConfiguration
apiServer:
certSANs:
- <proxy-ip>
- <dns-record>Replace <proxy-ip> with the load balancer's IP address and <dns-record> with its DNS name.
On each control plane node, back up the existing Public Key Infrastructure (PKI) files:
tar czf pki.tar.gz /etc/kubernetes/pkiThis creates a compressed archive of the certificate files in case you need to restore them later.
Delete the existing apiserver certificates on each control plane node:
rm /etc/kubernetes/pki/apiserver.crt /etc/kubernetes/pki/apiserver.keyThis step removes the old certificates so they can be replaced with new ones that include the load balancer's details.
Run the following command on each control plane node to generate new certificates using the updated configuration:
kubeadm init phase certs apiserver --config san-config.yamlAfter running the command, you should see output similar to this:
[certs] Generating "apiserver" certificate and key
[certs] apiserver serving cert is signed for DNS names [<control-plane-hostname> kubernetes kubernetes.default kubernetes.default.svc kubernetes.default.svc.cluster.local <your-dns-record>] and IPs [10.96.0.1 <control-plane-ip> <proxy-ip>]
This confirms that the new certificates include the load balancer's IP and DNS name.
Finally, update your Kubernetes configuration file (~/.kube/config) to point to the load balancer instead of a specific control plane node.
Locate the cluster section and replace the control plane IP with the load balancer's IP:
clusters:
- cluster:
server: https://<proxy-ip>:6443
name: kubernetesSave the file, and you're done!