Shell脚本如何回滚容器应用版本

wen 实用脚本 1

本文目录导读:

Shell脚本如何回滚容器应用版本

  1. 基于Docker容器的回滚
  2. 基于Kubernetes的Pod回滚
  3. 多版本管理回滚脚本
  4. API方式回滚(带数据库迁移)
  5. 使用建议

在Shell脚本中实现容器应用版本回滚,主要有以下几种方法:

基于Docker容器的回滚

使用Docker Compose的回滚脚本

#!/bin/bash
# 回滚脚本 - rollback.sh
# 配置
APP_NAME="myapp"
COMPOSE_FILE="docker-compose.yml"
BACKUP_DIR="./backups"
ROLLBACK_VERSION=$1  # 从命令行参数获取回滚版本
# 颜色输出
RED='\033[0;31m'
GREEN='\033[0;32m'
YELLOW='\033[1;33m'
NC='\033[0m'
log_info() {
    echo -e "${GREEN}[INFO]${NC} $1"
}
log_warn() {
    echo -e "${YELLOW}[WARN]${NC} $1"
}
log_error() {
    echo -e "${RED}[ERROR]${NC} $1"
}
# 检查参数
if [ -z "$ROLLBACK_VERSION" ]; then
    log_error "请指定回滚版本号"
    echo "用法: $0 <版本号>"
    echo "可用版本:"
    ls -1 "$BACKUP_DIR" 2>/dev/null || echo "无可用备份"
    exit 1
fi
# 检查备份是否存在
if [ ! -d "${BACKUP_DIR}/${ROLLBACK_VERSION}" ]; then
    log_error "版本 ${ROLLBACK_VERSION} 的备份不存在"
    exit 1
fi
# 停止当前应用
log_info "停止当前应用..."
docker-compose -f "$COMPOSE_FILE" down || {
    log_error "停止应用失败"
    exit 1
}
# 恢复备份的配置文件
log_info "恢复版本 ${ROLLBACK_VERSION} 的配置..."
cp -r "${BACKUP_DIR}/${ROLLBACK_VERSION}/." ./
# 重新部署指定版本
log_info "部署版本 ${ROLLBACK_VERSION}..."
docker-compose -f "$COMPOSE_FILE" up -d || {
    log_error "部署失败"
    exit 1
}
# 健康检查
log_info "执行健康检查..."
sleep 10
if docker-compose -f "$COMPOSE_FILE" ps | grep -q "Up"; then
    log_info "回滚成功: 应用已恢复到版本 ${ROLLBACK_VERSION}"
else
    log_error "回滚失败: 应用未正常启动"
    exit 1
fi

基于Kubernetes的Pod回滚

Kubernetes回滚脚本

