ubuntu 24.04.4,使用kubeadm + kube-vip 在线部署三个master节点的高可用k8s v1.34.10集群

系统,ubuntu 24.04.4
集群规划(3 台服务器):

主机名:k8s-master-01,内网ip:172.29.128.1

主机名:k8s-worker-01,内网ip:172.29.132.68

主机名:k8s-worker-02,内网ip:172.29.132.69
由于服务器有限,把这三台服务器既当master节点,又当工作节点,部署三个master节点的高可用k8s集群。

节点清单:

节点 内网 IP 角色 
k8s-master-01 172.29.128.1 Master01+Worker 
k8s-worker-01 172.29.132.68 Master02+Worker 
k8s-worker-02 172.29.132.69 Master03+Worker

 

 

 

 

 

一、所有 3 台节点统一前置初始化(全部执行)

1.1 主机名 & hosts 解析

分别设置主机名

# 节点1执行
hostnamectl set-hostname k8s-master-01
# 节点2执行
hostnamectl set-hostname k8s-worker-01
# 节点3执行
hostnamectl set-hostname k8s-worker-02

所有节点写入 /etc/hosts

cat >> /etc/hosts <<EOF
172.29.128.1    k8s-master-01
172.29.132.68   k8s-worker-01
172.29.132.69   k8s-worker-02
172.29.128.100  k8s-apiserver-vip
EOF

1.2 系统内核配置、关闭 swap、防火墙

# 关闭永久swap
swapoff -a
sed -i '/swap/s/^/#/' /etc/fstab

#关闭 ufw防火墙
systemctl stop ufw
systemctl disable ufw

# 内核转发、iptables桥接
cat >> /etc/sysctl.conf <<EOF
net.bridge.bridge-nf-call-iptables  = 1
net.bridge.bridge-nf-call-ip6tables = 1
net.ipv4.ip_forward                 = 1
#配置ARP广播必需参数
net.ipv4.conf.all.arp_ignore = 1
net.ipv4.conf.all.arp_announce = 2
net.ipv4.conf.default.rp_filter = 2
net.ipv4.conf.all.rp_filter = 2
net.ipv4.ip_nonlocal_bind = 1
# 替换你的网卡名
net.ipv4.conf.ens3.arp_ignore = 1
net.ipv4.conf.ens3.arp_announce = 2
net.ipv4.conf.ens3.rp_filter = 2

EOF
sysctl -p

# 加载overlay/iptables内核模块
modprobe overlay
modprobe br_netfilter

 

1.3. 时间同步

apt install chrony -y
systemctl enable --now chronyd
timedatectl set-timezone Asia/Shanghai

 

二,安装 containerd + kubeadm(所有节点执行)

1, 安装containerd

# 1. 重新生成密钥+阿里源
curl -fsSL https://mirrors.aliyun.com/docker-ce/linux/ubuntu/gpg | gpg --dearmor -o /usr/share/keyrings/docker-archive-keyring.gpg
chmod 644 /usr/share/keyrings/docker-archive-keyring.gpg
echo "deb [arch=$(dpkg --print-architecture) signed-by=/usr/share/keyrings/docker-archive-keyring.gpg] https://mirrors.aliyun.com/docker-ce/linux/ubuntu $(lsb_release -cs) stable" | tee /etc/apt/sources.list.d/docker.list > /dev/null

# 2. 更新源(不会再出现download.docker.com报错)
apt update
#安装containerd
apt install -y containerd.io
# 生成默认配置
containerd config default | tee /etc/containerd/config.toml

# 修改cgroup驱动为systemd + 配置国内pause镜像
sed -i 's/SystemdCgroup \= false/SystemdCgroup \= true/g' /etc/containerd/config.toml
sed -i 's#sandbox_image = "registry.k8s.io/pause:3.10"#sandbox_image = "registry.ustc.edu.cn/k8s/pause:3.10"#' /etc/containerd/config.toml

