方案介绍#
在私有环境中部署 Kubernetes 高可用集群时,传统方案需要准备硬件或软件负载均衡器来创建多控制平面集群。通常我们会选择使用 HAProxy + Keepalived 来实现这个功能:创建 2 个负载均衡器虚拟机,分配一个 VIP(虚拟 IP),通过 VIP 将流量重定向到后端的 Kubernetes 控制平面节点。架构如下图所示:

使用 Kube-VIP 的架构如下:

可以看到,使用 Kube-VIP 后架构更加优雅,无需额外的负载均衡服务器。
环境配置#
节点信息#
| IP 地址 | 主机名 | 操作系统 | 内核版本 |
|---|---|---|---|
| 192.168.8.81 | master-01 | CentOS Linux release 7.9.2009 | 5.4.128-1.el7.elrepo.x86_64 |
| 192.168.8.82 | master-02 | CentOS Linux release 7.9.2009 | 5.4.128-1.el7.elrepo.x86_64 |
| 192.168.8.83 | master-03 | CentOS Linux release 7.9.2009 | 5.4.128-1.el7.elrepo.x86_64 |
| 192.168.8.84 | node-01 | CentOS Linux release 7.9.2009 | 5.4.128-1.el7.elrepo.x86_64 |
| 192.168.8.85 | node-02 | CentOS Linux release 7.9.2009 | 5.4.128-1.el7.elrepo.x86_64 |
| 192.168.8.86 | node-03 | CentOS Linux release 7.9.2009 | 5.4.128-1.el7.elrepo.x86_64 |
| 192.168.8.100 (Kube-VIP 虚拟IP) | - | - | - |
软件版本#
| 组件 | 版本 |
|---|---|
| Kubernetes | v1.20.5 |
| Containerd | v1.4.6 |
| Rancher | v2.4.15 |
集群部署#
以下节点初始化操作需要在所有节点上执行。
节点初始化#
配置主机名解析#
cat >> /etc/hosts << EOF
192.168.8.81 master-01
192.168.8.82 master-02
192.168.8.83 master-03
192.168.8.84 node-01
192.168.8.85 node-02
192.168.8.86 node-03
EOF
关闭 Swap#
swapoff -a
sed -i 's/.*swap.*/#&/' /etc/fstab
设置主机名#
hostnamectl set-hostname xxx # 例如:hostnamectl set-hostname master-01
关闭防火墙#
systemctl stop firewalld
systemctl disable firewalld
关闭 SELinux#
sed -i 's#SELINUX=enforcing#SELINUX=disabled#g' /etc/selinux/config
grep -i ^selinux= /etc/selinux/config
setenforce 0
getenforce
更新内核#
参考文档步骤
配置内核参数#
sudo yum install -y conntrack ipvsadm ipset jq sysstat curl iptables
cat <<EOF | sudo tee /etc/modules-load.d/containerd.conf
overlay
br_netfilter
EOF
chmod a+x /etc/rc.local
cat <<EOF | sudo tee /etc/sysctl.d/99-kubernetes-cri.conf
net.bridge.bridge-nf-call-iptables = 1
net.ipv4.ip_forward = 1
net.bridge.bridge-nf-call-ip6tables = 1
EOF
modprobe overlay
modprobe br_netfilter # 加载内核模块
cat > /etc/rc.local << EOF
modprobe overlay
modprobe br_netfilter
EOF
sysctl -p /etc/sysctl.d/99-kubernetes-cri.conf
启用 IPVS 内核模块#
cat > /etc/sysconfig/modules/ipvs.modules <<EOF
#!/bin/bash
modprobe -- ip_vs
modprobe -- ip_vs_rr
modprobe -- ip_vs_wrr
modprobe -- ip_vs_sh
modprobe -- nf_conntrack_ipv4
EOF
chmod 755 /etc/sysconfig/modules/ipvs.modules \
&& bash /etc/sysconfig/modules/ipvs.modules \
&& lsmod | grep -e ip_vs -e nf_conntrack_ipv4
安装和配置 Containerd#
sudo yum install -y yum-utils device-mapper-persistent-data lvm2 \
&& sudo yum-config-manager --add-repo https://mirrors.aliyun.com/docker-ce/linux/centos/docker-ce.repo \
&& sudo yum makecache fast
yum install containerd -y
containerd config default > /etc/containerd/config.toml
sed -i "s#k8s.gcr.io#registry.cn-hangzhou.aliyuncs.com/google_containers#g" /etc/containerd/config.toml
sed -i '/containerd.runtimes.runc.options/a\ \ \ \ \ \ \ \ \ \ \ \ SystemdCgroup = true' /etc/containerd/config.toml
sed -i "s#https://registry-1.docker.io#https://registry.cn-hangzhou.aliyuncs.com#g" /etc/containerd/config.toml
systemctl daemon-reload
systemctl enable containerd
systemctl restart containerd
安装 crictl 客户端#
crictl 是 Containerd 的命令行客户端工具
wget https://github.com/kubernetes-sigs/cri-tools/releases/download/v1.21.0/crictl-v1.21.0-linux-amd64.tar.gz
sudo tar zxvf crictl-v1.21.0-linux-amd64.tar.gz -C /usr/local/bin
cat > /etc/crictl.yaml << EOF
runtime-endpoint: unix:///run/containerd/containerd.sock
image-endpoint: unix:///run/containerd/containerd.sock
timeout: 10
debug: true
EOF
安装 Kubernetes 组件#
cat <<EOF > /etc/yum.repos.d/kubernetes.repo
[kubernetes]
name=Kubernetes
baseurl=http://mirrors.aliyun.com/kubernetes/yum/repos/kubernetes-el7-x86_64
enabled=1
gpgcheck=0
repo_gpgcheck=0
gpgkey=http://mirrors.aliyun.com/kubernetes/yum/doc/yum-key.gpg http://mirrors.aliyun.com/kubernetes/yum/doc/rpm-package-key.gpg
EOF
yum list kubeadm --showduplicates | sort -r # 查看所有可用的 kubeadm 版本
yum install -y kubeadm-1.20.5 kubelet-1.20.5 kubectl-1.20.5
systemctl enable kubelet # 启用 kubelet 服务自启动
可选:配置 kubectl 命令补全功能
yum install -y bash-completion source /usr/share/bash-completion/bash_completion source <(kubectl completion bash) echo "source <(kubectl completion bash)" >> ~/.bashrc
Kubernetes 集群初始化#
使用 kubeadm 首先初始化
master-01节点,操作步骤如下:
生成 kubeadm 初始化配置文件#
注意:由于控制平面地址配置为 VIP 地址,如果 Kube-VIP 尚未部署,kubeadm init 操作将一直处于 pending 状态直至超时。因此需要在执行初始化操作后立即部署 Kube-VIP。
kubeadm config print init-defaults > init_kubelet.yaml # 生成默认的初始化配置文件
# 修改后的初始化配置文件内容如下:
cat init_kubelet.yaml
apiVersion: kubeadm.k8s.io/v1beta2
bootstrapTokens:
- groups:
- system:bootstrappers:kubeadm:default-node-token
token: abcdef.0123456789abcdef
ttl: 24h0m0s
usages:
- signing
- authentication
kind: InitConfiguration
nodeRegistration:
criSocket: /run/containerd/containerd.sock
---
apiServer:
timeoutForControlPlane: 4m0s
apiVersion: kubeadm.k8s.io/v1beta2
certificatesDir: /etc/kubernetes/pki
clusterName: kubernetes
controllerManager: {}
dns:
type: CoreDNS
etcd:
local:
dataDir: /var/lib/etcd
imageRepository: registry.cn-hangzhou.aliyuncs.com/google_containers
kind: ClusterConfiguration
controlPlaneEndpoint: "192.168.8.100:6443"
kubernetesVersion: v1.20.5
networking:
dnsDomain: cluster.local
serviceSubnet: 10.96.0.0/12
scheduler: {}
---
apiVersion: kubelet.config.k8s.io/v1beta1
kind: KubeletConfiguration
cgroupDriver: systemd
#protectKernelDefaults: false
---
apiVersion: kubeproxy.config.k8s.io/v1alpha1
kind: KubeProxyConfiguration
mode: ipvs
kubeadm init --config init_kubelet.yaml --upload-certs
这里记录一个踩坑点,就是配置文件中所示的 “protectKernelDefaults”,添加了这个配置项后,会出现
kubelet 奔溃问题,将其注释掉后问题就解决了,下面图片中为官方文档中给出的注解。
部署 Kube-VIP 静态 Pod#
kubelet 静态 Pod 目录为
/etc/kubernetes/manifests/,只需将对应的 YAML 文件生成到此目录下,Pod 的生命周期将由 kubelet 管理。
export VIP=192.168.8.100 # VIP 地址
export INTERFACE=eth0
ctr image pull docker.io/plndr/kube-vip:0.3.1
mkdir -p /etc/kubernetes/manifests
ctr run --rm --net-host docker.io/plndr/kube-vip:0.3.1 vip \
/kube-vip manifest pod \
--interface $INTERFACE \
--vip $VIP \
--controlplane \
--services \
--arp \
--leaderElection | tee /etc/kubernetes/manifests/kube-vip.yaml