#!/bin/bash
# Kubernetes回滚脚本 - k8s_rollback.sh
# 配置
NAMESPACE="production"
DEPLOYMENT_NAME="myapp-deployment"
ROLLBACK_REVISION=$1
# 颜色输出
GREEN='\033[0;32m'
YELLOW='\033[1;33m'
RED='\033[0;31m'
NC='\033[0m'
# 检查kubectl是否安装
check_kubectl() {
    if ! command -v kubectl &> /dev/null; then
        log_error "kubectl未安装"
        exit 1
    fi
}
log_info() { echo -e "${GREEN}[INFO]${NC} $1"; }
log_warn() { echo -e "${YELLOW}[WARN]${NC} $1"; }
log_error() { echo -e "${RED}[ERROR]${NC} $1"; }
# 获取部署历史
list_revisions() {
    log_info "可用的回滚版本:"
    kubectl rollout history deployment/"${DEPLOYMENT_NAME}" -n "${NAMESPACE}"
}
# 执行回滚
rollback_deployment() {
    local revision=$1
    if [ -z "$revision" ]; then
        log_warn "未指定版本,回滚到上一个版本"
        kubectl rollout undo deployment/"${DEPLOYMENT_NAME}" -n "${NAMESPACE}"
    else
        log_info "回滚到版本: ${revision}"
        kubectl rollout undo deployment/"${DEPLOYMENT_NAME}" \
            -n "${NAMESPACE}" \
            --to-revision="${revision}"
    fi
    # 监控回滚状态
    log_info "监控回滚状态..."
    kubectl rollout status deployment/"${DEPLOYMENT_NAME}" \
        -n "${NAMESPACE}" \
        --timeout=120s
}
# 主函数
main() {
    check_kubectl
    # 如果不带参数,显示版本列表
    if [ $# -eq 0 ]; then
        list_revisions
        echo ""
        read -p "请输入要回滚到的版本号: " revision
        rollback_deployment "$revision"
    else
        rollback_deployment "$ROLLBACK_REVISION"
    fi
    # 验证回滚结果
    log_info "当前运行版本:"
    kubectl get deployment "${DEPLOYMENT_NAME}" \
        -n "${NAMESPACE}" \
        -o jsonpath='{.spec.template.metadata.labels.version}'
}
main "$@"

多版本管理回滚脚本

#!/bin/bash
# 多版本管理回滚 - multi_version_rollback.sh
# 配置
APP_NAME="myapp"
IMAGE_REGISTRY="registry.example.com"
CURRENT_VERSION_FILE="/var/lib/${APP_NAME}/current_version"
BACKUP_DIR="/var/backups/${APP_NAME}"
COMPOSE_FILE="/opt/${APP_NAME}/docker-compose.yml"
# 初始化
init() {
    mkdir -p "${BACKUP_DIR}"
    mkdir -p "$(dirname ${CURRENT_VERSION_FILE})"
}
# 记录当前版本
record_version() {
    local version=$1
    echo "$version" > "$CURRENT_VERSION_FILE"
    echo "$(date '+%Y-%m-%d %H:%M:%S') - 部署版本: $version" >> "${BACKUP_DIR}/deploy_history.log"
}
# 备份当前配置
backup_current_config() {
    local version=$(cat "$CURRENT_VERSION_FILE" 2>/dev/null)
    if [ -n "$version" ]; then
        log_info "备份当前版本 ${version} 的配置..."
        tar -czf "${BACKUP_DIR}/config_${version}_$(date +%Y%m%d_%H%M%S).tar.gz" \
            -C "$(dirname ${COMPOSE_FILE})" .
    fi
}
# 执行回滚
rollback_to_version() {
    local target_version=$1
    local backup_file="${BACKUP_DIR}/config_${target_version}_*.tar.gz"
    # 查找备份文件
    local latest_backup=$(ls -t $backup_file 2>/dev/null | head -1)
    if [ -z "$latest_backup" ]; then
        log_error "未找到版本 ${target_version} 的备份文件"
        return 1
    fi
    # 备份当前版本
    backup_current_config
    # 停止当前服务
    log_info "停止当前服务..."
    docker-compose -f "$COMPOSE_FILE" down
    # 恢复目标版本配置
    log_info "恢复版本 ${target_version} 的配置..."
    tar -xzf "$latest_backup" -C "$(dirname ${COMPOSE_FILE})"
    # 拉取特定版本镜像
    log_info "拉取版本 ${target_version} 的镜像..."
    docker pull "${IMAGE_REGISTRY}/${APP_NAME}:${target_version}"
    # 启动服务
    log_info "启动服务..."
    docker-compose -f "$COMPOSE_FILE" up -d
    # 等待服务启动
    sleep 5
    # 健康检查
    if curl -s http://localhost:8080/health | grep -q "OK"; then
        record_version "$target_version"
        log_info "回滚成功!当前版本: ${target_version}"
        return 0
    else
        log_error "回滚失败,启动自动恢复..."
        # 自动恢复到上一个版本
        docker-compose -f "$COMPOSE_FILE" down
        tar -xzf "${BACKUP_DIR}/config_${target_version}_*.tar.gz" -C "$(dirname ${COMPOSE_FILE})"
        docker-compose -f "$COMPOSE_FILE" up -d
        return 1
    fi
}
# 主函数
main() {
    local target_version=$1
    init
    case "${target_version}" in
        "list")
            echo "可用版本列表:"
            ls -1 "${BACKUP_DIR}"/*.tar.gz | while read file; do
                basename "$file" | cut -d'_' -f2
            done | sort -u
            ;;
        "current")
            cat "$CURRENT_VERSION_FILE" 2>/dev/null || echo "无记录"
            ;;
        *)
            if [ -z "${target_version}" ]; then
                echo "用法: $0 <版本号|list|current>"
                exit 1
            fi
            rollback_to_version "${target_version}"
            ;;
    esac
}
# 日志函数
log_info() { echo -e "\033[0;32m[INFO]\033[0m $1"; }
log_error() { echo -e "\033[0;31m[ERROR]\033[0m $1"; }
main "$@"

API方式回滚(带数据库迁移)

#!/bin/bash
# API版本回滚带数据库迁移 - api_rollback.sh
# 配置
API_ENDPOINT="https://api.example.com"
API_KEY="your-api-key"
SERVICE_NAME="user-service"
DB_MIGRATIONS_DIR="/opt/migrations"
# 回滚函数
rollback_api_version() {
    local old_version=$1
    local new_version=$2
    # 1. 执行数据库迁移回滚
    log_info "执行数据库迁移回滚..."
    if [ -f "${DB_MIGRATIONS_DIR}/rollback_${old_version}_to_${new_version}.sql" ]; then
        mysql -u root -p${DB_PASSWORD} ${DB_NAME} < \
            "${DB_MIGRATIONS_DIR}/rollback_${old_version}_to_${new_version}.sql"
    fi
    # 2. 调用API回滚
    log_info "通过API执行服务回滚..."
    curl -X POST "${API_ENDPOINT}/api/v1/deploy/rollback" \
        -H "Authorization: Bearer ${API_KEY}" \
        -H "Content-Type: application/json" \
        -d '{
            "service": "'${SERVICE_NAME}'",
            "from_version": "'${old_version}'",
            "to_version": "'${new_version}'"
        }'
    # 3. 验证回滚
    sleep 10
    local current_version=$(curl -s "${API_ENDPOINT}/api/v1/version" | jq -r '.version')
    if [ "$current_version" == "$new_version" ]; then
        log_info "API回滚成功"
        return 0
    else
        log_error "API回滚失败"
        return 1
    fi
}

使用建议

  1. 版本标记:始终为每个部署版本添加明确的标签或标记
  2. 备份机制:在更新前备份当前配置和数据
  3. 灰度回滚:对于生产环境,建议先在小范围内验证
  4. 自动回滚:如果健康检查失败,自动触发回滚
  5. 日志记录:记录所有回滚操作,便于审计

选择合适的回滚策略取决于你的部署环境:

  • Docker: 使用docker-compose和备份文件
  • Kubernetes: 使用kubectl rollout命令
  • 自定义: 使用API和多版本管理

脚本应该包含:版本检查、备份、执行回滚、健康验证等关键步骤。

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