ubuntu26.04,离线升级k8s,根据kubeadm的deb离线包 + 离线镜像,从现有k8s-v1.32.13升级到k8s-v1.33.9(NLB + 3 master + 2 worker节点)

ubuntu 26.04。

集群规划(5 节点)

master节点01,主机名:k8s-master-01,ip:172.21.64.36

master节点02,主机名:k8s-master-02,ip:172.21.64.37

master节点03,主机名:k8s-master-03,ip:172.21.64.38

工作节点01:主机名:k8s-worker-01,ip:172.21.64.39

工作节点02:主机名:k8s-worker-02,ip:172.21.64.40

 
机器名 内网 ip 角色
k8s-master-01 172.21.64.36 master
k8s-master-02 172.21.64.37 master
k8s-master-03 172.21.64.38 master
k8s-worker-01 172.21.64.39 worker
k8s-worker-02 172.21.64.40 worker

 一,升级前准备离线包

1. 下载kubeadm -v1.33.9离线包

离线资源清单及下载流程参考:ubunbu 26.04,用bash脚本自动下载kubeadm的deb离线安装包

离线包目录结构:

/data/k8s/k8s-v1.33.9
├── calico-images-v3.31.6.list
├── calico-images-v3.31.6.tar
├── calico-v3.31.6.yaml
├── ingress-nginx-images-v1.14.5.list
├── ingress-nginx-images-v1.14.5.tar
├── ingress-nginx-v1.14.5.yaml
├── k8s-debs
│   ├── containerd.io_2.3.3-1~ubuntu.26.04~resolute_amd64.deb
│   ├── cri-tools_1.33.0-1.1_amd64.deb
│   ├── kubeadm_1.33.9-1.1_amd64.deb
│   ├── kubectl_1.33.9-1.1_amd64.deb
│   ├── kubelet_1.33.9-1.1_amd64.deb
│   └── kubernetes-cni_1.6.0-1.1_amd64.deb
├── k8s-images-v1.33.9.list
├── k8s-images-v1.33.9.tar
└── k8s-offline.conf

 

2. 把离线包上传到所有节点

#!/bin/bash
set -euo pipefail

# 节点列表
nodes=(
172.21.64.36
172.21.64.37
172.21.64.38
172.21.64.39
172.21.64.40
)
src_dir="/data/k8s/k8s-v1.33.9"
dst_dir="/data/k8s/k8s-v1.33.9"

for ip in "${nodes[@]}"; do
    echo "====================================="
    echo "处理节点 $ip"
    echo "====================================="
    # 远程创建目录
    ssh root@"$ip" "mkdir -p ${dst_dir}"
    # 同步全部离线资源
    rsync -avz --progress ${src_dir}/ root@${ip}:${dst_dir}/
done

echo "✅ 所有节点离线资源分发完成"

 

 

二,备份etcd(仅master-01节点执行)

1. 安装etcdctl

mkdir -p /data/etcd
cd /data/etcd wget https://github.com/etcd-io/etcd/releases/download/v3.6.5/etcd-v3.6.5-linux-amd64.tar.gz tar -zxvf etcd-v3.6.5-linux-amd64.tar.gz cp etcd-v3.6.5-linux-amd64/etcdctl /usr/local/bin/ chmod +x /usr/local/bin/etcdctl #校验版本,必须输出3.6.5 etcdctl version

 

2.导出etcd数据库

# 备份etcd快照,保存到本地,故障回滚使用
mkdir -p /data/k8s ETCDCTL_API=3 etcdctl snapshot save /data/k8s/etcd-snapshot-pre-upgrade-v1.34.11.db.$(date +%Y%m%d) \ --endpoints=https://127.0.0.1:2379 \ --cacert=/etc/kubernetes/pki/etcd/ca.crt \d --cert=/etc/kubernetes/pki/etcd/server.crt \ --key=/etc/kubernetes/pki/etcd/server.key

 

三,升级

升级分三种角色:

节点 升级命令
第一个 master

kubeadm upgrade plan

kubeadm upgrade apply v1.33.9

其余 master kubeadm upgrade node
worker kubeadm upgrade node

1. 【第一阶段,所有节点导入镜像】

1.1 所有安装nerdctl(已经安装就跳过)

下载:https://github.com/containerd/nerdctl/releases/download/v2.3.4/nerdctl-2.3.4-linux-amd64.tar.gz

执行部署

curl https://github.com/containerd/nerdctl/releases/download/v2.3.4/nerdctl-2.3.4-linux-amd64.tar.gz
tar -zxvf nerdctl-2.3.4-linux-amd64.tar.gz
mv nerdctl /usr/local/bin/
chmod +x /usr/local/bin/nerdctl