# 重启生效
systemctl daemon-reload
systemctl restart containerd
systemctl enable --now containerd

 

2, 添加 k8s -v1.34.10官方源

# 导入k8s密钥
curl -fsSL https://pkgs.k8s.io/core:/stable:/v1.34/deb/Release.key | gpg --dearmor -o /usr/share/keyrings/kubernetes-apt-keyring.gpg
# 写入apt源
echo 'deb [signed-by=/usr/share/keyrings/kubernetes-apt-keyring.gpg] https://pkgs.k8s.io/core:/stable:/v1.34/deb/ /' | tee /etc/apt/sources.list.d/kubernetes.list
apt update

查看k8s可用版本

# 查询kubeadm所有可用版本
apt-cache madison kubeadm
# kubectl
apt-cache madison kubectl
# kubelet
apt-cache madison kubelet

输出:

 apt-cache madison kubeadm
   kubeadm | 1.34.10-1.1 | https://pkgs.k8s.io/core:/stable:/v1.34/deb  Packages
   kubeadm | 1.34.9-1.1 | https://pkgs.k8s.io/core:/stable:/v1.34/deb  Packages
   kubeadm | 1.34.8-1.1 | https://pkgs.k8s.io/core:/stable:/v1.34/deb  Packages
   kubeadm | 1.34.7-1.1 | https://pkgs.k8s.io/core:/stable:/v1.34/deb  Packages
   kubeadm | 1.34.6-1.1 | https://pkgs.k8s.io/core:/stable:/v1.34/deb  Packages
   kubeadm | 1.34.5-1.1 | https://pkgs.k8s.io/core:/stable:/v1.34/deb  Packages
   kubeadm | 1.34.4-1.1 | https://pkgs.k8s.io/core:/stable:/v1.34/deb  Packages
   kubeadm | 1.34.3-1.1 | https://pkgs.k8s.io/core:/stable:/v1.34/deb  Packages
   kubeadm | 1.34.2-1.1 | https://pkgs.k8s.io/core:/stable:/v1.34/deb  Packages
   kubeadm | 1.34.1-1.1 | https://pkgs.k8s.io/core:/stable:/v1.34/deb  Packages
   kubeadm | 1.34.0-1.1 | https://pkgs.k8s.io/core:/stable:/v1.34/deb  Packages

 

3, 安装kubeadm、kubelet、kubectl

# 锁定指定版本v1.34.10
K8S_VERSION="1.34.10-1.1"
apt install -y kubelet=${K8S_VERSION} kubeadm=${K8S_VERSION} kubectl=${K8S_VERSION}
# 锁定版本防止自动升级
apt-mark hold kubelet kubeadm kubectl
# 校验版本
kubeadm version
kubectl version --client

 

三,部署 kube-vip 静态 Pod(所有 3 台 master 节点执行)

kube-vip 以静态 Pod方式运行在每台控制平面节点,接管 VIP 172.29.128.100,实现 APIServer 高可用

1, 预拉取 kube-vip 镜像(三台都执行)

# kube-vip最新稳定版适配k8s 1.34
ctr images pull ghcr.io/kube-vip/kube-vip:v1.2.2

 校验镜像是否存在

ctr images list
ctr images list | grep kube-vip

 

2, 生成 kube-vip配置文件(仅 master-01 执行)mkdir -p /etc/kubernetes/manifests

 

export VIP=172.29.128.100 #vip地址
export INTERFACE=eth0   #填你的真实网卡名
ctr run --rm --net-host ghcr.io/kube-vip/kube-vip:v1.2.2 kv-gen /kube-vip manifest pod \
--interface $INTERFACE \
--address $VIP \
--controlplane \
--services \
--arp \
--enableLoadBalancer \
--leaderElection | sudo tee /etc/kubernetes/manifests/kube-vip.yaml

  

生成的文件内容如下:

apiVersion: v1
kind: Pod
metadata:
  name: kube-vip
  namespace: kube-system
