ubunbu 26.04,用bash脚本自动下载kubeadm的deb离线安装包 + containerd.io的deb离线安装包+ 离线镜像包

准备一台没有安装过containerd、并且没有安装过kubeadm、kubelet、kubectl的ubuntu 26.04的是脑。

一,离线资源清单

1.ubuntu26.04、 kubernetes、containerd依赖包清单

资源名称 deb名称 示例
utuntu20.04系统依赖
socat 
conntrack 
iproute2 
iptables 
net-tools 
iputils-ping 
ethtool 
ebtables 
apt-transport-https 
ca-certificates 
gnupg 
lsb-release
26.04
containerd

 containerd.io_${version}_amd64.deb

 cri-tools_${version}_amd64.deb

 containerd.io_2.3.3-1~ubuntu.26.04~resolute_amd64.deb

 cri-tools_1.32.0-1.1_amd64.deb

kubernetes

kubeadm_${version}_amd64.deb

kubectl_${version}_amd64.deb

kubelet_${version}_amd64.deb

kubernetes-cni_${version}_amd64.deb

kubeadm_1.32.13-1.1_amd64.deb

kubectl_1.32.13-1.1_amd64.deb

kubelet_1.32.13-1.1_amd64.deb

kubernetes-cni_1.6.0-1.1_amd64.deb

2. kubeadm、calico、ingress需要的镜像清单

资源名称 镜像 示例
kubeadm镜像

registry.k8s.io/kube-apiserver:${version}

registry.k8s.io/kube-controller-manager:${version}

registry.k8s.io/kube-scheduler:${version}

registry.k8s.io/kube-proxy:${version}

registry.k8s.io/etcd:${etcd_version}

registry.k8s.io/coredns/coredns:${coredns_version}

registry.k8s.io/pause:${pause_version}

registry.k8s.io/kube-apiserver:v1.36.3

registry.k8s.io/kube-controller-manager:v1.36.3

registry.k8s.io/kube-scheduler:v1.36.3

registry.k8s.io/kube-proxy:v1.36.3

registry.k8s.io/etcd:3.5.18-0

registry.k8s.io/coredns/coredns:v1.12.0

registry.k8s.io/pause:3.10.1

calico镜像

quay.io/calico/cni:${version}

quay.io/calico/node:${version}

quay.io/calico/kube-controllers:${version}


quay.io/calico/cni:v3.31.6

quay.io/calico/node:v3.31.6

quay.io/calico/kube-controllers:v3.31.6

 ingress镜像  

registry.k8s.io/ingress-nginx/controller:${version}

registry.k8s.io/ingress-nginx/kube-webhook-certgen:${certgen_version}

registry.k8s.io/ingress-nginx/controller:v1.15.1

registry.k8s.io/ingress-nginx/kube-webhook-certgen:v1.6.9

 

3. yaml部署文件清单

yaml名称 yaml文件名 示例
calico部署yaml calico-${calico_ver}.yaml calico-v1.32.1.yaml
ingress部署yaml ingress-nginx-${ingress_ver}.yaml ingress-nginx-v1.15.1.yaml

 

4.calico版与本k8s版本对应规则

规则:Calico Open Source 一个大版本支持连续 3 个 K8s minor 版本;patch 版本不影响兼容性。

Calico 开源版本与 K8S 官方兼容矩阵:

Kubernetes 版本 生产推荐 Calico 版本 calico.yaml 下载地址模板
v1.32.x v3.31.6 https://raw.githubusercontent.com/projectcalico/calico/v3.31.6/manifests/calico.yaml
v1.33.x v3.31.6 https://raw.githubusercontent.com/projectcalico/calico/v3.31.6/manifests/calico.yaml
v1.34.x v3.32.1 https://raw.githubusercontent.com/projectcalico/calico/v3.32.1/manifests/calico.yaml
v1.35.x v3.32.1 https://raw.githubusercontent.com/projectcalico/calico/v3.32.1/manifests/calico.yaml
v1.36.x v3.32.1 https://raw.githubusercontent.com/projectcalico/calico/v3.32.1/manifests/calico.yaml

官方文档入口:https://docs.tigera.io/calico/latest/getting-started/kubernetes/requirements

 

5. ingress与k8s版本对应规则

