一、安装私有镜像仓库

参考: 私有镜像仓库

二、准备文件

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

    Choose Release Version

  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
    
    mkdir -p rancher-images-$(date +"%Y-%m-%d")
    
    for i in $(cat ${list});
    do
        if [[ ! -f rancher-images-$(date +"%Y-%m-%d")/$(echo $i | sed "s#/#-#g; s#:#-#g").tgz ]];then
    
            docker pull ${i}
    
            if [ $? -ne 0 ]; then
                logger "${i} pull failed."
            else
                logger "${i} pull successfully."
            fi
    
            docker save ${i} | gzip > rancher-images-$(date +"%Y-%m-%d")/$(echo $i | sed "s#/#-#g; s#:#-#g").tgz
    
            if [ $? -ne 0 ]; then
                logger "${i} save failed."
            else
                logger "${i} save successfully."
            fi
    
        else
            logger "${i} Images downloaded."
        fi
    done
  6. 复制以下脚本保存为rancher-load-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}
    }
    
    POSITIONAL=()
    while [[ $# -gt 0 ]]; do
        key="$1"
        case $key in
            -i|--images-path)
            images_path="$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
    
    # 镜像压缩文件列表
    images=$(ls $images_path | grep ".tgz")
    
    # 导入镜像
    docker_load ()
    {
        for imgs in $(echo ${images});
        do
            gunzip -c $images_path/${imgs} | docker load
    
            if [ $? -ne 0 ]; then
                logger "${imgs} load failed."
            else
                logger "${imgs} load successfully."
            fi
        done
    }
    
    docker_load
  7. 复制以下脚本保存为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=   # 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=library
                    #重命名镜像
                    docker tag ${imgs} ${registry}/${namespace}/${img_tag}
                    #删除原始镜像
                    #docker rmi ${imgs}
                    #上传镜像
                    docker push ${registry}/${namespace}/${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-$(date +"%Y-%m-%d")生成所有镜像的压缩文件

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

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

    chmod +x ./rancher-load-images.sh && ./rancher-load-images.sh --images-path ./rancher-images-$(date +"%Y-%m-%d")
  3. 使用rancher-push-images.sh把导入的docker镜像自动tag重命名,然后上传到私有镜像仓库

    注意 镜像默认全部上传到镜像仓库的rancher项目下,如果镜像仓库不支持自动创建项目名(比如Harbor),需要提前手动去镜像仓库创建好项目。

    chmod +x ./rancher-push-images.sh && ./rancher-push-images.sh

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