Fork me on GitHub

前置操作汇总

docker 配置代理拉取镜像
下载kubespray源代码
需要进入到kubespray源代码目录中

$ cd contrib/offline
$ bash generate_list.sh
$ tree temp/
temp/
├── files.list
├── files.list.template
├── images.list
└── images.list.template
  • flies.list 是依赖文件的列表。
  • images.list 是依赖镜像的列表。

下载二进制文件

执行以下命令将依赖的静态文件全部下载到 temp/files 目录下:

wget -t 5 -T 30-x -P temp/files -i temp/files.list
  • -i 批量下载列表文件
  • -p 指定保存目录
  • -x 强制创建目录结构
  • -t 5 重试5次
  • -T 30 超时30秒

将静态文件通过静态服务器暴露出来,比如使用 nginx,根据情况修改 nginx 配置

user root;
server {
        listen 80 default_server;
        listen [::]:80 default_server;
        location /k8s/ {
                alias /root/kubespray/contrib/offline/temp/files/;
        }
}

下载镜像文件

push.sh 脚本包含下载镜像,创建项目,无项目默认将镜像放置在library项目中,推送镜像,删除本地镜像缓存功能
此脚本需要提前完成docker的前置操作

#!/bin/bash
# Harbor仓库配置
REGISTRY="192.168.255.61"
USERNAME="admin"
PASSWORD="Harbor12345"
PROJECT_CACHE=".harbor_projects.cache"  # 项目缓存文件

# 登录Docker仓库
echo "登录Harbor仓库..."
echo "$PASSWORD" | docker login --username "$USERNAME" --password-stdin "$REGISTRY" || {
    echo "❌ Harbor登录失败!请检查凭证和网络连接"
    exit 1
}

# 创建Harbor项目函数
create_harbor_project() {
    local project_name="$1"
    
    # 项目名规范化(小写+替换非法字符)
    normalized_name=$(echo "$project_name" | tr '[:upper:]' '[:lower:]' | sed 's/[^a-z0-9-]/-/g')
    
    # 检查项目是否已存在(本地缓存)
    if grep -q "^${normalized_name}$" "$PROJECT_CACHE"; then
        echo "ℹ️  项目 ${normalized_name} 已存在(缓存记录)"
        return 0
    fi

    # 调用Harbor API创建项目
    echo "创建项目: ${normalized_name}"
    echo curl -s -k -w "%{http_code}" -u "${USERNAME}:${PASSWORD}" -X POST 
    echo    -H "Content-Type: application/json" 
    echo    "${REGISTRY}/api/v2.0/projects" 
    echo    -d '{"project_name": "'"${normalized_name}"'", "public": true}'
    
    response=$(curl -s -k -w "%{http_code}" -u "${USERNAME}:${PASSWORD}" -X POST \
        -H "Content-Type: application/json" \
        "${REGISTRY}/api/v2.0/projects" \
        -d '{"project_name": "'"${normalized_name}"'", "public": true}')
    

    http_code=${response: -3}
    case $http_code in
        201) 
            echo "✅ 项目 ${normalized_name} 创建成功"
            echo "$normalized_name" >> "$PROJECT_CACHE"
            ;;
        409)
            echo "ℹ️  项目 ${normalized_name} 已存在(Harbor返回)"
            echo "$normalized_name" >> "$PROJECT_CACHE"
            ;;
        401)
            echo "❌ 认证失败!请检查管理员凭证[1,6](@ref)"
            exit 1
            ;;
        *)
            echo "❌ 创建项目失败 (HTTP $http_code):${response%???}"
            ;;
    esac
}

# 主镜像处理流程
echo "开始处理镜像..."
declare -A created_projects  # 项目去重缓存
touch "$PROJECT_CACHE"        # 确保缓存文件存在

