Build a Highly Available Kubernetes Cluster with HAProxy & Keepalived on CentOS
This step‑by‑step guide shows how to prepare five CentOS 7 machines, configure hostnames, set up password‑less SSH, upgrade the kernel, disable firewalls and swap, tune sysctl, add Docker and Kubernetes repositories, install Docker, install kubeadm/kubelet/kubectl, configure HAProxy and Keepalived for a virtual IP, join master and worker nodes, deploy a flannel network plugin, and finally verify the cluster with an nginx pod and the Kubernetes dashboard.
Installation Requirements
Before starting, the five machines that will form the Kubernetes cluster must meet the following conditions:
Five machines running CentOS 7.5+ (minimal installation)
Hardware: at least 2 GB RAM, 2 vCPU+, 30 GB+ disk space
All machines must have network connectivity to each other and to the Internet
Installation Steps
Roles and IP addresses used in the tutorial:
k8s-lb 192.168.50.100
master1 192.168.50.128
master2 192.168.50.129
master3 192.168.50.130
node1 192.168.50.131
node2 192.168.50.1322.1 Pre‑processing
Configure hostnames
# hostnamectl set-hostname master1 # repeat for master2, master3, node1, node2Reload the hostname configuration: # bash Add hosts entries
# cat >> /etc/hosts <<EOF
192.168.50.100 k8s-lb
192.168.50.128 master1
192.168.50.129 master2
192.168.50.130 master3
192.168.50.131 node1
192.168.50.132 node2
EOFConfigure password‑less SSH
# ssh-keygen -t rsa -b 1200
# ssh-copy-id -i ~/.ssh/id_rsa.pub root@master1
# ssh-copy-id -i ~/.ssh/id_rsa.pub root@master2
# ssh-copy-id -i ~/.ssh/id_rsa.pub root@master3
# ssh-copy-id -i ~/.ssh/id_rsa.pub root@node1
# ssh-copy-id -i ~/.ssh/id_rsa.pub root@node2Upgrade kernel
# yum localinstall -y kernel-lt*
# grub2-set-default 0 && grub2-mkconfig -o /etc/grub2.cfg
# grubby --args="user_namespace.enable=1" --update-kernel="$(grubby --default-kernel)"Disable firewall and SELinux
# systemctl disable --now firewalld
# setenforce 0
# sed -i 's/enforcing/disabled/' /etc/selinux/configDisable swap
# swapoff -a
# sed -i.bak 's/^.*centos-swap/#&/' /etc/fstabSysctl tuning for Kubernetes
# cat > /etc/sysctl.d/k8s.conf <<EOF
net.ipv4.ip_forward = 1
net.bridge.bridge-nf-call-iptables = 1
net.bridge.bridge-nf-call-ip6tables = 1
fs.may_detach_mounts = 1
vm.overcommit_memory=1
vm.panic_on_oom=0
fs.inotify.max_user_watches=89100
fs.file-max=52706963
fs.nr_open=52706963
net.ipv4.tcp_keepalive_time = 600
net.ipv4.tcp_keepalive_probes = 3
net.ipv4.tcp_keepalive_intvl = 15
net.ipv4.tcp_max_tw_buckets = 36000
net.ipv4.tcp_tw_reuse = 1
net.ipv4.tcp_max_orphans = 327680
net.ipv4.tcp_orphan_retries = 3
net.ipv4.tcp_syncookies = 1
net.ipv4.tcp_max_syn_backlog = 16384
net.ipv4.ip_conntrack_max = 65536
net.core.somaxconn = 16384
EOF
# sysctl --systemConfigure yum repositories (Alibaba Cloud mirrors)
# mv /etc/yum.repos.d/* /tmp
# curl -o /etc/yum.repos.d/CentOS-Base.repo https://mirrors.aliyun.com/repo/Centos-7.repo
# curl -o /etc/yum.repos.d/epel.repo http://mirrors.aliyun.com/repo/epel-7.repoSet timezone and synchronize time
# ln -sf /usr/share/zoneinfo/Asia/Shanghai /etc/localtime
# yum install dnf ntpdate -y
# ntpdate ntp.aliyun.com2.2 Install Docker
Add Docker yum repository from Alibaba Cloud and install the latest Docker CE:
# curl -o /etc/yum.repos.d/docker-ce.repo https://mirrors.aliyun.com/docker-ce/linux/centos/docker-ce.repo
# dnf list docker-ce --showduplicates
# dnf install -y docker-ce docker-ce-cli
# systemctl enable --now docker
# docker --version # verify installationConfigure a local registry mirror for faster image pulls:
# cat > /etc/docker/daemon.json <<EOF
{
"registry-mirrors": ["https://f1bhsuge.mirror.aliyuncs.com"]
}
EOF
# systemctl restart docker2.3 Install Kubernetes components
Add the Kubernetes yum repository (Alibaba Cloud mirror) and install a specific version (1.18.6 in the example):
# cat > /etc/yum.repos.d/kubernetes.repo <<EOF
[kubernetes]
name=Kubernetes
baseurl=https://mirrors.aliyun.com/kubernetes/yum/repos/kubernetes-el7-x86_64
enabled=1
gpgcheck=0
repo_gpgcheck=0
EOF
# dnf clean all && dnf makecache
# dnf install -y kubelet-1.18.6 kubeadm-1.18.6 kubectl-1.18.6
# systemctl enable kubeletNote: kubelet is enabled but not started yet.
2.4 Configure HAProxy + Keepalived for a virtual IP
Install keepalived and haproxy on the three master nodes: # dnf install -y keepalived haproxy HAProxy configuration (saved as /etc/haproxy/haproxy.cfg) – only the relevant sections are shown:
global
maxconn 2000
ulimit-n 16384
log 127.0.0.1 local0 err
stats timeout 30s
defaults
log global
mode http
option httplog
timeout connect 5000
timeout client 50000
timeout server 50000
timeout http-request 15s
timeout http-keep-alive 15s
frontend k8s-master
bind 0.0.0.0:8443
bind 127.0.0.1:8443
mode tcp
option tcplog
default_backend k8s-master
backend k8s-master
mode tcp
balance roundrobin
server master1 192.168.50.128:6443 check
server master2 192.168.50.129:6443 check
server master3 192.168.50.130:6443 checkKeepalived configuration (saved as /etc/keepalived/keepalived.cfg) sets the virtual IP 192.168.50.100 and priority for each master (100, 99, 98). A health‑check script /etc/keepalived/check_kubernetes.sh monitors the kube‑apiserver process and stops keepalived if the master is down.
#!/bin/bash
function check_kubernetes() {
for i in {1..5}; do
apiserver_pid=$(pgrep kube-apiserver)
if [[ -n $apiserver_pid ]]; then
return
else
sleep 2
fi
done
}
check_kubernetes
if [[ $apiserver_pid -eq 0 ]]; then
/usr/bin/systemctl stop keepalived
exit 1
else
exit 0
fiEnable and start both services on each master:
# systemctl enable --now keepalived haproxy2.5 Deploy the first master (master1)
Generate the kubeadm init configuration file and edit the important fields (VIP address, API server SANs, pod subnet, etc.).
# kubeadm config print init-defaults > kubeadm-init.yaml
# vi kubeadm-init.yaml # edit advertiseAddress, controlPlaneEndpoint, podSubnet, etc.Pre‑pull required images to speed up the init:
# kubeadm config images pull --config kubeadm-init.yamlInitialize the control plane:
# kubeadm init --config kubeadm-init.yaml --upload-certsAfter a successful init, set up the local kubeconfig:
# mkdir -p $HOME/.kube
# sudo cp -i /etc/kubernetes/admin.conf $HOME/.kube/config
# sudo chown $(id -u):$(id -g) $HOME/.kube/config2.6 Join the remaining masters
Run the kubeadm join … --control-plane --certificate-key … command printed at the end of the init on master2 and master3, then copy the admin kubeconfig as above.
2.7 Join worker nodes
Run the plain kubeadm join … command (without --control-plane) on node1 and node2.
2.8 Install a network plugin (Flannel)
Because the default GitHub URL is blocked in China, add a hosts entry for raw.githubusercontent.com and download the manifest locally:
# echo "199.232.28.133 raw.githubusercontent.com" >> /etc/hosts
# curl -o kube-flannel.yml https://raw.githubusercontent.com/coreos/flannel/master/Documentation/kube-flannel.yml
# sed -i 's/quay.io/quay-mirror.qiniu.com/g' kube-flannel.yml
# kubectl apply -f kube-flannel.ymlVerify that the flannel pods are running and that all nodes become Ready:
# kubectl get pods -n kube-system | grep flannel
# kubectl get nodes3 Test the Cluster
Create a simple nginx deployment and expose it as a NodePort service:
# kubectl create deployment nginx --image=nginx
# kubectl expose deployment nginx --port=80 --type=NodePortFind the assigned NodePort (e.g., 30249) and access the service via the IP of the node where the pod is scheduled.
Deploy the Kubernetes dashboard, modify its Service to type: NodePort (port 30001 in the example), and access it with the admin token generated for the dashboard-admin service account.
# wget https://raw.githubusercontent.com/kubernetes/dashboard/v2.0.0-beta8/aio/deploy/recommended.yaml
# edit the Service to add "type: NodePort" and "nodePort: 30001"
# kubectl apply -f recommended.yaml
# kubectl create serviceaccount dashboard-admin -n kube-system
# kubectl create clusterrolebinding dashboard-admin --clusterrole=cluster-admin --serviceaccount=kube-system:dashboard-admin
# kubectl describe secret -n kube-system $(kubectl -n kube-system get secret | awk '/dashboard-admin/{print $1}')Signed-in readers can open the original source through BestHub's protected redirect.
This article has been distilled and summarized from source material, then republished for learning and reference. If you believe it infringes your rights, please contactand we will review it promptly.
MaGe Linux Operations
Founded in 2009, MaGe Education is a top Chinese high‑end IT training brand. Its graduates earn 12K+ RMB salaries, and the school has trained tens of thousands of students. It offers high‑pay courses in Linux cloud operations, Python full‑stack, automation, data analysis, AI, and Go high‑concurrency architecture. Thanks to quality courses and a solid reputation, it has talent partnerships with numerous internet firms.
How this landed with the community
Was this worth your time?
0 Comments
Thoughtful readers leave field notes, pushback, and hard-won operational detail here.