安装 CNI 网络插件#
集群初始化后,需要安装网络插件才能正常使用。CNI 插件有多种选择,这里以 Cilium 为例。
curl https://raw.githubusercontent.com/helm/helm/master/scripts/get-helm-3 | bash
helm repo add cilium https://helm.cilium.io/
helm install cilium cilium/cilium --version 1.9.4 \
--namespace kube-system

添加其他控制平面节点#
复制证书文件到其他控制平面节点#
ssh-keygen # 生成 SSH 密钥对
ssh-copy-id root@"node_id" # 配置免密登录
USER=root # 可自定义用户
CONTROL_PLANE_IPS="192.168.8.82 192.168.8.83"
for host in ${CONTROL_PLANE_IPS}; do
ssh "${USER}"@$host "mkdir -p /etc/kubernetes/pki/ /etc/kubernetes/pki/etcd/"
scp /etc/kubernetes/pki/ca.crt "${USER}"@$host:/etc/kubernetes/pki/
scp /etc/kubernetes/pki/ca.key "${USER}"@$host:/etc/kubernetes/pki/
scp /etc/kubernetes/pki/sa.key "${USER}"@$host:/etc/kubernetes/pki/
scp /etc/kubernetes/pki/sa.pub "${USER}"@$host:/etc/kubernetes/pki/
scp /etc/kubernetes/pki/front-proxy-ca.crt "${USER}"@$host:/etc/kubernetes/pki/
scp /etc/kubernetes/pki/front-proxy-ca.key "${USER}"@$host:/etc/kubernetes/pki/
scp /etc/kubernetes/pki/etcd/ca.crt "${USER}"@$host:/etc/kubernetes/pki/etcd/
scp /etc/kubernetes/pki/etcd/ca.key "${USER}"@$host:/etc/kubernetes/pki/etcd/
done


控制平面节点加入集群#
kubeadm join 192.168.8.100:6443 --token hash.hash\
--discovery-token-ca-cert-hash sha256:hash \
--control-plane --certificate-key key
master-02 加入集群

master-03 加入集群

重要提醒:新加入集群的 Master 节点需要部署 Kube-VIP 静态 Pod,以确保集群具备高可用特性。请在每个新加入的控制平面节点上执行上述 Kube-VIP 部署步骤。



添加 Worker 节点#
kubeadm join 192.168.8.100:6443 --token hash.hash\
--discovery-token-ca-cert-hash sha256:hash


可选配置优化#
移除 Master 节点污点#
生产环境中请谨慎操作,建议保留 Master 节点污点以避免业务 Pod 调度到控制平面节点。
kubectl taint nodes --all node-role.kubernetes.io/master-

