前言

在Kubernetes生产环境中,高可用性是保障业务连续性的关键要求。为了应对单点故障风险,本文设计了一套基于Keepalived + HAProxy的高可用K8s集群方案。通过HAProxy为kube-apiserver提供负载均衡,任意Master节点故障时流量自动切换到正常节点;同时利用Keepalived的VRRP机制实现HAProxy自身的故障转移,确保整个控制平面入口的稳定。此外,结合Proxy Protocol代理协议,在实现四层负载均衡的同时还能透传客户端真实IP。

本文将基于openEuler 24.03 LTS-SP1操作系统,从零开始完整演示高可用K8s集群的构建过程。涵盖环境规划、操作系统基础配置、Keepalived和HAProxy安装、Containerd运行时配置、Kubeadm集群初始化、Calico网络插件部署以及集群可用性验证等全流程。希望为你在私有网络环境中搭建生产级K8s集群提供一份可落地的参考。


一、环境说明

本实战采用6台主机,包括2个Master节点、2个Worker节点以及2个独立的负载均衡节点(同时部署Keepalived和HAProxy)。主机规划如下:

主机名 IP地址 操作系统 角色
k8s-master1 192.168.38.160 openEuler 24.03 SP1 K8s master节点
k8s-master2 192.168.38.158 openEuler 24.03 SP1 K8s master节点
k8s-node1 192.168.38.159 openEuler 24.03 SP1 Worker节点
k8s-node2 192.168.38.155 openEuler 24.03 SP1 Worker节点
keepalived1/haproxy1 192.168.38.156 openEuler 24.03 SP1 HAProxy + Keepalived 1
keepalived2/haproxy2 192.168.38.157 openEuler 24.03 SP1 HAProxy + Keepalived 2

高可用架构示意图如下:

开始部署之前,请先确保所有节点的YUM源配置正确,推荐使用华为云镜像源。修改 /etc/yum.repos.d/openEuler.repo 文件,内容如下:


二、主机基础配置

以下操作需要在所有K8s节点(master1、master2、node1、node2)上执行。这里以 k8s-master1 为例。

1. 修改主机名并配置 hosts 文件

# 各节点分别执行
hostnamectl set-hostname k8s-master1   # master1
hostnamectl set-hostname k8s-master2   # master2
hostnamectl set-hostname k8s-node1     # node1
hostnamectl set-hostname k8s-node2     # node2

编辑 /etc/hosts,添加以下内容:

cat >> /etc/hosts << EOF
127.0.0.1   localhost
192.168.38.160  k8s-master1
192.168.38.158  k8s-master2
192.168.38.159  k8s-node1
192.168.38.155  k8s-node2
EOF

2. 开启流量转发

cat > /etc/sysctl.d/k8s.conf << EOF
net.bridge.bridge-nf-call-ip6tables = 1
net.bridge.bridge-nf-call-iptables = 1
net.ipv4.ip_forward = 1
vm.swappiness=0
EOF

modprobe br_netfilter
sysctl -p /etc/sysctl.d/k8s.conf

确保 br_netfilter 模块开机自动加载:

echo "br_netfilter" > /etc/modules-load.d/br_netfilter.conf

将内核参数配置加入开机自启(/etc/rc.local):

echo "sysctl -p /etc/sysctl.d/k8s.conf" >> /etc/rc.local
chmod 755 /etc/rc.d/rc.local

注意:在openEuler系统中,还需检查 /etc/sysctl.conf 中是否存在 net.ipv4.ip_forward=0,若有则删除或改为 =1,否则上述配置可能不生效。

3. 关闭防火墙与 SELinux

sed -i 's/^SELINUX=enforcing$/SELINUX=disabled/' /etc/selinux/config
systemctl disable --now firewalld

4. 关闭 Swap

swapoff -a
sed -ri 's/.*swap.*/#&/' /etc/fstab

为了永久禁用,还需执行:

systemctl mask 'dev-disk-by\x2ddiskseq-2\x2dpart5.swap'   # 根据实际swap单元名修改

