Shell脚本如何配置容器迁移方案

wen 实用脚本 2

本文目录导读:

Shell脚本如何配置容器迁移方案

  1. 核心迁移思路
  2. 基础迁移脚本模板
  3. 高级配置与优化
  4. 故障恢复脚本
  5. 使用注意事项
  6. 安全性建议

这是一个关于Shell脚本配置容器迁移方案的详细指南,我将分步骤介绍如何编写脚本来实现容器(以Docker为例)的迁移,包括导出、传输、导入和启动流程。

核心迁移思路

容器迁移主要分为三个阶段:

  1. 源端: 停止容器 → 提交为镜像 → 导出为tar文件
  2. 传输: 将tar文件传输到目标服务器
  3. 目标端: 导入镜像 → 启动新容器

基础迁移脚本模板

单容器迁移脚本

#!/bin/bash
# 容器迁移脚本 - migrate_container.sh
# 配置变量
CONTAINER_NAME="myapp"
IMAGE_NAME="myapp-image"
IMAGE_TAG="migrated-$(date +%Y%m%d%H%M%S)"
TAR_FILE="${IMAGE_NAME}_${IMAGE_TAG}.tar"
TARGET_USER="root"
TARGET_HOST="192.168.1.100"
TARGET_PATH="/tmp/"
TARGET_DIR="/opt/containers"
# 错误处理函数
handle_error() {
    echo "错误: $1"
    exit 1
}
# 步骤1:验证源容器是否存在
echo "===== 步骤1: 验证源容器 ====="
if ! docker inspect "$CONTAINER_NAME" >/dev/null 2>&1; then
    handle_error "容器 $CONTAINER_NAME 不存在"
fi
# 步骤2:停止容器
echo "===== 步骤2: 停止容器 ====="
docker stop "$CONTAINER_NAME" || echo "容器已经在停止状态"
# 步骤3:提交容器为镜像
echo "===== 步骤3: 提交镜像 ====="
docker commit "$CONTAINER_NAME" "${IMAGE_NAME}:${IMAGE_TAG}" || \
    handle_error "镜像提交失败"
# 步骤4:导出镜像为文件
echo "===== 步骤4: 导出镜像 ====="
docker save -o "$TAR_FILE" "${IMAGE_NAME}:${IMAGE_TAG}" || \
    handle_error "镜像导出失败"
# 步骤5:传输到目标服务器
echo "===== 步骤5: 传输镜像 ====="
scp "$TAR_FILE" "${TARGET_USER}@${TARGET_HOST}:${TARGET_PATH}" || \
    handle_error "镜像传输失败"
# 步骤6:在目标服务器上执行导入和启动
echo "===== 步骤6: 远程执行导入 ====="
ssh "${TARGET_USER}@${TARGET_HOST}" "
    # 创建目标目录
    mkdir -p $TARGET_DIR
    # 导入镜像
    docker load -i ${TARGET_PATH}${TAR_FILE} || exit 1
    # 重新创建容器(根据原始容器配置调整)
    docker run -d \\
        --name ${CONTAINER_NAME} \\
        --restart unless-stopped \\
        -p 8080:80 \\  # 修改为实际端口映射
        ${IMAGE_NAME}:${IMAGE_TAG}
    # 清理tar文件
    rm -f ${TARGET_PATH}${TAR_FILE}
" || handle_error "远程导入失败"
# 步骤7:清理本地临时文件
echo "===== 步骤7: 清理临时文件 ====="
rm -f "$TAR_FILE"
docker rmi "${IMAGE_NAME}:${IMAGE_TAG}"
echo "===== 迁移完成 ====="
echo "容器 $CONTAINER_NAME 已成功迁移到 $TARGET_HOST"

增强版迁移脚本(支持多容器和配置持久化)

#!/bin/bash
# 增强版容器迁移脚本 - advanced_migrate.sh
# 配置区 - 可修改为配置文件读取
CONFIG_FILE="migration.conf"
# 默认配置
declare -A CONTAINERS=(
    ["nginx-web"]="nginx:latest:80:80"
    ["mysql-db"]="mysql:8.0:3306:3306"
    ["redis-cache"]="redis:alpine:6379:6379"
)
TARGET_HOST="192.168.1.200"
TARGET_USER="root"
BACKUP_DIR="/tmp/container_backup_$(date +%Y%m%d_%H%M%S)"
TARGET_BASE_DIR="/opt/containers"
VOLUME_BACKUP_ENABLED=true
# 加载配置文件
if [ -f "$CONFIG_FILE" ]; then
    source "$CONFIG_FILE"
