本文永久链接: https://www.xtplayer.cn/rancher/install/rancher-install-offline-images/

准备文件

  1. 使用可以访问 Internet 的主机,访问我们的版本 发布页面,找到需要安装的 Rancher 2.x.x 版本。不要下载 rc 或者 Pre-release 版本,因为它们不适用于稳定的生产环境。

  2. 从发行版本的 Assets 部分,下载 rancher-images.txt,此文件包含安装 Rancher 所需的所有镜像的列表。

  3. 通过 RKE 生成镜像清单

    rke config --system-images -all >> ./rancher-images.txt
  4. 对镜像列表进行排序和去重,以去除重复的镜像。

    sort -u rancher-images.txt -o rancher-images.txt
  5. 复制以下脚本保存为 rancher-save-images.sh,与 rancher-images.txt 放在同一目录层级;

    #!/bin/bash
    # 定义日志
    workdir=`pwd`
    log_file=${workdir}/sync_images_$(date +"%Y-%m-%d").log

    logger()
    {
    log=$1
    cur_time='['$(date +"%Y-%m-%d %H:%M:%S")']'
    echo ${cur_time} ${log} | tee -a ${log_file}
    }

    list="rancher-images.txt"
    #images="rancher-images.tar.gz"

    POSITIONAL=()
    while [[ $# -gt 0 ]];
    do
    key="$1"
    case $key in
    -i|--images)
    images="$2"
    shift # past argument
    shift # past value
    ;;
    -l|--image-list)
    list="$2"
    shift # past argument
    shift # past value
    ;;
    -h|--help)
    help="true"
    shift
    ;;
    esac
    done

    usage () {
    echo "USAGE: $0 [--image-list rancher-images.txt] [--images rancher-images.tar.gz]"
    echo " [-l|--images-list path] text file with list of images. 1 per line."
    echo " [-l|--images path] tar.gz generated by docker save."
    echo " [-h|--help] Usage message"
    }

    if [[ $help ]]; then
    usage
    exit 0
    fi

    for i in $(cat ${list});
    do
    docker pull ${i} >> /dev/null 2>&1

    if [ $? -ne 0 ]; then
    logger "image ${i} download failed."
    else
    logger "image ${i} download complete."
    fi
    done

    logger "save all images to rancher-images.tgz."
    docker save $(cat ${list}) | gzip > rancher-images.tgz
  6. 复制以下脚本保存为 rancher-push-images.sh,与 rancher-images.txt 放在同一目录层级;

    #!/bin/bash

    ## 镜像上传说明
    # 需要先在镜像仓库中创建 rancher 项目
    # 根据实际情况更改以下私有仓库地址

    # 定义日志
    workdir=`pwd`
    log_file=${workdir}/sync_images_$(date +"%Y-%m-%d").log

    logger()
    {
    log=$1
    cur_time='['$(date +"%Y-%m-%d %H:%M:%S")']'
    echo ${cur_time} ${log} | tee -a ${log_file}
    }

    images_hub() {

    while true;
    do
    read -p "输入镜像仓库地址(不加 http/https): " registry
    read -p "输入镜像仓库用户名: " registry_user
    read -p "输入镜像仓库用户密码: " registry_password
    echo "您设置的仓库地址为: ${registry},用户名: ${registry_user},密码: xxx"
    read -p "是否确认(Y/N): " confirm

    if [ $confirm != Y ] && [ $confirm != y ] && [ $confirm == '' ]; then
    echo "输入不能为空,重新输入"
    else
    break
    fi
    done
    }

    images_hub

    echo "镜像仓库 $(docker login -u ${registry_user} -p ${registry_password} ${registry})"

    #images=$(docker images -a | grep -v TAG | awk '{print $1 ":" $2}')

    images=$( cat rancher-images.txt )

    # 定义全局项目,如果想把镜像全部同步到一个仓库,则指定一个全局项目名称;
    global_namespace=$1 # rancher

    docker_push() {
    for imgs in $( echo "${images}" );
    do
    if [[ -n "$global_namespace" ]]; then

    n=$(echo ${imgs} | awk -F"/" '{print NF-1}')
    # 如果镜像名中没有/,那么此镜像一定是 library 仓库的镜像;
    if [ ${n} -eq 0 ]; then
    img_tag=${imgs}

    #重命名镜像
    docker tag ${imgs} ${registry}/${global_namespace}/${img_tag}
    #删除原始镜像
    #docker rmi ${imgs}
    #上传镜像
    docker push ${registry}/${global_namespace}/${img_tag}

    # 如果镜像名中有一个/,那么/左侧为项目名,右侧为镜像名和 tag
    elif [ ${n} -eq 1 ]; then
    img_tag=$(echo ${imgs} | awk -F"/" '{print $2}')

    #重命名镜像
    docker tag ${imgs} ${registry}/${global_namespace}/${img_tag}
    #删除旧镜像
    #docker rmi ${imgs}
    #上传镜像
    docker push ${registry}/${global_namespace}/${img_tag}

    # 如果镜像名中有两个/,
    elif [ ${n} -eq 2 ]; then
    img_tag=$(echo ${imgs} | awk -F"/" '{print $3}')

    #重命名镜像
    docker tag ${imgs} ${registry}/${global_namespace}/${img_tag}
    #删除旧镜像
    #docker rmi ${imgs}
    #上传镜像
    docker push ${registry}/${global_namespace}/${img_tag}
    else
    #标准镜像为四层结构,即:仓库地址/项目名/镜像名:tag,如不符合此标准,即为非有效镜像。
    echo "No available images"
    fi
    else
    n=$(echo ${imgs} | awk -F"/" '{print NF-1}')
    # 如果镜像名中没有/,那么此镜像一定是 library 仓库的镜像;
    if [ ${n} -eq 0 ]; then
    img_tag=${imgs}
    namespace_1=library
    namespace_2=rancher

    #重命名镜像
    docker tag ${imgs} ${registry}/${namespace_1}/${img_tag}
    docker tag ${imgs} ${registry}/${namespace_2}/${img_tag}
    #删除原始镜像
    #docker rmi ${imgs}
    #上传镜像
    docker push ${registry}/${namespace_1}/${img_tag}
    docker push ${registry}/${namespace_2}/${img_tag}

    # 如果镜像名中有一个/,那么/左侧为项目名,右侧为镜像名和 tag
    elif [ ${n} -eq 1 ]; then
    img_tag=$(echo ${imgs} | awk -F"/" '{print $2}')
    namespace=$(echo ${imgs} | awk -F"/" '{print $1}')

    #重命名镜像
    docker tag ${imgs} ${registry}/${namespace}/${img_tag}
    #删除旧镜像
    #docker rmi ${imgs}
    #上传镜像
    docker push ${registry}/${namespace}/${img_tag}

    # 如果镜像名中有两个/,
    elif [ ${n} -eq 2 ]; then
    img_tag=$(echo ${imgs} | awk -F"/" '{print $3}')
    namespace=$(echo ${imgs} | awk -F"/" '{print $2}')

    #重命名镜像
    docker tag ${imgs} ${registry}/${namespace}/${img_tag}
    #删除旧镜像
    #docker rmi ${imgs}
    #上传镜像
    docker push ${registry}/${namespace}/${img_tag}
    else
    #标准镜像为四层结构,即:仓库地址/项目名/镜像名:tag,如不符合此标准,即为非有效镜像。
    echo "No available images"
    fi
    fi
    done
    }

    docker_push