while IFS= read -r image; do
    # 跳过空行和注释
    [[ -z "$image" || "$image" == \#* ]] && continue
    
    echo "--------------------------------------------------"
    echo "处理镜像: $image"
    
    # 提取镜像路径并确定项目名
    image_path="${image#*/}"
    if [[ "$image_path" == */* ]]; then
        project_name="${image_path%%/*}"   # 提取第一个路径段
        new_image="${REGISTRY}/${image_path}"
    else
        project_name="library"             # 默认项目
        new_image="${REGISTRY}/library/${image_path}"
    fi

    # 创建Harbor项目(自动去重)
    if [[ -z "${created_projects[$project_name]}" ]]; then
        create_harbor_project "$project_name"
        created_projects["$project_name"]=1
    fi

    # 拉取原始镜像
    echo "拉取镜像: $image"
    docker pull "$image" || {
        echo "⚠️  拉取失败 - $image,跳过后续操作"
        continue
    }
    
    # 重命名镜像
    echo "重命名: $image => $new_image"
    docker tag "$image" "$new_image"
    
    # 推送镜像
    echo "推送镜像: $new_image"
    for attempt in {1..3}; do  # 失败重试机制
        docker push "$new_image" && break
        echo "⚠️  推送失败($attempt/3),10秒后重试..."
        sleep 10
    done || {
        echo "❌ 推送失败 - $new_image"
        continue
    }
    
    # 清理镜像
    docker rmi "$image" "$new_image" 2>/dev/null
    echo "清理完成: $image"
    
done < images.list  # 镜像列表文件

echo "=================================================="
echo "✅ 全部镜像推送完成!"

修改 offline.yml

搬运好了文件和镜像,我们来修改下 kubespray 的地址,让依赖的文件和镜像下载地址使用我们自己的地址
修改 /root/kubespray-2.22.0/inventory/mycluster/group_vars/all/offline.yml
此offline.yml文件在 download/tasks/download_container.yml会使用下载容器
默认使用download/defaults/main.yml中的变量,offline.yml变量的优先级高于defaults,所以要修改offline.yml,使用指定的镜像版本

registry_host: "192.168.255.61:80"
kube_image_repo: "{{ registry_host }}/library"
gcr_image_repo: "{{ registry_host }}"
github_image_repo: "{{ registry_host }}"
docker_image_repo: "{{ registry_host }}"
quay_image_repo: "{{ registry_host }}"
pod_infra_image_repo: "{{ kube_image_repo }}/pause"
coredns_image_repo: "{{ registry_host }}/coredns/coredns"
nodelocaldns_image_repo: "{{ registry_host }}/dns/k8s-dns-node-cache"
dnsautoscaler_image_repo: "{{ registry_host }}/cpa/cluster-proportional-autoscaler"
metrics_server_image_repo: "{{ registry_host }}/metrics-server/metrics-server"
local_volume_provisioner_image_repo: "{{ registry_host }}/sig-storage/local-volume-provisioner"
ingress_nginx_controller_image_repo: "{{ registry_host }}/ingress-nginx/controller"
ingress_nginx_kube_webhook_certgen_image_repo: "{{ registry_host }}/ingress-nginx/kube-webhook-certgen"
csi_attacher_image_repo: "{{ registry_host }}/sig-storage/csi-attacher"
csi_provisioner_image_repo: "{{ registry_host }}/sig-storage/csi-provisioner"
csi_snapshotter_image_repo: "{{ registry_host }}/sig-storage/csi-snapshotter"
csi_resizer_image_repo: "{{ registry_host }}/sig-storage/csi-resizer"
csi_node_driver_registrar_image_repo: "{{ registry_host }}/sig-storage/csi-node-driver-registrar"
csi_livenessprobe_image_repo: "{{ registry_host }}/sig-storage/livenessprobe"
snapshot_controller_image_repo: "{{ registry_host }}/sig-storage/snapshot-controller"
gcp_pd_csi_plugin_image_repo: "{{ registry_host }}/cloud-provider-gcp/gcp-compute-persistent-disk-csi-driver"
files_repo: "http://192.168.255.60/k8s-binary"
kubeadm_download_url: "{{ files_repo }}/dl.k8s.io/release/{{ kube_version }}/bin/linux/{{ image_arch }}/kubeadm"
kubectl_download_url: "{{ files_repo }}/dl.k8s.io/release/{{ kube_version }}/bin/linux/{{ image_arch }}/kubectl"
kubelet_download_url: "{{ files_repo }}/dl.k8s.io/release/{{ kube_version }}/bin/linux/{{ image_arch }}/kubelet"
cni_download_url: "{{ files_repo }}/github.com/containernetworking/plugins/releases/download/{{ cni_version }}/cni-plugins-linux-{{ image_arch }}-{{ cni_version }}.tgz"
crictl_download_url: "{{ files_repo }}/github.com/kubernetes-sigs/cri-tools/releases/download/{{ crictl_version }}/crictl-{{ crictl_version }}-{{ ansible_system | lower }}-{{ image_arch }}.tar.gz"
etcd_download_url: "{{ files_repo }}/github.com/etcd-io/etcd/releases/download/{{ etcd_version }}/etcd-{{ etcd_version }}-linux-{{ image_arch }}.tar.gz"
calicoctl_download_url: "{{ files_repo }}/github.com/projectcalico/calico/releases/download/{{ calico_ctl_version }}/calicoctl-linux-{{ image_arch }}"
calico_crds_download_url: "{{ files_repo }}/github.com/projectcalico/calico/archive/{{ calico_version }}.tar.gz"
flannel_cni_download_url: "{{ files_repo }}/github.com/flannel-io/cni-plugin/releases/download/{{ flannel_cni_version }}/flannel-{{ image_arch }}"
helm_download_url: "{{ files_repo }}/get.helm.sh/helm-{{ helm_version }}-linux-{{ image_arch }}.tar.gz"
crun_download_url: "{{ files_repo }}/github.com/containers/crun/releases/download/{{ crun_version }}/crun-{{ crun_version }}-linux-{{ image_arch }}"
kata_containers_download_url: "{{ files_repo }}/github.com/kata-containers/kata-containers/releases/download/{{ kata_containers_version }}/kata-static-{{ kata_containers_version }}-{{ ansible_architecture }}.tar.xz"
runc_download_url: "{{ files_repo }}/github.com/opencontainers/runc/releases/download/{{ runc_version }}/runc.{{ image_arch }}"
containerd_download_url: "{{ files_repo }}/github.com/containerd/containerd/releases/download/v{{ containerd_version }}/containerd-{{ containerd_version }}-linux-{{ image_arch }}.tar.gz"
nerdctl_download_url: "{{ files_repo }}/github.com/containerd/nerdctl/releases/download/v{{ nerdctl_version }}/nerdctl-{{ nerdctl_version }}-{{ ansible_system | lower }}-{{ image_arch }}.tar.gz"
krew_download_url: "{{ files_repo }}/github.com/kubernetes-sigs/krew/releases/download/{{ krew_version }}/krew-{{ host_os }}_{{ image_arch }}.tar.gz"
cri_dockerd_download_url: "{{ files_repo }}/github.com/Mirantis/cri-dockerd/releases/download/{{ cri_dockerd_version }}/cri-dockerd-{{ cri_dockerd_version }}-linux-{{ image_arch }}.tar.gz"
gvisor_runsc_download_url: "{{ files_repo }}/storage.googleapis.com/gvisor/releases/release/{{ gvisor_version }}/{{ ansible_architecture }}/runsc"
gvisor_containerd_shim_runsc_download_url: "{{ files_repo }}/storage.googleapis.com/gvisor/releases/release/{{ gvisor_version }}/{{ ansible_architecture }}/containerd-shim-runsc-v1"
youki_download_url: "{{ files_repo }}/github.com/containers/youki/releases/download/v{{ youki_version }}/youki_v{{ youki_version | regex_replace('\\.', '_') }}_linux.tar.gz"
posted on 2025-07-25 15:56  anyux  阅读(30)  评论(0)    收藏  举报