三、Keepalived + HAProxy 安装与配置

1. HAProxy 安装与配置

在两个负载均衡节点(192.168.38.156和192.168.38.157)上执行以下操作。

源码编译安装
# 安装依赖
yum install -y gcc gcc-c++ make

# 下载并解压HAProxy源码(以3.0.5为例)
wget https://www.haproxy.org/download/3.0/src/haproxy-3.0.5.tar.gz
tar zxvf haproxy-3.0.5.tar.gz
cd haproxy-3.0.5

# 编译安装
make -j 2 TARGET=linux-glibc PREFIX=/usr/local/haproxy
make install PREFIX=/usr/local/haproxy

# 创建配置和日志目录
mkdir /usr/local/haproxy/conf /usr/local/haproxy/logs

# 拷贝示例配置文件(后续会覆盖)
cp examples/option-http_proxy.cfg /usr/local/haproxy/conf/haproxy.cfg

# 创建haproxy用户
useradd haproxy
创建 systemd 服务文件

编辑 /etc/systemd/system/haproxy.service

[Unit]
Description=HAProxy Load Balancer
After=network.target

[Service]
ExecStartPre=/usr/local/haproxy/sbin/haproxy -f /usr/local/haproxy/conf/haproxy.cfg -c -q
ExecStart=/usr/local/haproxy/sbin/haproxy -Ws -f /usr/local/haproxy/conf/haproxy.cfg -p /usr/local/haproxy/logs/haproxy.pid
ExecReload=/bin/kill -USR2 $MAINPID
PIDFile=/usr/local/haproxy/logs/haproxy.pid
Restart=on-failure
StandardOutput=journal
StandardError=journal

[Install]
WantedBy=multi-user.target
配置 HAProxy

编辑 /usr/local/haproxy/conf/haproxy.cfg,内容如下:

global
        log 127.0.0.1 local0 info
        maxconn 4096
        daemon
        user haproxy
        group haproxy
        nbthread 4

defaults
        mode tcp
        retries 3
        option tcplog
        timeout connect 20s
        timeout client 30s
        timeout server 30s
        timeout check 2s

listen admin_stats
        bind 0.0.0.0:19088
        mode http
        log 127.0.0.1 local0 err
        stats refresh 30s
        stats uri /haproxy-status
        stats realm welcome login\ Haproxy
        stats auth admin:admin123
        stats hide-version
        stats admin if TRUE

frontend kubernetes-frontend
        bind 0.0.0.0:6443
        default_backend kubernetes-backend

backend kubernetes-backend
        balance roundrobin
        option tcp-check
        server app1 192.168.38.160:6443 weight 6 check inter 2000 rise 2 fall 3
        server app2 192.168.38.158:6443 weight 6 check inter 2000 rise 2 fall 3

提示:在初始化集群时,如果第二个Master节点尚未加入,可先注释掉 app2 一行,等Master2加入后再取消注释并重启HAProxy。

启动HAProxy并设置开机自启:

systemctl daemon-reload
systemctl enable --now haproxy

2. Keepalived 安装与配置

两个负载均衡节点均需安装Keepalived。

yum install -y keepalived ipvsadm
# 或者源码安装(根据需要)
配置 Keepalived

编辑 /etc/keepalived/keepalived.conf(主节点示例,备节点优先级降低):

global_defs {
   notification_email {
     acassen@firewall.loc
   }
   notification_email_from Alexandre.Cassen@firewall.loc
   smtp_server 192.168.200.1
   smtp_connect_timeout 30
   router_id haproxy_DEVEL
}

vrrp_script check_haproxy {
    script "killall -0 haproxy"
    interval 2
}

vrrp_instance HAproxy_1 {
    state BACKUP
    interface ens3                # 替换为实际网卡名
    virtual_router_id 118
    priority 100                  # 备节点改为80
    advert_int 2
    nopreempt
    authentication {
        auth_type PASS
        auth_pass qwaszx
    }
    track_script {
        check_haproxy
    }
    virtual_ipaddress {
       192.168.38.100/24 dev ens3
    }
}