同步镜像

  1. 在可用访问 Internet 的主机中,使用 rancher-save-images.shrancher-images.txt 创建所有所需镜像的压缩包。

    注意: 镜像同步需要接近 20GB 的空磁盘空间。

    chmod +x ./rancher-save-images.sh && \
    ./rancher-save-images.sh --image-list ./rancher-images.txt

    结果: 在当前目录生成所有镜像的压缩文件 rancher-images.tgz

  2. 拷贝所有文件到内网环境中的 Linux 主机上,然后执行以下命令去加载压缩包

    注意 如果上一步下载镜像的主机可以连接内网的镜像仓库,那么此步骤可以跳过,直接在 上一步 的主机上执行下一个步骤。

    gunzip -c rancher-images.tgz | docker load
  3. 使用 rancher-push-images.sh 把导入的 docker 镜像自动 tag 重命名,然后上传到私有镜像仓库

    注意 镜像列表中存在多个 repo 的镜像,rancher-push-images.sh 脚本默认把镜像推送到与原镜像相同的 repo 中。有的镜像仓库服务不支持自动创建 repo(比如 Harbor),需要提前去镜像仓库服务手动创建好对应的 repo,然后再执行推送。如果想把镜像列表中的所有镜像推送到某个指定的 repo(比如:统一推送到 rancher 下),可以传递参数给 rancher-push-images.sh 脚本。

    chmod +x ./rancher-push-images.sh && \
    ./rancher-push-images.sh
    # 如果要把镜像统一推送到指定的 repo,比如:rancher
    chmod +x ./rancher-push-images.sh && \
    ./rancher-push-images.sh rancher

    执行脚本后会要求输入镜像仓库地址用户名、用户密码