spec:
  containers:
  - args:
    - manager
    env:
    - name: vip_arp
      value: "true"
    - name: port
      value: "6443"
    - name: vip_nodename
      valueFrom:
        fieldRef:
          fieldPath: spec.nodeName
    - name: vip_interface
      value: eth0
    - name: vip_subnet
      value: "32"
    - name: dns_mode
      value: first
    - name: dhcp_mode
      value: ipv4
    - name: cp_enable
      value: "true"
    - name: cp_namespace
      value: kube-system
    - name: svc_enable
      value: "true"
    - name: svc_leasename
      value: plndr-svcs-lock
    - name: vip_leaderelection
      value: "true"
    - name: vip_leasename
      value: plndr-cp-lock
    - name: vip_leaseduration
      value: "15"
    - name: vip_renewdeadline
      value: "10"
    - name: vip_retryperiod
      value: "2"
    - name: lb_enable
      value: "true"
    - name: lb_port
      value: "6443"
    - name: lb_fwdmethod
      value: local
    - name: address
      value: 172.29.128.100
    - name: prometheus_server
      value: :2112
    image: ghcr.io/kube-vip/kube-vip:v1.2.2
    imagePullPolicy: IfNotPresent
    name: kube-vip
    resources: {}
    securityContext:
      capabilities:
        add:
        - NET_ADMIN
        - NET_RAW
        drop:
        - ALL
    volumeMounts:
    - mountPath: /etc/kubernetes/admin.conf
      name: kubeconfig
  hostAliases:
  - hostnames:
    - kubernetes
    ip: 127.0.0.1
  hostNetwork: true
  volumes:
  - hostPath:
      path: /etc/kubernetes/admin.conf
    name: kubeconfig
status: {}

 

3, 修改 /etc/kubernetes/manifests/kube-vip.yaml 文件的配置:

把 /etc/kubernetes/admin.conf 修改 为 /etc/kubernetes/super-admin.conf

 

4, 分发 kube-vip.yaml 到另外几台 master 节点

# master-01执行,替换对应IP
scp /etc/kubernetes/manifests/kube-vip.yaml root@172.29.132.68:/etc/kubernetes/manifests/
scp /etc/kubernetes/manifests/kube-vip.yaml root@172.29.132.69:/etc/kubernetes/manifests/

注意:每台机器的网卡名不一致时,分别修改三台 yaml 内vip_interface字段。

spec:
  containers:
  - args:
    - manager
    env:
    - name: vip_arp
      value: "true"
    - name: port
      value: "6443"
    - name: vip_nodename
      valueFrom:
        fieldRef:
          fieldPath: spec.nodeName
    - name: vip_interface
      value: eth0  #修改为三台机器真实的网卡名称

 

四,初始化master节点

1, 执行镜像预拉取(所有节点执行):

# 源镜像仓库(可替换阿里云/华为/本地私有仓)
SOURCE_REPO="registry.aliyuncs.com/google_containers"
# K8s标准目标仓库固定值
K8S_REPO="registry.k8s.io"
# 版本变量统一管理
K8S_VER="v1.34.10"
COREDNS_VER="v1.12.1"
ETCD_VER="3.6.5-0"
PAUSE_VER="3.10.1"

# 预先拉取镜像(单行命令)
kubeadm config images pull --kubernetes-version ${K8S_VER} --image-repository ${SOURCE_REPO}

# 逐条打tag 4个控制平面镜像
nerdctl tag ${SOURCE_REPO}/kube-apiserver:${K8S_VER}        ${K8S_REPO}/kube-apiserver:${K8S_VER}
nerdctl tag ${SOURCE_REPO}/kube-controller-manager:${K8S_VER} ${K8S_REPO}/kube-controller-manager:${K8S_VER}
nerdctl tag ${SOURCE_REPO}/kube-scheduler:${K8S_VER}        ${K8S_REPO}/kube-scheduler:${K8S_VER}
nerdctl tag ${SOURCE_REPO}/kube-proxy:${K8S_VER}            ${K8S_REPO}/kube-proxy:${K8S_VER}