启动Keepalived:

systemctl enable --now keepalived

验证VIP是否已绑定:

ip a | grep 192.168.38.100


四、K8s软件包安装

以下操作需要在所有K8s节点(master1、master2、node1、node2)上执行。

# 安装containerd、kubernetes组件、cri-tools
yum install -y containerd kubernetes* cri-tools

如果 containerd 版本低于 1.6.22-15,请手动升级:

wget --no-check-certificate https://repo.openeuler.org/openEuler-24.03-LTS/update/x86_64/Packages/containerd-1.6.22-15.oe2403.x86_64.rpm
rpm -Uvh containerd-1.6.22-15.oe2403.x86_64.rpm

下载CNI插件(所有节点):

mkdir -p /opt/cni/bin
cd /opt/cni/bin
wget --no-check-certificate https://github.com/containernetworking/plugins/releases/download/v1.5.1/cni-plugins-linux-amd64-v1.5.1.tgz
tar -xzvf cni-plugins-linux-amd64-v1.5.1.tgz

五、配置 Containerd

所有K8s节点执行。

containerd_conf="/etc/containerd/config.toml"
mkdir -p /etc/containerd
containerd config default > "${containerd_conf}"

修改配置:

  • sandbox镜像registry.k8s.io/pause:3.9 → registry.aliyuncs.com/google_containers/pause:3.9

  • cgroup驱动SystemdCgroup = true

  • 关闭registry.k8s.io证书验证:添加 insecure_skip_verify = true

  • 镜像加速:为 docker.io 添加国内端点

可使用以下命令快速修改:

sed -i 's#registry.k8s.io/pause:3.9#registry.aliyuncs.com/google_containers/pause:3.9#g' "${containerd_conf}"
sed -i "/SystemdCgroup/s/false/true/g" "${containerd_conf}"
sed -i '/plugins."io.containerd.grpc.v1.cri".registry.configs/a\[plugins."io.containerd.grpc.v1.cri".registry.configs."registry.k8s.io".tls]\n  insecure_skip_verify = true' "${containerd_conf}"

# 在[plugins."io.containerd.grpc.v1.cri".registry.mirrors]下添加
cat >> "${containerd_conf}" << EOF

    [plugins."io.containerd.grpc.v1.cri".registry.mirrors."docker.io"]
      endpoint = ["https://proxy.1panel.live","https://docker.1ms.run"]
EOF

重启containerd:

systemctl daemon-reload
systemctl enable --now containerd

六、配置 crictl 使用 Containerd

所有K8s节点执行:

crictl config runtime-endpoint unix:///run/containerd/containerd.sock
crictl config image-endpoint unix:///run/containerd/containerd.sock

七、配置 Kubelet

所有K8s节点执行:

systemctl enable kubelet
echo 'KUBELET_EXTRA_ARGS="--runtime-cgroups=/systemd/system.slice --kubelet-cgroups=/systemd/system.slice"' >> /etc/sysconfig/kubelet

八、使用 Kubeadm 创建集群

1. 生成集群配置文件(仅在master1执行)

kubeadm config print init-defaults --component-configs KubeletConfiguration > kubeletConfig.yaml

编辑 kubeletConfig.yaml,修改以下关键项:

  • advertiseAddress: 192.168.38.160 (master1 IP)

  • name: k8s-master1

  • imageRepository: registry.aliyuncs.com/google_containers

  • kubernetesVersion: v1.29.1 (根据实际安装版本填写)

  • networking.podSubnet: 10.244.0.0/16 (Calico默认)

  • 在 scheduler: {} 下方添加:

    controlPlaneEndpoint: "192.168.38.100:6443"

2. 启动负载均衡服务

在两个负载均衡节点上启动HAProxy和Keepalived(如果尚未启动):

systemctl start haproxy keepalived

确认VIP 192.168.38.100 可ping通。

3. 初始化集群(仅master1)

kubeadm init --config kubeletConfig.yaml

若失败,可执行 kubeadm reset --force 后重试。

初始化成功后,配置kubectl:

mkdir -p "$HOME"/.kube
cp -i /etc/kubernetes/admin.conf "$HOME"/.kube/config
chown "$(id -u)":"$(id -g)" "$HOME"/.kube/config
echo "export KUBECONFIG=/etc/kubernetes/admin.conf" >> ~/.bashrc
source ~/.bashrc

4. 将Master2节点加入集群

首先从master1拷贝证书到master2:

# 在master2上创建目录
mkdir -p /etc/kubernetes/pki/etcd

# 拷贝证书(在master2上执行)
scp -r root@192.168.38.160:/etc/kubernetes/pki/ca.* /etc/kubernetes/pki/
scp -r root@192.168.38.160:/etc/kubernetes/pki/sa.* /etc/kubernetes/pki/
scp -r root@192.168.38.160:/etc/kubernetes/pki/front-proxy-ca.* /etc/kubernetes/pki/
scp root@192.168.38.160:/etc/kubernetes/admin.conf /etc/kubernetes/
scp -r root@192.168.38.160:/etc/kubernetes/pki/etcd/ca* /etc/kubernetes/pki/etcd/

然后执行join命令(注意使用初始化输出的token和hash):

kubeadm join 192.168.38.100:6443 --token abcdef.0123456789abcdef \
    --discovery-token-ca-cert-hash sha256:4ef4e0b5a94973b5399300ce659532bbc4c3428c7375a76b2a2b38242fda3ad4 \
    --control-plane

5. 将Worker节点加入集群

在node1和node2上执行(同样使用上述token):

kubeadm join 192.168.38.100:6443 --token abcdef.0123456789abcdef \
    --discovery-token-ca-cert-hash sha256:4ef4e0b5a94973b5399300ce659532bbc4c3428c7375a76b2a2b38242fda3ad4

若token过期,可在master1上重新生成:kubeadm token create --print-join-command

6. 查看节点状态

kubectl get nodes

此时节点状态可能为 NotReady,因为尚未安装网络插件。


九、部署 Calico 网络插件

在master1上执行:

wget https://raw.githubusercontent.com/projectcalico/calico/v3.27.0/manifests/calico.yaml
sed -i 's#docker.io/calico#docker.m.daocloud.io/calico#g' calico.yaml
kubectl apply -f calico.yaml

等待几分钟后再次查看节点状态:

kubectl get nodes

所有节点应变为 Ready


十、集群验证

部署一个简单的HTTP服务测试集群功能。

创建 http.yml

apiVersion: apps/v1
kind: Deployment
metadata:
  name: http-deployment
spec:
  replicas: 3
  selector:
    matchLabels:
      app: http_server
  template:
    metadata:
      labels:
        app: http_server
    spec:
      containers:
      - name: http-web
        image: nginx:1.27.3

创建 service.yml

apiVersion: v1
kind: Service
metadata:
  name: service-httpd
spec:
  type: NodePort
  selector:
    app: http_server
  ports:
  - protocol: TCP
    port: 8080
    targetPort: 80

部署资源:

kubectl apply -f http.yml
kubectl apply -f service.yml

查看Pod和Service:

kubectl get pods -o wide
kubectl get svc service-httpd

通过任意节点IP和NodePort访问,例如:

curl http://192.168.38.155:31767   # 实际端口以Service显示为准

或者宿主机直接访问:

若能返回nginx欢迎页,则集群已正常工作。


结语

本文详细演示了在openEuler 24.03 LTS-SP1操作系统上搭建高可用Kubernetes集群的完整过程。通过Keepalived + HAProxy实现了控制平面的高可用,使用Containerd作为容器运行时,Calico作为网络插件,最终完成了多Master、多Worker的生产级集群部署。经测试验证,集群能够正常运行容器化应用,并对外提供稳定服务。

Logo

openEuler 是由开放原子开源基金会孵化的全场景开源操作系统项目,面向数字基础设施四大核心场景(服务器、云计算、边缘计算、嵌入式),全面支持 ARM、x86、RISC-V、loongArch、PowerPC、SW-64 等多样性计算架构

更多推荐