Kubernetes 版本 生产推荐ingress-nginx-controller版本 ingress-deploy.yaml 下载地址模板
v1.32.x v1.14.5 https://raw.githubusercontent.com/kubernetes/ingress-nginx/controller-v1.14.5/deploy/static/provider/cloud/deploy.yaml
v1.33.x v1.14.5 https://raw.githubusercontent.com/kubernetes/ingress-nginx/controller-v1.14.5/deploy/static/provider/cloud/deploy.yaml
v1.34.x v1.15.1 https://raw.githubusercontent.com/kubernetes/ingress-nginx/controller-v1.15.1/deploy/static/provider/cloud/deploy.yaml
v1.35.x v1.15.1 https://raw.githubusercontent.com/kubernetes/ingress-nginx/controller-v1.15.1/deploy/static/provider/cloud/deploy.yaml
v1.36.x 需要使用F5 NGINX Ingress Controller v5.54
社区版ingress-nginx已停止维护

https://raw.githubusercontent.com/nginxinc/kubernetes-ingress/v5.5.4/deploy/crds.yaml

https://raw.githubusercontent.com/nginxinc/kubernetes-ingress/v5.5.4/deploy/nginx-ingress.yaml

 

 

二,安装必备工具

1. 安装系统工具

apt update && apt install -y ca-certificates curl wget gnupg lsb-release

 

2. 安装nerdctl

下载nerdctl完整包:nerdctl-full(推荐离线,一步到位,自带 buildkit) 

完整版下载: https://github.com/containerd/nerdctl/releases/download/v2.3.3/nerdctl-full-2.3.3-linux-amd64.tar.gz

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

下载后的离线文件清单(完整版本或精简版下载其一即可)

nerdctl-full-2.3.3-linux-amd64.tar.gz
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

 

三,下载deb离线包

规划下载的离线包目录结构:

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

 

1. 全局变量配置文件

mkdir -p /data/k8s/k8s-v1.32.13
vi /data/k8s/k8s-v1.32.13/k8s-offline.conf

k8s-offline.conf 文件内容:

# K8s离线资源下载统一配置
# 提供k8s & containerd数据源、deb包下载、镜像拉取脚本共用版本与路径变量
base_dir="/data/k8s"
# k8s_apt_branch:apt源分支 1.32 / 1.33 / 1.34 / 1.35 / 1.36
k8s_apt_branch="v1.32"
k8s_pkg_ver="1.32.13-1.1"
# containerd.io deb安装包完整版本号
containerd_io_pkg_ver="2.3.3-1~ubuntu.26.04~resolute"
# k8s版本
k8s_ver="v1.32.13"
# kubeadm二进制文件目录
kubeadm_bin_dir="/data/k8s/kubeadm-bin"
calico_ver="v3.31.6"
ingress_ver="v1.14.5"

 

2. 下载ubuntu 26.04系统依赖(注意加了圆括号新开shell,exit不会退出终端)

进到 k8s-offline.conf所在的目录执行:

#!/bin/bash
set -euo pipefail
(
# 配置文件:当前版本目录内的离线构建配置
conf_file="./k8s-offline.conf"

# 1. 判断配置文件
if [ ! -f "${conf_file}" ];then
    echo "ERROR: 当前目录缺少配置文件 ${conf_file}"
    echo "当前工作目录:$(pwd)"
    echo "请进入对应k8s版本目录执行脚本!"
    exit 1
fi
source "${conf_file}"

# 变量校验
check_var() {
    local name="$1"
    if [[ -z "${!name:-}" ]]; then
        echo "ERROR: 配置变量【${name}】不能为空,请检查 ${conf_file}"
        exit 1
    fi
}
check_var base_dir

# =====================
# 定义本地变量,从全局配置读取值
# =====================
local_base_dir="${base_dir}"
local_sysdep_pack_dir="ubuntu-26.04-sys-debs"
local_sysdep_tar_filename="${local_sysdep_pack_dir}.tar.gz"

# 清理apt缓存旧包
apt clean
rm -f /var/cache/apt/archives/*.deb

rm -rf "${local_base_dir}/${local_sysdep_pack_dir}"
mkdir -p "${local_base_dir}/${local_sysdep_pack_dir}"
cd "${local_base_dir}/${local_sysdep_pack_dir}"

apt-get download \
socat \
conntrack \
iproute2 \
iptables \
net-tools \
iputils-ping \
ethtool \
ebtables \
apt-transport-https \
ca-certificates \
gnupg \
lsb-release

rm -f "${local_base_dir}/${local_sysdep_tar_filename}"
cd "${local_base_dir}"
tar -zcvf "${local_sysdep_tar_filename}" "${local_sysdep_pack_dir}"

echo -e "\n系统依赖包下载完成:${local_base_dir}/${local_sysdep_tar_filename}"
ls -lh "${local_base_dir}/${local_sysdep_pack_dir}"
)

 

3.配置仓库

1)  配置新版本containerd仓库源

#!/bin/bash
# 探测信息赋值本地副本变量
local_arch=$(dpkg --print-architecture)
local_ubuntu_codename=$(lsb_release -cs)

# 清理旧docker源
rm -f /etc/apt/sources.list.d/docker.list
rm -f /etc/apt/trusted.gpg.d/docker*.gpg

# 阿里云docker-ce公钥
curl -fsSL https://mirrors.aliyun.com/docker-ce/linux/ubuntu/gpg | gpg --dearmor -o /etc/apt/trusted.gpg.d/docker.gpg

# 添加阿里云docker-ce源(包含 containerd.io)
echo "deb [arch=${local_arch} signed-by=/etc/apt/trusted.gpg.d/docker.gpg] https://mirrors.aliyun.com/docker-ce/linux/ubuntu ${local_ubuntu_codename} stable" | tee /etc/apt/sources.list.d/docker.list

apt update

echo -e "\n=== 当前架构:${local_arch},系统代号:${local_ubuntu_codename} ==="
echo -e "\n=== 查看当前源可用 containerd.io 版本 ==="
apt-cache madison containerd.io

 

2)  配置k8s仓库源,需要哪个版本的k8s就配置哪个版本的仓库源

同一时间只能配置一个k8s版本,多个k8s版本需要先删除旧的k8s源,然后逐个配置 

#!/bin/bash
set -euo pipefail
(
conf_file="./k8s-offline.conf"

if [ ! -f "${conf_file}" ];then
    echo "ERROR: 当前目录缺少配置文件 ${conf_file}"
    echo "当前工作目录:$(pwd)"
    echo "请进入对应k8s版本目录执行脚本!"
    exit 1
fi
source "${conf_file}"

# 校验依赖变量
check_var() {
    local name="$1"
    if [[ -z "${!name:-}" ]]; then
        echo "ERROR: 配置变量【${name}】不能为空,请检查 ${conf_file}"
        exit 1
    fi
}
check_var k8s_apt_branch

# ======================
# 定义本地变量,从全局配置读取值
#
apt源分支 1.32 / 1.33 / 1.34 / 1.35 / 1.36
# ======================
local_k8s_apt_branch="${k8s_apt_branch}"

# 后续全部使用 local_ 前缀本地变量
# 清理旧k8s源
rm -f /etc/apt/sources.list.d/kubernetes.list
rm -f /etc/apt/trusted.gpg.d/kubernetes-*.gpg

# 导入对应版本密钥
curl -fsSL "https://pkgs.k8s.io/core:/stable:/${local_k8s_apt_branch}/deb/Release.key" | gpg --dearmor -o "/etc/apt/trusted.gpg.d/kubernetes-v${local_k8s_apt_branch}.gpg"

# 添加对应版本apt源
echo "deb [signed-by=/etc/apt/trusted.gpg.d/kubernetes-v${local_k8s_apt_branch}.gpg] https://pkgs.k8s.io/core:/stable:/${local_k8s_apt_branch}/deb/ /" | tee /etc/apt/sources.list.d/kubernetes.list

# 更新缓存
apt update

# 查看可用kubeadm版本
echo -e "\n========== 可用 kubeadm 版本列表 =========="
apt-cache madison kubeadm
)

 

4. 下载离线deb包(containerd、kubeadm、kubelet、kubectl)

#!/bin/bash
set -euo pipefail
(
conf_file="./k8s-offline.conf"

# 校验配置文件存在
if [ ! -f "${conf_file}" ];then
    echo "ERROR: 当前目录缺少配置文件 ${conf_file}"
    echo "当前工作目录:$(pwd)"
    echo "请进入对应k8s版本目录执行脚本!"
    exit 1
fi
source "${conf_file}"

# 变量校验函数
check_var() {
    local name="$1"
    if [[ -z "${!name:-}" ]]; then
        echo "ERROR: 配置变量【${name}】不能为空,请检查 ${conf_file}"
        exit 1
    fi
}
# 校验公共配置原始变量
check_var base_dir
check_var k8s_pkg_ver
check_var containerd_io_pkg_ver

# ======================
# 脚本本地副本变量
# ======================
local_base_dir="${base_dir}"
local_k8s_pkg_ver="${k8s_pkg_ver}"
local_containerd_io_pkg_ver="${containerd_io_pkg_ver}"

# 衍生变量,基于本地副本计算,目录带上v前缀 k8s-v1.32.13
local_k8s_short_ver=$(echo "${local_k8s_pkg_ver}" | cut -d'-' -f1)
local_deb_dir="${local_base_dir}/k8s-v${local_k8s_short_ver}/k8s-debs"

rm -rf "${local_deb_dir}"
mkdir -p "${local_deb_dir}"
cd "${local_deb_dir}"

# 清理apt缓存旧包
apt clean
rm -f /var/cache/apt/archives/*.deb

# 下载核心deb包
apt-get download \
kubeadm=${local_k8s_pkg_ver} \
kubelet=${local_k8s_pkg_ver} \
kubectl=${local_k8s_pkg_ver} \
containerd.io=${local_containerd_io_pkg_ver} \
cri-tools \
kubernetes-cni

echo -e "\ndeb包下载完成,目录:${local_deb_dir}"
ls -lh "${local_deb_dir}"
)

 

输出:

total 111M
-rw-r--r-- 1 root root 22M Aug 13 20:51 containerd.io_2.3.3-1~ubuntu.26.04~resolute_amd64.deb
-rw-r--r-- 1 root root 16M Dec  9  2024 cri-tools_1.32.0-1.1_amd64.deb
-rw-r--r-- 1 root root 12M Feb 27 08:18 kubeadm_1.32.13-1.1_amd64.deb
-rw-r--r-- 1 root root 11M Feb 27 08:18 kubectl_1.32.13-1.1_amd64.deb
-rw-r--r-- 1 root root 15M Feb 27 08:18 kubelet_1.32.13-1.1_amd64.deb
-rw-r--r-- 1 root root 37M Dec 12  2024 kubernetes-cni_1.6.0-1.1_amd64.deb

  

四. 安装containerd 2.3(安装一次即可,高版本continerd向下兼容k8s各版本) 

#!/bin/bash
set -euo pipefail
(
conf_file="./k8s-offline.conf"

if [ ! -f "${conf_file}" ];then
    echo "ERROR: 当前目录缺少配置文件 ${conf_file}"
    echo "当前工作目录:$(pwd)"
    echo "请进入对应k8s版本目录执行脚本!"
    exit 1
fi
source "${conf_file}"

# 变量校验
check_var() {
    local name="$1"
    if [[ -z "${!name:-}" ]]; then
        echo "ERROR: 配置变量【${name}】不能为空,请检查 ${conf_file}"
        exit 1
    fi
}
check_var base_dir
check_var k8s_pkg_ver

# 本地变量副本
local_base_dir="${base_dir}"
local_k8s_pkg_ver="${k8s_pkg_ver}"
local_k8s_short_ver=$(echo "${local_k8s_pkg_ver}" | cut -d'-' -f1)
local_deb_dir="${local_base_dir}/k8s-v${local_k8s_short_ver}/k8s-debs"

# 判断deb目录是否存在
if [ ! -d "${local_deb_dir}" ];then
    echo "ERROR: deb包目录不存在:${local_deb_dir}"
    exit 1
fi

echo "====================================="
echo "离线安装目录:${local_deb_dir}"
echo "====================================="

cd "${local_deb_dir}"

# 升级 containerd:先停止服务,防止进程占用二进制
echo -e "\n===== 停止 containerd.service ====="
systemctl stop containerd || true

# 【可选操作,正常升级不需要开启】
# 如需彻底卸载旧版本(出现冲突时手动启用)
# apt remove -y containerd.io
# apt purge -y containerd.io

echo -e "\n===== 安装/升级 containerd.io ====="
dpkg -i ./containerd.io_*.deb

echo -e "\n===== 安装 cri-tools ====="
dpkg -i ./cri-tools_*.deb

echo -e "\n===== 安装 kubeadm kubelet kubectl kubernetes-cni ====="
dpkg -i ./kube*.deb ./kubernetes-cni*.deb

# 离线修复依赖
echo -e "\n===== 修复依赖 --no-download ====="
apt-get install -y -f --no-download

# 启动组件
echo -e "\n===== 启用并启动 kubelet ====="
systemctl enable --now kubelet

echo -e "\n===== 启动 containerd ====="
systemctl enable --now containerd

echo -e "\n===== 离线安装/升级完成 ====="
containerd --version
kubeadm version
kubectl version --client
)

 

配置 containerd(根据 pause版本修改)

#!/bin/bash
# 根据K8s的pause镜像的版本修改
PAUSE_VERSION="3.10"

#生成默认配置
containerd config default | tee /etc/containerd/config.toml

# 修改cgroup驱动为systemd
sed -i 's/SystemdCgroup \= false/SystemdCgroup \= true/g' /etc/containerd/config.toml

# 正则替换pause版本,直接内嵌变量
sed -i "s#sandbox_image = \".*pause:[0-9.]*\"#sandbox_image = \"registry.k8s.io/pause:${PAUSE_VERSION}\"#g" /etc/containerd/config.toml

# 重启containerd
systemctl daemon-reload
systemctl restart containerd
systemctl enable --now containerd
# systemctl status containerd
# 校验连接文件
ls -l /run/containerd/containerd.sock

 

五,获取kubeadm需要的镜像

1. 下载kubeadm二进制,用于获取依赖的镜像

下载规则:

# 国内下载地址
https://mirrors.aliyun.com/kubernetes-release/release/${tag}/bin/linux/${arch}/kubeadm # 官方下载地址 https://dl.k8s.io/release/${tag}/bin/linux/${arch}/kubeadm

tag = v1.32.13(必须带 v)

arch = amd64 / arm64

下载kubeadm二进制包

#!/bin/bash
(
conf_file="./k8s-offline.conf"

if [ ! -f "${conf_file}" ];then
    echo "ERROR: 配置文件不存在 -> ${conf_file}"
    exit 1
fi
source "${conf_file}"

check_var() {
    local name="$1"
    if [[ -z "${!name}" ]]; then
        echo "ERROR: 配置变量【$name】不能为空,请检查配置文件"
        exit 1
    fi
}
check_var base_dir
check_var k8s_pkg_ver

# =========本地副本变量=========
local_base_dir="${base_dir}"
local_k8s_pkg_ver="${k8s_pkg_ver}"
local_arch=$(dpkg --print-architecture)

# 从 k8s_pkg_ver="1.32.13-1~xxx" 截取 1.32.13
local_k8s_short_ver=$(echo "${local_k8s_pkg_ver}" | cut -d'-' -f1)
local_k8s_tag="v${local_k8s_short_ver}"

# 存放目录
local_kubeadm_bin_dir="${local_base_dir}/kubeadm-bin"
mkdir -p "${local_kubeadm_bin_dir}"
local_output_file="${local_kubeadm_bin_dir}/kubeadm-${local_k8s_tag}"

echo "开始下载 kubeadm ${local_k8s_tag}"
# curl下载
curl -L -fsSL "https://mirrors.aliyun.com/kubernetes-release/release/${local_k8s_tag}/bin/linux/${local_arch}/kubeadm" -o "${local_output_file}"

# 添加执行权限
chmod +x "${local_output_file}"

echo "下载完成:${local_output_file}"
ls -lh "${local_kubeadm_bin_dir}"
)

 

已下载的kubeadm二进制文件(加版本区分)

-rwxr-xr-x 1 root root 68M Aug 17 15:56 kubeadm-v1.32.13
-rw-r--r-- 1 root root 72M Aug 16 17:28 kubeadm-v1.33.9
-rw-r--r-- 1 root root 71M Aug 16 17:28 kubeadm-v1.34.10
-rw-r--r-- 1 root root 70M Aug 16 17:29 kubeadm-v1.35.5
-rw-r--r-- 1 root root 70M Aug 16 17:29 kubeadm-v1.36.3

 

2. 从二进制kubeadm包获取镜像并下载

#!/bin/bash
(
conf_file="./k8s-offline.conf"

if [ ! -f "${conf_file}" ];then
    echo "ERROR: 配置文件不存在 -> ${conf_file}"
    exit 1
fi
source "${conf_file}"

check_var() {
    local name="$1"
    if [[ -z "${!name}" ]]; then
        echo "ERROR: 配置变量【$name】不能为空,请检查配置文件"
        exit 1
    fi
}
check_var base_dir
check_var k8s_ver

# =========本地副本变量=========
local_base_dir="${base_dir}"
local_k8s_ver="${k8s_ver}"

# kubeadm二进制路径
local_kubeadm_bin="${local_base_dir}/kubeadm-bin/kubeadm-${local_k8s_ver}"

# 目录与文件定义
local_work_dir="${local_base_dir}/k8s-${local_k8s_ver}"
local_img_list_file="${local_work_dir}/k8s-images-${local_k8s_ver}.list"
local_all_in_one_tar="${local_work_dir}/k8s-images-${local_k8s_ver}.tar.gz"

mkdir -p "${local_work_dir}"

# 校验kubeadm二进制文件
if [ ! -f "${local_kubeadm_bin}" ];then
    echo "ERROR: kubeadm二进制不存在:${local_kubeadm_bin}"
    exit 1
fi

# ============镜像源【手动注释切换】============
# DaoCloud
local_registry_prefix="m.daocloud.io"
# 华为渡渡鸟DDN-K8s
# local_registry_prefix="swr.cn-north-4.myhuaweicloud.com/ddn-k8s"
# ==============================================

echo "====================================="
echo "K8s版本:           ${local_k8s_ver}"
echo "命名空间:          k8s.io (固定)"
echo "镜像加速源前缀:    ${local_registry_prefix}"
echo "工作目录:          ${local_work_dir}"
echo "镜像清单文件:      ${local_img_list_file}"
echo "统一镜像包:        ${local_all_in_one_tar}"
echo "====================================="

# 旧包存在直接删除,强制覆盖
if [ -f "${local_all_in_one_tar}" ]; then
    echo "INFO: 删除旧镜像包:${local_all_in_one_tar}"
    rm -f "${local_all_in_one_tar}"
fi

# 生成原始镜像清单
echo "生成镜像清单..."
${local_kubeadm_bin} config images list --kubernetes-version=${local_k8s_ver} > "${local_img_list_file}"
if [ ! -s "${local_img_list_file}" ];then
    echo "ERROR: 获取镜像列表为空!"
    exit 1
fi
echo "镜像清单已保存:${local_img_list_file}"

origin_img_array=()
accel_img_array=()

# 拉取镜像、打原生标签
while read -r origin_img; do
    [ -z "${origin_img}" ] && continue

    accel_img="${local_registry_prefix}/${origin_img}"
    accel_img_array+=("${accel_img}")
    origin_img_array+=("${origin_img}")

    echo -e "\n===== 拉取镜像:${accel_img} ====="
    nerdctl -n k8s.io pull "${accel_img}"
    if [ $? -ne 0 ];then
        echo "ERROR: ${accel_img} 拉取失败"
        exit 1
    fi

    echo "打原生标签:${origin_img}"
    nerdctl -n k8s.io tag "${accel_img}" "${origin_img}"

done < "${local_img_list_file}"

# 使用 nerdctl save 一次性打包全部镜像
echo -e "\n===== 开始统一导出全部镜像 ====="
nerdctl -n k8s.io save -o "${local_all_in_one_tar}" "${origin_img_array[@]}"
if [ $? -ne 0 ];then
    echo "ERROR: 镜像统一导出失败!"
    exit 1
fi
echo "镜像大包导出成功:${local_all_in_one_tar}"

# 清理加速标签镜像
echo -e "\n===== 清理所有加速源镜像标签 ====="
for img in "${accel_img_array[@]}"; do
    nerdctl -n k8s.io rmi "${img}" >/dev/null 2>&1
done

echo -e "\n===== 全部镜像处理完成 ====="
ls -lh "${local_work_dir}"
)

输出:

drwxr-xr-x 2 root root      4096 Aug 17 15:16 k8s-debs
-rw-r--r-- 1 root root       262 Aug 17 16:33 k8s-images-v1.32.13.list
-rw-r--r-- 1 root root 147200000 Aug 17 16:33 k8s-images-v1.32.13.tar.gz

 

 

六,下载calico / ingress部署文件及镜像

根据k8s版本下载对应的yaml版本

1,下载yaml文件

1)  k8s-v1.32、k8s-v1.33下载两个文件

calico-v3.31.6:https://raw.githubusercontent.com/projectcalico/calico/v3.31.6/manifests/calico.yaml

ingress-nginx-controler-v1.14.5:https://raw.githubusercontent.com/kubernetes/ingress-nginx/controller-v1.14.5/deploy/static/provider/cloud/deploy.yaml

2) k8s-v1.34、k8s-v1.35下载这两个文件

calico-v3.32.1:https://raw.githubusercontent.com/projectcalico/calico/v3.32.1/manifests/calico.yaml

ingress-nginx-controler-v1.15.1:https://raw.githubusercontent.com/kubernetes/ingress-nginx/controller-v1.15.1/deploy/static/provider/cloud/deploy.yaml

下载calico与ingress-nginx的部署文件

#!/bin/bash
set -euo pipefail
(
conf_file="./k8s-offline.conf"

if [ ! -f "${conf_file}" ];then
    echo "ERROR: 当前目录缺少配置文件 ${conf_file}"
    echo "当前工作目录:$(pwd)"
    echo "请进入对应k8s版本目录执行脚本!"
    exit 1
fi
source "${conf_file}"

check_var() {
    local name="$1"
    if [[ -z "${!name:-}" ]]; then
        echo "ERROR: 配置变量【${name}】不能为空,请检查 ${conf_file}"
        exit 1
    fi
}
check_var base_dir
check_var k8s_ver
check_var calico_ver
check_var ingress_ver

local_base_dir="${base_dir}"
local_k8s_ver="${k8s_ver}"
local_calico_ver="${calico_ver}"
local_ingress_ver="${ingress_ver}"

target_dir="${local_base_dir}/k8s-${local_k8s_ver}"
mkdir -p "${target_dir}"
cd "${target_dir}" || exit 1

calico_yaml="calico-${local_calico_ver}.yaml"
ingress_yaml="ingress-nginx-${local_ingress_ver}.yaml"

echo "===== 处理 ${calico_yaml} ====="
if [ -f "${calico_yaml}" ]; then
    echo "${calico_yaml} 已存在,跳过下载"
else
    echo "开始下载 ${calico_yaml}"
    curl -fSL -o "${calico_yaml}" \
https://mirror.ghproxy.com/https://raw.githubusercontent.com/projectcalico/calico/${local_calico_ver}/manifests/calico.yaml || {
        echo "⚠️ Calico yaml 下载失败"
    }
fi

echo -e "\n===== 处理 ${ingress_yaml} ====="
if [ -f "${ingress_yaml}" ]; then
    echo "${ingress_yaml} 已存在,跳过下载"
else
    echo "开始下载 ${ingress_yaml}"
    curl -fSL -o "${ingress_yaml}" \
https://mirror.ghproxy.com/https://raw.githubusercontent.com/kubernetes/ingress-nginx/controller-${local_ingress_ver}/deploy/static/provider/cloud/deploy.yaml || {
        echo "⚠️ Ingress-Nginx yaml 下载失败"
    }
fi

echo -e "\n✅ yaml文件就绪,当前目录yaml列表:"
ls -lh *.yaml 2>/dev/null
)

 

2.根据yaml文件里的镜像版本下载calico与ingress-nginx镜像

#!/bin/bash
set -euo pipefail
(
conf_file="./k8s-offline.conf"

if [ ! -f "${conf_file}" ];then
    echo "ERROR: 当前目录缺少配置文件 ${conf_file}"
    echo "当前工作目录:$(pwd)"
    echo "请进入对应k8s版本目录执行脚本!"
    exit 1
fi
source "${conf_file}"

check_var() {
    local name="$1"
    if [[ -z "${!name:-}" ]]; then
        echo "ERROR: 配置变量【${name}】不能为空,请检查 ${conf_file}"
        exit 1
    fi
}
check_var base_dir
check_var k8s_ver
check_var calico_ver
check_var ingress_ver

local_base_dir="${base_dir}"
local_k8s_ver="${k8s_ver}"
local_calico_ver="${calico_ver}"
local_ingress_ver="${ingress_ver}"

# 渡渡鸟:备用源(仅定义保留,本次不启用拉取)
local_mirror_ddn="swr.cn-north-4.myhuaweicloud.com/ddn-k8s/"
# DaoCloud 统一主源
local_mirror_dao="m.daocloud.io/"

target_dir="${local_base_dir}/k8s-${local_k8s_ver}"
mkdir -p "${target_dir}"
cd "${target_dir}" || exit 1

calico_yaml="calico-${local_calico_ver}.yaml"
calico_list="calico-images-${local_calico_ver}.list"
calico_tar="calico-images-${local_calico_ver}.tar.gz"

ingress_yaml="ingress-nginx-${local_ingress_ver}.yaml"
ingress_list="ingress-nginx-images-${local_ingress_ver}.list"
ingress_tar="ingress-nginx-images-${local_ingress_ver}.tar.gz"

# 校验yaml必须存在
if [[ ! -f "${calico_yaml}" ]]; then
    echo "❌ 错误:找不到文件 ${target_dir}/${calico_yaml}"
    exit 1
fi
if [[ ! -f "${ingress_yaml}" ]]; then
    echo "❌ 错误:找不到文件 ${target_dir}/${ingress_yaml}"
    exit 1
fi

# --------------------------
# Calico镜像拉取打包(DaoCloud源)
# --------------------------
echo -e "\n===== 提取 Calico 镜像清单 ====="
awk '/image:/ {sub(/@.*/,"",$2);print $2}' "${calico_yaml}" | sort -u > "${calico_list}"
cat "${calico_list}"