# 特殊路径镜像单独处理
nerdctl tag ${SOURCE_REPO}/coredns:${COREDNS_VER}  ${K8S_REPO}/coredns/coredns:${COREDNS_VER}
nerdctl tag ${SOURCE_REPO}/pause:${PAUSE_VER}      ${K8S_REPO}/pause:${PAUSE_VER}
nerdctl tag ${SOURCE_REPO}/etcd:${ETCD_VER}        ${K8S_REPO}/etcd:${ETCD_VER}

 

--image-repository 备选仓库:

阿里云:registry.aliyuncs.com/google_containers
腾讯云:mirror.ccs.tencentyun.com/k8s
华为云:repo.huaweicloud.com/kubernetes
道客云:k8s.m.daocloud.io 

 

2, 集群初始化文件准备

查看kind默认配置

kubeadm config print init-defaults --component-configs KubeProxyConfiguration

生成配置文件样例 kubeadm-config.yaml

kubeadm config print init-defaults --component-configs KubeProxyConfiguration > kubeadm-init.yaml

修改kubeadm-init.yaml的几个配置(必须) 

#1. advertiseAddress: 1.2.3.4  修改成你自己master节点ip
advertiseAddress: 172.29.128.1
#2. nodeRegistration下面的name: node 修改成master节点名称
nodeRegistration:
  name: k8s-master-01
#3. apiServer:{}  ,先删掉左右大括号{},再添加所有master节点名称及ip、vip的ip或域名。(工作节点不需要添加)
apiServer:
  certSANs:
  - 172.29.128.100
  - k8s-master-01
  - k8s-worker-01
  - k8s-worder-02
  - 172.29.128.1
  - 172.29.132.68
  - 172.29.132.69
#4. 在apiVersion的前面增加controlPlaneEndpoint配置,填vip的ip地址(或域名)及端口
apiServer:
  certSANs:
  - 172.29.128.100
  - k8s-master-01
  - k8s-worker-01
  - k8s-worder-02
  - 172.29.128.1
  - 172.29.132.68
  - 172.29.132.69
controlPlaneEndpoint: 172.29.128.100:6443
apiVersion: kubeadm.k8s.io/v1beta4

#5. 在networking下增加子节点 podSubnet: 10.244.0.0/16或者podSubnet: 192.168.0.0/16
networking:
  dnsDomain: cluster.local
  serviceSubnet: 10.96.0.0/12
  podSubnet: 192.168.0.0/16
#6. ipvs下面的strictARP: false  改成 strictARP: true
ipvs:
  excludeCIDRs: null
  minSyncPeriod: 0s
  scheduler: ""
  strictARP: true
  syncPeriod: 0s
  tcpFinTimeout: 0s
  tcpTimeout: 0s
  udpTimeout: 0s

#7. nftables: 节点上面的mode: ""  改成 mode: "ipvs"
metricsBindAddress: ""
mode: "ipvs"
nftables:
  masqueradeAll: false
  masqueradeBit: null
  minSyncPeriod: 0s
  syncPeriod: 0s
#8. kubernetesVersion: 1.xx.x 版本号改成你要安装的版本
kubernetesVersion: 1.34.10

 

2,初始化master节点

用kubeadm-init.yaml 文件初始化集群

kubeadm init --config kubeadm-init.yaml --upload-certs --v=9

 

用纯命令初始化主master节点

kubeadm init \
  --kubernetes-version=v1.34.10 \
  --control-plane-endpoint=172.29.128.100:6443 \
  --apiserver-advertise-address=172.29.128.1 \
  --pod-network-cidr=192.168.0.0/16 \
  --service-cidr=10.96.0.0/12 \
  --upload-certs \
  --cri-socket=/run/containerd/containerd.sock