# 同样配置默认命名空间
mkdir -p /etc/nerdctl
cat > /etc/nerdctl/nerdctl.toml <<EOF
namespace = "k8s.io"
address = "/run/containerd/containerd.sock"
cgroup_manager = "systemd"
EOF

 

1.2 批量分发镜像到其它节点

#!/bin/bash
set -euo pipefail

# 源&目标目录,所有节点保持相同路径
work_dir="/data/k8s/k8s-v1.33.9"

node_ips=(
"172.21.64.37"
"172.21.64.38"
"172.21.64.39"
"172.21.64.40"
)

for ip in "${node_ips[@]}"; do
    echo "==================== 分发到节点 ${ip} ===================="
    # 先在远端确保父目录存在
    ssh root@"${ip}" "mkdir -p $(dirname ${work_dir})"
    # -r 递归,--delete 可选:远端目录删除本地不存在的旧文件,按需开启
    rsync -av --progress "${work_dir}/" root@"${ip}":"${work_dir}/"
done

echo "====全部节点目录分发完成===="

 

1.3 批量导入镜像

#!/bin/bash
set -euo pipefail

# 定义目录变量
tar_dir="/data/k8s/k8s-v1.33.9"

node_ips=(
"172.21.64.37"
"172.21.64.38"
"172.21.64.39"
"172.21.64.40"
)

for ip in "${node_ips[@]}"; do
  echo "==================== 处理节点 ${ip} ===================="
  ssh root@${ip} "
set -euo pipefail
tar_dir=\"${tar_dir}\"
cd \"\${tar_dir}\"
ctr -n k8s.io images import k8s-images-*.tar
ctr -n k8s.io images import calico-images-*.tar
ctr -n k8s.io images import ingress-nginx-images-*.tar
ctr -n k8s.io images list | wc -l
"
done

echo "====全部节点镜像导入完成===="

 

2. 第一个 mastert升级(k8s-master-01)

重要:只有第一个 master 执行 kubeadm upgrade apply,其余 master 执行kubeadm upgrade node

#!/bin/bash
set -euo pipefail

# ========== 版本变量,只需要修改此处 ==========
k8s_version="v1.33.9"
deb_base_dir="/data/k8s/k8s-${k8s_version}/k8s-debs"
# ============================================

#解除版本锁定
apt-mark unhold cloud-init containerd.io cri-tools intel-microcode kubeadm kubectl kubelet kubernetes-cni

# 1. 确认升级计划(仅在master-01节点执行)
kubeadm upgrade plan

# 2. 升级kubeadm
cd "${deb_base_dir}"
dpkg -i kubeadm_*.deb

# 确认版本
kubeadm version -o short

# 执行控制平面升级(更新 apiserver/controller-manager/scheduler/etcd/coredns/kube-proxy 的 manifest)
kubeadm upgrade apply "${k8s_version}" -y

# 3. 升级containerd
#   备份配置(防止 dpkg 覆盖)
cp /etc/containerd/config.toml /etc/containerd/config.toml.bak.$(date +%Y%m%d)
dpkg -i containerd.io_*.deb
systemctl restart containerd

# 4. 升级 kubelet + kubectl
dpkg -i kubelet_*.deb kubectl_*.deb cri-tools_*.deb kubernetes-cni_*.deb

systemctl daemon-reload
systemctl restart kubelet

# 锁定版本自动更新
apt-mark hold cloud-init containerd.io cri-tools intel-microcode kubeadm kubectl kubelet kubernetes-cni

# 5. 等待节点 Ready
echo "等待节点变为Ready..."
kubectl wait --for=condition=Ready node/$(hostname) --timeout=15s
kubectl get nodes
containerd --version
kubelet --version

 

2.2 其它 master节点

k8s_version="v1.33.9"

# 1. 升级kubeadm
cd /data/k8s/k8s-${k8s_version}/k8s-debs

#解除版本锁定kubectl kubelet kubernetes-cni
apt-mark unhold cloud-init containerd.io cri-tools intel-microcode kubeadm 
# 升级kubeadm
dpkg -i kubeadm_*.deb
kubeadm upgrade node

# 3. 升级 containerd
# 备份配置
cp /etc/containerd/config.toml /etc/containerd/config.toml.bak.$(date +%Y%m%d)
dpkg -i containerd.io_*.deb
systemctl restart containerd

# 4. 升级 kubelet + kubectl
dpkg -i kubelet_*.deb kubectl_*.deb cri-tools_*.deb kubernetes-cni_*.deb
systemctl daemon-reload
systemctl restart kubelet
# 锁定版本自动更新
apt-mark hold cloud-init containerd.io cri-tools intel-microcode kubeadm kubectl kubelet kubernetes-cni
# 等待节点 Ready
echo "等待节点变为Ready..."
kubectl wait --for=condition=Ready node/$(hostname) --timeout=15s
kubectl get nodes
containerd --version
kubelet --version

 