echo -e "\n===== 拉取 Calico 镜像(DaoCloud源) ====="
while read -r img; do
  [[ -z "${img}" ]] && continue
  mirror_img="${local_mirror_dao}${img}"
  echo "pull ${mirror_img}"
  if ! nerdctl -n k8s.io pull "${mirror_img}"; then
      echo "⚠️ ${mirror_img} 拉取失败,跳过"
      continue
  fi
  echo "tag ${mirror_img} -> ${img}"
  nerdctl -n k8s.io tag "${mirror_img}" "${img}"
  echo "rm temp mirror image ${mirror_img}"
  nerdctl -n k8s.io rmi "${mirror_img}"
done < "${calico_list}"

echo -e "\n===== 打包 Calico 镜像 ${calico_tar} ====="
mapfile -t calico_images < "${calico_list}"
if [[ ${#calico_images[@]} -gt 0 ]]; then
    nerdctl -n k8s.io save -o "${calico_tar}" "${calico_images[@]}"
else
    echo "⚠️ Calico镜像清单为空,跳过打包"
fi

# --------------------------
# Ingress-Nginx镜像拉取打包(DaoCloud源)
# --------------------------
echo -e "\n===== 提取 Ingress-Nginx 镜像清单 ====="
awk '/image:/ {sub(/@.*/,"",$2);print $2}' "${ingress_yaml}" | sort -u > "${ingress_list}"
cat "${ingress_list}"

echo -e "\n===== 拉取 Ingress-Nginx 镜像(DaoCloud源) ====="
while read -r img; do
  [[ -z "${img}" ]] && continue

  mirror_img="${local_mirror_dao}${img}"
  echo "尝试拉取(DaoCloud): ${mirror_img}"
  if nerdctl -n k8s.io pull "${mirror_img}"; then
      echo "tag ${mirror_img} -> ${img}"
      nerdctl -n k8s.io tag "${mirror_img}" "${img}"
      nerdctl -n k8s.io rmi "${mirror_img}"
  else
      echo "❌ ${img} DaoCloud源拉取失败,跳过"
  fi
done < "${ingress_list}"

echo -e "\n===== 打包 Ingress-Nginx 镜像 ${ingress_tar} ====="
mapfile -t ingress_images < "${ingress_list}"
if [[ ${#ingress_images[@]} -gt 0 ]]; then
    nerdctl -n k8s.io save -o "${ingress_tar}" "${ingress_images[@]}"
else
    echo "⚠️ Ingress镜像清单为空,跳过打包"
fi

echo -e "\n✅ 镜像拉取打包完成!输出压缩包:"
ls -lh *.tar.gz *.list
)

 

七,生成的文件清单

ls -lh
total 548M
-rw-r--r-- 1 root root   95 Aug 17 18:18 calico-images-v3.31.6.list
-rw-r--r-- 1 root root 272M Aug 17 18:18 calico-images-v3.31.6.tar.gz
-rw-r--r-- 1 root root 324K Aug 17 18:00 calico-v3.31.6.yaml
-rw-r--r-- 1 root root  107 Aug 17 18:18 ingress-nginx-images-v1.14.5.list
-rw-r--r-- 1 root root 136M Aug 17 18:18 ingress-nginx-images-v1.14.5.tar.gz
-rw-r--r-- 1 root root  16K Aug 17 18:00 ingress-nginx-v1.14.5.yaml
drwxr-xr-x 2 root root 4.0K Aug 17 17:33 k8s-debs
-rw-r--r-- 1 root root  262 Aug 17 17:24 k8s-images-v1.32.13.list
-rw-r--r-- 1 root root 141M Aug 17 17:24 k8s-images-v1.32.13.tar.gz
-rw-r--r-- 1 root root  528 Aug 17 17:43 k8s-offline.conf
ls -lh ./k8s-debs/
total 111M
-rw-r--r-- 1 root root 22M Aug 13 20:51 containerd.io_2.3.3-1~ubuntu.26.04~resolute_amd64.deb
-rw-r--r-- 1 root root 16M Dec  9  2024 cri-tools_1.32.0-1.1_amd64.deb
-rw-r--r-- 1 root root 12M Feb 27 08:18 kubeadm_1.32.13-1.1_amd64.deb
-rw-r--r-- 1 root root 11M Feb 27 08:18 kubectl_1.32.13-1.1_amd64.deb
-rw-r--r-- 1 root root 15M Feb 27 08:18 kubelet_1.32.13-1.1_amd64.deb
-rw-r--r-- 1 root root 37M Dec 12  2024 kubernetes-cni_1.6.0-1.1_amd64.deb

 

八,部署

1. manifest.info 文件配置

vi /data/k8s/k8s-v1.32.13

K8S_BASE="/data/k8s/k8s-v1.32.13"
K8S_VERSION="v1.32.13"
CALICO_VERSION="v3.29.0"
INGRESS_NGINX_VERSION="v1.11.2"
PAUSE_VERSION="v3.10"

 

2. 部署脚本

# 切换版本只改这一行source路径
source /data/k8s/k8s-v1.32.13/manifest.info

# 安装deb
dpkg -i ${K8S_BASE}/k8s-debs/*.deb

# 导入k8s合并镜像包
ctr -n k8s.io images import ${K8S_BASE}/k8s-images-${K8S_VERSION}.tar.gz

# calico
ctr -n k8s.io images import ${K8S_BASE}/calico-images-${CALICO_VERSION}.tar.gz
kubectl apply -f ${K8S_BASE}/calico-${CALICO_VERSION}.yaml

# ingress‑nginx
ctr -n k8s.io images import ${K8S_BASE}/ingress-nginx-images-${INGRESS_NGINX_VERSION}.tar.gz
kubectl apply -f ${K8S_BASE}/ingress-nginx-${INGRESS_NGINX_VERSION}.yaml

 

posted @ 2026-08-16 18:01  民工黑猫  阅读(6)  评论(0)    收藏  举报