fi
# 日志函数
log() {
    echo "[$(date '+%Y-%m-%d %H:%M:%S')] $1"
}
# 函数:备份容器卷
backup_volumes() {
    local container=$1
    local backup_path=$2
    log "备份卷数据: $container"
    # 获取容器的挂载点信息
    local volumes=$(docker inspect "$container" | jq -r '.[0].Mounts[] | select(.Type=="bind" or .Type=="volume") | .Source')
    if [ -z "$volumes" ]; then
        log "没有发现卷"
        return 0
    fi
    # 使用临时容器来打包卷数据
    docker run --rm \
        --volumes-from "$container" \
        -v "${backup_path}:/backup" \
        alpine tar czf "/backup/${container}_volumes.tar.gz" \
        /data 2>/dev/null || true
}
# 函数:迁移单个容器
migrate_container() {
    local container=$1
    local image=$2
    local host_port=$3
    local container_port=$4
    local tar_file="${container}_$(date +%Y%m%d%H%M%S).tar"
    log "开始迁移容器: $container"
    # 停止并提交
    docker stop "$container" 2>/dev/null
    docker commit "$container" "${container}:migrated" || {
        log "ERROR: 提交失败: $container"
        return 1
    }
    # 导出
    docker save -o "${BACKUP_DIR}/${tar_file}" "${container}:migrated" || {
        log "ERROR: 导出失败: $container"
        return 1
    }
    # 备份卷
    if [ "$VOLUME_BACKUP_ENABLED" = true ]; then
        backup_volumes "$container" "$BACKUP_DIR"
    fi
    # 传输到目标
    scp "${BACKUP_DIR}/${tar_file}" "${TARGET_USER}@${TARGET_HOST}:${TARGET_BASE_DIR}/" || {
        log "ERROR: 传输失败: $container"
        return 1
    }
    # 远程导入和启动
    ssh "${TARGET_USER}@${TARGET_HOST}" "
        log() { echo \"[\$(date '+%Y-%m-%d %H:%M:%S')] \$1\"; }
        log '加载镜像: ${container}'
        docker load -i ${TARGET_BASE_DIR}/${tar_file}
        # 创建卷目录
        mkdir -p ${TARGET_BASE_DIR}/volumes/${container}
        # 启动容器 - 这里需要根据实际情况调整参数
        docker run -d \\
            --name ${container} \\
            --restart unless-stopped \\
            -p ${host_port}:${container_port} \\
            -v ${TARGET_BASE_DIR}/volumes/${container}:/data \\
            ${container}:migrated
        # 清理
        rm -f ${TARGET_BASE_DIR}/${tar_file}
    " || {
        log "ERROR: 远程执行失败: $container"
        return 1
    }
    # 清理本地
    rm -f "${BACKUP_DIR}/${tar_file}"
    docker rmi "${container}:migrated" 2>/dev/null
    log "迁移完成: $container"
    return 0
}
# 主迁移流程
main() {
    log "启动容器迁移流程"
    # 创建本地备份目录
    mkdir -p "$BACKUP_DIR"
    # 创建目标目录
    ssh "${TARGET_USER}@${TARGET_HOST}" "mkdir -p ${TARGET_BASE_DIR}/volumes"
    # 遍历并迁移所有容器
    for container in "${!CONTAINERS[@]}"; do
        IFS=':' read -r image host_port container_port <<< "${CONTAINERS[$container]}"
        migrate_container "$container" "$image" "$host_port" "$container_port"
    done
    # 清理备份目录
    rm -rf "$BACKUP_DIR"
    log "所有容器迁移完成"
}
# 执行主函数
main

高级配置与优化

配置文件示例 (migration.conf)

# migration.conf - 容器迁移配置文件
# 容器配置: [容器名]=镜像:主机端口:容器端口
CONTAINERS=(
    ["nginx-web"]="nginx:latest:80:80"
    ["mysql-db"]="mysql:8.0:3306:3306"
    ["redis-cache"]="redis:alpine:6379:6379"
)
# 目标服务器配置
TARGET_HOST="192.168.1.100"
TARGET_USER="root"
TARGET_BASE_DIR="/opt/containers"
# 迁移选项
VOLUME_BACKUP_ENABLED=true
KEEP_SOURCE_CONTAINER=false
COMPRESS_LEVEL=6  # gzip压缩级别 1-9
# 网络配置
NETWORK_MODE="bridge"
DEFAULT_DNS="8.8.8.8"
# 资源限制 (可选)
MEMORY_LIMIT="1g"
CPU_LIMIT="2"

并行迁移脚本

#!/bin/bash
# 并行迁移脚本 - parallel_migrate.sh
PARALLEL_LIMIT=3  # 并行执行数量
# 任务队列
declare -a TASKS
# 添加迁移任务
for container in "${!CONTAINERS[@]}"; do
    TASKS+=("$container")
done
# 并行执行函数
run_parallel() {
    local running=0
    local index=0
    while [ $index -lt ${#TASKS[@]} ]; do
        if [ $running -lt $PARALLEL_LIMIT ]; then
            migrate_container "${TASKS[$index]}" &
            ((running++))
            ((index++))
        else
            wait -n
            ((running--))
        fi
    done
    # 等待所有任务完成
    wait
}
# 执行并行迁移
run_parallel

故障恢复脚本

#!/bin/bash
# 故障恢复脚本 - rollback.sh
TARGET_HOST="192.168.1.100"
BACKUP_DIR="/opt/container_backups"
# 回滚到指定版本
rollback_to_version() {
    local container=$1
    local timestamp=$2
    local tar_file="${container}_${timestamp}.tar"
    ssh "$TARGET_HOST" "
        # 停止并删除当前容器
        docker stop $container 2>/dev/null
        docker rm $container 2>/dev/null
        # 加载备份镜像
        docker load -i ${BACKUP_DIR}/${tar_file}
        # 启动旧版本
        docker run -d --name $container --restart unless-stopped \\
            $(cat /opt/container_configs/${container}_config.txt) \\
            ${container}:${timestamp}
    "
}

使用注意事项

  1. 数据一致性:确保在停止容器后提交,避免数据不一致
  2. 网络配置:注意检查目标服务器的网络环境和端口占用
  3. 资源限制:确认目标服务器有足够资源运行容器
  4. 日志保留:迁移过程详细记录日志,便于问题追踪
  5. 测试验证:生产环境迁移前务必在测试环境验证

安全性建议

  • 使用SSH密钥认证而非密码
  • 对传输的文件进行校验(MD5/SHA256)
  • 敏感数据考虑加密传输
  • 迁移后清理临时文件和中间镜像

这个脚本框架可以根据你的具体环境进行调整和扩展,记得在实际使用前充分测试,并根据需要添加错误处理和重试机制。

抱歉,评论功能暂时关闭!