3. 【第三阶段(一),第一个worker节点升级 】

worker 升级需要在 master-01 和 worker 本身 之间切换操作,穿插执行。以 k8s-worker-01 为例:

第 1 步:在 master-01 上先驱逐worker-01节点

kubectl drain k8s-worker-01 --ignore-daemonsets --delete-emptydir-data

 

第 2 步:在 k8s-worker-01 上执行升级

k8s_version="v1.33.9"
cd /data/k8s/k8s-${k8s_version}/k8s-debs
#解除版本锁定
apt-mark unhold cloud-init containerd.io cri-tools intel-microcode kubeadm kubectl kubelet kubernetes-cni

# 升级kubeadm
dpkg -i kubeadm_*.deb
kubeadm upgrade node


# 升级 containerd
# 先备份配置(防止 dpkg 覆盖)
cp /etc/containerd/config.toml /etc/containerd/config.toml.bak.$(date +%Y%m%d)
dpkg -i containerd.io_*.deb

# 升级 kubelet + kubectl
dpkg -i kubelet_*.deb kubectl_*.deb cri-tools_*.deb kubernetes-cni_*.deb

#重启
systemctl daemon-reload
systemctl restart containerd
systemctl restart kubelet
# 锁定版本自动更新
apt-mark hold cloud-init containerd.io cri-tools intel-microcode kubeadm kubectl kubelet kubernetes-cni

 

第 3 步:回到 master-01 上 取消驱逐 worker-01

kubectl uncordon k8s-worker-01

 第 4 步:确认 Ready 后,对 k8s-worker-02 重复同样操作

 

4. 【第三阶段(二),第二个worker节点升级 】

worker 升级需要在 master-01 和 worker 本身 之间切换操作,穿插执行。以 k8s-worker-01 为例:

第 1 步:在任意master节点上先驱逐worker-02节点

kubectl drain k8s-worker-02 --ignore-daemonsets --delete-emptydir-data

 

第 2 步:在 k8s-worker-01 上执行升级

k8s_version="v1.33.9"
cd /data/k8s/k8s-${k8s_version}/k8s-debs
#解除版本锁定
apt-mark unhold cloud-init containerd.io cri-tools intel-microcode kubeadm kubectl kubelet kubernetes-cni

# 升级kubeadm
dpkg -i kubeadm_*.deb
kubeadm upgrade node


# 升级 containerd
# 先备份配置(防止 dpkg 覆盖)
cp /etc/containerd/config.toml /etc/containerd/config.toml.bak.$(date +%Y%m%d)
dpkg -i containerd.io_*.deb

# 升级 kubelet + kubectl
dpkg -i kubelet_*.deb kubectl_*.deb cri-tools_*.deb kubernetes-cni_*.deb

#重启
systemctl daemon-reload
systemctl restart containerd
systemctl restart kubelet
# 锁定版本自动更新
apt-mark hold cloud-init containerd.io cri-tools intel-microcode kubeadm kubectl kubelet kubernetes-cni

 

第 3 步:回到任意master节点, 取消驱逐 worker-02

kubectl uncordon k8s-worker-02

 第 4 步:确认 Ready 后,对 k8s-worker-03 /  k8s-worker-04 / k8s-worker-05 等重复同样的操作

 

5. 【第四阶段,在master-01节点升级calico 与ingress】

caliico与ingress  可以兼容三个大版本k8s,如果这个版本需要更新calico与 ingress。

把所有worker节点升级完后再升级calico 与 ingress

kubectl apply -f calico-v3.31.6.yaml  
kubectl apply -f ingress-nginx-v1.14.5.yaml 

 

四,最终验证

所有节点升级完后:

kubectl get nodes -owide
# 5 个节点 VERSION 全部 v1.33.9,STATUS Ready

kubectl get pods -A -owide
# 所有 Pod Running,没有 CrashLoopBackOff

kubectl get pods -A | grep -v Running | grep -v Completed
# 应该没有输出(除了正常的 Completed Job)

输出:

root@k8s-master-01:/data/k8s/k8s-v1.33.9/k8s-debs# kubectl get nodes -owide
NAME            STATUS   ROLES           AGE   VERSION   INTERNAL-IP    EXTERNAL-IP   OS-IMAGE           KERNEL-VERSION     CONTAINER-RUNTIME
k8s-master-01   Ready    control-plane   17h   v1.33.9   172.21.64.36   <none>        Ubuntu 26.04 LTS   7.0.0-28-generic   containerd://2.3.3
k8s-master-02   Ready    control-plane   15h   v1.33.9   172.21.64.37   <none>        Ubuntu 26.04 LTS   7.0.0-28-generic   containerd://2.3.3
k8s-master-03   Ready    control-plane   15h   v1.33.9   172.21.64.38   <none>        Ubuntu 26.04 LTS   7.0.0-28-generic   containerd://2.3.3
k8s-worker-01   Ready    <none>          14h   v1.33.9   172.21.64.39   <none>        Ubuntu 26.04 LTS   7.0.0-28-generic   containerd://2.3.3
k8s-worker-02   Ready    <none>          14h   v1.33.9   172.21.64.40   <none>        Ubuntu 26.04 LTS   7.0.0-28-generic   containerd://2.3.3
root@k8s-master-01:/data/k8s/k8s-v1.33.9/k8s-debs# kubectl get pod -A -owide
NAMESPACE     NAME                                       READY   STATUS    RESTARTS        AGE     IP                NODE            NOMINATED NODE   READINESS GATES
kube-system   calico-kube-controllers-678b6c5f64-8lt4p   1/1     Running   2 (134m ago)    17h     192.168.151.134   k8s-master-01   <none>           <none>
kube-system   calico-node-74l7c                          1/1     Running   1 (40m ago)     14h     172.21.64.40      k8s-worker-02   <none>           <none>
kube-system   calico-node-ccskt                          1/1     Running   1 (40m ago)     14h     172.21.64.39      k8s-worker-01   <none>           <none>
kube-system   calico-node-mvqx6                          1/1     Running   1 (141m ago)    15h     172.21.64.37      k8s-master-02   <none>           <none>
kube-system   calico-node-slmvj                          1/1     Running   1 (155m ago)    17h     172.21.64.36      k8s-master-01   <none>           <none>
kube-system   calico-node-xv5qh                          1/1     Running   1 (139m ago)    15h     172.21.64.38      k8s-master-03   <none>           <none>
kube-system   coredns-674b8bbfcf-9k624                   1/1     Running   0               4m2s    192.168.183.129   k8s-master-03   <none>           <none>
kube-system   coredns-674b8bbfcf-dqw49                   1/1     Running   0               2m7s    192.168.36.194    k8s-worker-01   <none>           <none>
kube-system   etcd-k8s-master-01                         1/1     Running   2 (21m ago)     21m     172.21.64.36      k8s-master-01   <none>           <none>
kube-system   etcd-k8s-master-02                         1/1     Running   2 (9m11s ago)   9m11s   172.21.64.37      k8s-master-02   <none>           <none>
kube-system   etcd-k8s-master-03                         1/1     Running   2 (7m12s ago)   7m13s   172.21.64.38      k8s-master-03   <none>           <none>
kube-system   kube-apiserver-k8s-master-01               1/1     Running   2 (21m ago)     21m     172.21.64.36      k8s-master-01   <none>           <none>
kube-system   kube-apiserver-k8s-master-02               1/1     Running   2 (9m11s ago)   9m11s   172.21.64.37      k8s-master-02   <none>           <none>
kube-system   kube-apiserver-k8s-master-03               1/1     Running   2 (7m12s ago)   7m13s   172.21.64.38      k8s-master-03   <none>           <none>
kube-system   kube-controller-manager-k8s-master-01      1/1     Running   1 (21m ago)     21m     172.21.64.36      k8s-master-01   <none>           <none>
kube-system   kube-controller-manager-k8s-master-02      1/1     Running   1 (9m11s ago)   9m11s   172.21.64.37      k8s-master-02   <none>           <none>
kube-system   kube-controller-manager-k8s-master-03      1/1     Running   1 (7m12s ago)   7m13s   172.21.64.38      k8s-master-03   <none>           <none>
kube-system   kube-proxy-6tfgz                           1/1     Running   0               6m46s   172.21.64.36      k8s-master-01   <none>           <none>
kube-system   kube-proxy-7dkxq                           1/1     Running   0               7m12s   172.21.64.38      k8s-master-03   <none>           <none>
kube-system   kube-proxy-k6s2r                           1/1     Running   0               7m20s   172.21.64.37      k8s-master-02   <none>           <none>
kube-system   kube-proxy-vk6p7                           1/1     Running   0               7m18s   172.21.64.40      k8s-worker-02   <none>           <none>
kube-system   kube-proxy-wqbvp                           1/1     Running   0               7m19s   172.21.64.39      k8s-worker-01   <none>           <none>
kube-system   kube-scheduler-k8s-master-01               1/1     Running   1 (21m ago)     21m     172.21.64.36      k8s-master-01   <none>           <none>
kube-system   kube-scheduler-k8s-master-02               1/1     Running   1 (9m11s ago)   9m11s   172.21.64.37      k8s-master-02   <none>           <none>
kube-system   kube-scheduler-k8s-master-03               1/1     Running   1 (7m12s ago)   7m13s   172.21.64.38      k8s-master-03   <none>           <none>

 

posted @ 2026-08-19 12:24  民工黑猫  阅读(20)  评论(0)    收藏  举报