参数说明:
  • --control-plane-endpoint:kube-vip VIP,集群统一接入地址
  • --upload-certs:将控制平面证书上传到 Secret,后续节点 join control-plane 免拷贝证书
  • `pod 网段 Calico 标准 192.168.0.0/16

master节点初始化成功后,输出:

Your Kubernetes control-plane has initialized successfully!

To start using your cluster, you need to run the following as a regular user:

  mkdir -p $HOME/.kube
  sudo cp -i /etc/kubernetes/admin.conf $HOME/.kube/config
  sudo chown $(id -u):$(id -g) $HOME/.kube/config

Alternatively, if you are the root user, you can run:

  export KUBECONFIG=/etc/kubernetes/admin.conf

You should now deploy a pod network to the cluster.
Run "kubectl apply -f [podnetwork].yaml" with one of the options listed at:
  https://kubernetes.io/docs/concepts/cluster-administration/addons/

You can now join any number of control-plane nodes running the following command on each as root:

  kubeadm join 172.29.128.100:6443 --token abcdef.0123456789abcdef \
        --discovery-token-ca-cert-hash sha256:2ffb0cb00bae4888b350db6e2ad2438ccec120b5c9955d450c6d1c74424f1fa2 \
        --control-plane --certificate-key 8154e310eafe6f2531a681bf0d8c2e6f586def63dd6b1d6116268840d17002ff

Please note that the certificate-key gives access to cluster sensitive data, keep it secret!
As a safeguard, uploaded-certs will be deleted in two hours; If necessary, you can use
"kubeadm init phase upload-certs --upload-certs" to reload certs afterward.

Then you can join any number of worker nodes by running the following on each as root:

kubeadm join 172.29.128.100:6443 --token abcdef.0123456789abcdef \
        --discovery-token-ca-cert-hash sha256:2ffb0cb00bae4888b350db6e2ad2438ccec120b5c9955d450c6d1c74424f1fa2

记录输出的 2 条 join 命令(保存备用)

 

3, 拷贝 kubeconfig,添加普通用户执行权限

mkdir -p $HOME/.kube
sudo cp -i /etc/kubernetes/admin.conf $HOME/.kube/config
sudo chown $(id -u):$(id -g) $HOME/.kube/config

 

4,查看三台master节点有没有VIP

查看pod

kubectl get pod -A

会看到有kube-vip-开头的三条pod记录,状态全部为Running,并且Ready全部为1/1,就表示kube-vip静态pod启动成功。

kube-system   kube-vip-k8s-master-01                     1/1     Running   0 (66s ago)     4m38s
kube-system   kube-vip-k8s-worker-01                     1/1     Running   0 (2m54s ago)   18m
kube-system   kube-vip-k8s-worker-02                     1/1     Running   0 (2m50s ago)   18m

逐个在三台master节点校验eth0网卡有没有VIP

ip a s
ip a s | grep 172.29.128.100

如果vip创建成功,在其中一台的ip a s  命令会输出含有 172.29.128.100/32 的信息:

eth0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc fq_codel state UP group default qlen 1000
    link/ether 00:16:3e:3c:a2:4a brd ff:ff:ff:ff:ff:ff
    altname enp0s5
    altname ens5
    inet 172.29.128.1/20 metric 100 brd 172.29.143.255 scope global dynamic eth0
       valid_lft 1891831497sec preferred_lft 1891831497sec
    inet 172.29.128.100/32 scope global
       valid_lft forever preferred_lft forever
    inet6 fe80::216:3eff:fe3c:a24a/64 scope link
       valid_lft forever preferred_lft forever

如果没有 172.29.128.100的输出信息,说明VIP创建失败,集群不可用。只有VIP创建成功后,才可以继续下一步加入其它控制面板。

 

5, 加入其它master节点与工作节点
(1) 另外两台加入控制平面(master 节点):

kubeadm join 172.29.128.100:6443 \
--token xxx \
--discovery-token-ca-cert-hash sha256:xxxx \
--control-plane \
--certificate-key xxxxx \
--apiserver-advertise-address=172.29.132.68  # 本机内网IP,第二台替换172.29.132.69

 

(2)新 master 节点拷贝 kubeconfig(每台新增 master 执行)

mkdir -p $HOME/.kube
sudo scp root@172.29.128.1:/etc/kubernetes/admin.conf $HOME/.kube/config
sudo chown $(id -u):$(id -g) $HOME/.kube/config

 

(3) 加入 worker 节点:

kubeadm join 172.29.128.100:6443 --token xxx --discovery-token-ca-cert-hash sha256:xxx -v 9

 

(4) 验证节点数量

kubectl get nodes
# 三台全部为control-plane:True,master污点默认存在
kubectl describe node k8s-master-01 | grep Taints

(5) :移除 master 节点污点,允许调度 Pod(ALL-IN-ONE 混合节点关键)

# 三台节点分别执行,或在master-01批量执行
kubectl taint nodes k8s-master-01 node-role.kubernetes.io/control-plane:NoSchedule-
kubectl taint nodes k8s-worker-01 node-role.kubernetes.io/control-plane:NoSchedule-
kubectl taint nodes k8s-worker-02 node-role.kubernetes.io/control-plane:NoSchedule-

或者一次性清除所有master节点污点

kubectl taint nodes --all node-role.kubernetes.io/control-plane- 

 

6, token过期重置 

token 过期重置:

kubeadm token create --print-join-command

证书 key 过期重置:

kubeadm init phase upload-certs --upload-certs

 

五,安装 calico网络插件

#下载calico官方配置文件(适合k8s v1.34.10的版本)
curl -O calico-v3.32.1.yaml https://raw.githubusercontent.com/projectcalico/calico/v3.32.1/manifests/calico.yaml
#替换为国内daocloud镜像源
sed -i 's|quay.io/calico|m.daocloud.io/quay.io/calico|g' calico-v3.32.1.yaml
#安装
kubectl apply -f calico-v3.32.1.yaml
# 等待calico全部pod就绪
kubectl get pods -n kube-system -w
# 全部ready后节点状态变为Ready
kubectl get nodes

查看calico健康状态

kubectl get pod -A -n kube-system -w

 

集群健康检查

kubectl get cs
kubectl get nodes
# 三台control-plane+worker全部Ready

 

六,kube-vip VIP高可用校验

1,验证VIP是否有漂移

查看 VIP 在哪台节点:ip addr | grep 172.29.128.100
关闭当前 leader 节点 kube-vip 容器,观察 VIP 是否有自动漂移至另外一台

# 关闭kube-vip静态pod(删除yaml,kubelet自动销毁)
mv /etc/kubernetes/manifests/kube-vip.yaml /tmp/
# 等待10s,再移回,模拟故障
mv /tmp/kube-vip.yaml /etc/kubernetes/manifests/

 

2,API Server 连通性

# 任意节点通过VIP访问集群
kubectl --server=https://172.29.128.100:6443 get nodes

 

七,卸载kube-vip(每台master节点执行)

1,如果要删除kube-vip,就删掉 /etc/kubernetes/manifests/kube-vip.yaml ,然后重启kubelet

# 删除静态清单文件
rm -f /etc/kubernetes/manifests/kube-vip.yaml
# 重启kubelet,立刻销毁kube-vip容器
systemctl restart kubelet

 2. 手动清除宿主机残留 VIP 地址

kube-vip 退出后 VIP 可能残留在网卡,手动清理:

VIP="172.29.128.100"
INTERFACE="eth0"
ip addr del ${VIP}/32 dev ${INTERFACE}
# 确认VIP已移除
ip a | grep ${VIP}

3. 清理本地镜像(可选,保留镜像可跳过)

ctr images rm ghcr.io/kube-vip/kube-vip:v1.2.2

 

posted @ 2026-08-04 14:00  民工黑猫  阅读(1)  评论(0)    收藏  举报