Shell脚本如何实现渐进式交付策略

wen 实用脚本 22

本文目录导读:

Shell脚本如何实现渐进式交付策略

  1. 基础架构设计
  2. 蓝绿部署实现
  3. 金丝雀发布实现
  4. 滚动更新实现
  5. 健康检查与指标监控
  6. 回滚机制
  7. 完整部署流程
  8. 集成测试示例

Shell脚本实现渐进式交付策略通常需要结合流量控制、健康检查和回滚机制,下面是完整的实现方案:

基础架构设计

#!/bin/bash
# 配置变量
APP_NAME="myapp"
DEPLOY_DIR="/opt/app"
ROLLBACK_DIR="/opt/app/rollback"
HEALTH_CHECK_URL="http://localhost:8080/health"
MIN_HEALTHY_INSTANCES=2
MAX_INSTANCES=5
CANARY_PERCENT=10
# 颜色输出
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"; }

蓝绿部署实现

# 蓝绿部署
blue_green_deploy() {
    local version=$1
    local new_color="green"
    local old_color="blue"
    log_info "开始蓝绿部署,版本: $version"
    # 检查当前活跃环境
    if [ -f "$DEPLOY_DIR/active_color" ]; then
        old_color=$(cat "$DEPLOY_DIR/active_color")
        [ "$old_color" == "blue" ] && new_color="green" || new_color="blue"
    fi
    # 部署新版本
    deploy_to_color "$new_color" "$version"
    # 健康检查
    if health_check "$new_color"; then
        # 切换流量
        switch_traffic "$new_color"
        echo "$new_color" > "$DEPLOY_DIR/active_color"
        log_info "流量已切换到 $new_color"
        # 清理旧版本
        clean_old_version "$old_color"
    else
        log_error "部署失败,执行回滚"
        rollback_to_color "$old_color"
        exit 1
    fi
}
deploy_to_color() {
    local color=$1
    local version=$2
    log_info "部署到 $color 环境,版本: $version"
    # 备份当前版本
    if [ -d "$DEPLOY_DIR/$color" ]; then
        tar czf "$ROLLBACK_DIR/${color}_$(date +%Y%m%d_%H%M%S).tar.gz" -C "$DEPLOY_DIR/$color" .
    fi
    # 部署新版本
    mkdir -p "$DEPLOY_DIR/$color"
    cp -r "$DEPLOY_DIR/packages/$version/"* "$DEPLOY_DIR/$color/"
    # 启动服务
    systemctl restart "$APP_NAME@$color"
}

金丝雀发布实现

# 金丝雀发布
canary_deploy() {
    local version=$1
    local canary_instances=$2
    log_info "开始金丝雀发布,版本: $version"
    log_info "金丝雀实例数: $canary_instances"
    # 启动金丝雀实例
    for i in $(seq 1 $canary_instances); do
        local port=$((8080 + i))
        start_canary_instance "$version" "$port"
    done
    # 等待服务启动
    sleep 10
    # 验证金丝雀实例
    if verify_canary_instances "$canary_instances"; then
        log_info "金丝雀验证通过,逐步增加流量"
        # 渐进式增加流量
        for percentage in 10 25 50 75 100; do
            update_traffic_weight "$percentage"
            sleep 30  # 观察期
            if ! check_system_health; then
                log_error "系统健康检查失败,执行回滚"
                rollback_canary
                exit 1
            fi
        done
        # 完成发布
        finalize_canary_deploy "$version"
    else
        log_error "金丝雀实例验证失败"
        rollback_canary
        exit 1
    fi
}
start_canary_instance() {
    local version=$1
    local port=$2
    # 使用容器或直接启动进程
    docker run -d \
        --name "${APP_NAME}_canary_${port}" \
        -p "$port:8080" \
        -e "VERSION=$version" \
        -e "CANARY=true" \
        "$APP_NAME:$version"
}
verify_canary_instances() {
    local count=$1
    local healthy=0
    for i in $(seq 1 $count); do
        local port=$((8080 + i))
        if curl -s "http://localhost:$port/health" | grep -q "ok"; then
            healthy=$((healthy + 1))
        fi
    done
    [ $healthy -eq $count ]
}

滚动更新实现

# 滚动更新
rolling_update() {
    local version=$1
    local instances=($(get_active_instances))
    local batch_size=1
    log_info "开始滚动更新,版本: $version"
    # 分批更新
    for ((i=0; i<${#instances[@]}; i+=batch_size)); do
        local batch=("${instances[@]:i:batch_size}")
        # 从负载均衡器移除
        remove_from_lb "${batch[@]}"
        # 更新实例
        for instance in "${batch[@]}"; do
            update_instance "$instance" "$version"
        done
        # 健康检查
        if check_batch_health "${batch[@]}"; then
            # 重新加入负载均衡器
            add_to_lb "${batch[@]}"
            log_info "批次更新完成: ${batch[*]}"
        else
            log_error "批次健康检查失败"
            rollback_batch "${batch[@]}"
            exit 1
        fi
    done
    log_info "滚动更新完成"
}
get_active_instances() {
    # 获取所有运行中的实例ID
    systemctl list-units --type=service --state=running | \
        grep "$APP_NAME@" | cut -d@ -f2 | cut -d. -f1 | sort
}
update_instance() {
    local instance=$1
    local version=$2
    log_info "更新实例: $instance"
    # 停止服务
    systemctl stop "$APP_NAME@$instance"
    # 更新代码
    rsync -a --delete "$DEPLOY_DIR/packages/$version/" "/opt/app/instances/$instance/"
    # 启动服务
    systemctl start "$APP_NAME@$instance"
    # 等待服务就绪
    wait_for_ready "$instance"
}

健康检查与指标监控

# 健康检查
health_check() {
    local environment=$1
    local check_pid
    log_info "执行健康检查..."
    # 基础健康检查
    check_basic_health() {
        curl -sf "$HEALTH_CHECK_URL" > /dev/null 2>&1
    }
    # 功能测试
    run_functional_tests() {
        # 执行集成测试
        python3 /opt/scripts/test_suite.py
        return $?
    }
    # 性能检查
    check_performance() {
        local threshold=500  # 最大响应时间(ms)
        local response_time
        response_time=$(curl -o /dev/null -s -w '%{time_total}' "$HEALTH_CHECK_URL")
        local result=$(echo "$response_time * 1000 / 1" | bc)
        [ $result -lt $threshold ]
    }
    # 并行执行检查
    {
        check_basic_health && run_functional_tests && check_performance
    } &
    check_pid=$!
    # 超时控制
    if wait $check_pid; then
        return 0
    else
        return 1
    fi
}
# 渐进式流量切换
update_traffic_weight() {
    local percentage=$1
    if command -v nginx &> /dev/null; then
        # Nginx 配置
        cat > /etc/nginx/conf.d/canary.conf << EOF
upstream backend {
    server 127.0.0.1:8080 weight=$((100 - percentage));
    server 127.0.0.1:8081 weight=$percentage;
}
EOF
        nginx -s reload
    fi
}

回滚机制

# 回滚到指定版本
rollback_deploy() {
    local target_version=$1
    log_warn "执行回滚操作到版本: $target_version"
    # 保存当前状态
    backup_current_state
    # 执行回滚
    case $DEPLOY_STRATEGY in
        "blue_green")
            rollback_blue_green "$target_version"
            ;;
        "canary")
            rollback_canary
            ;;
        "rolling")
            rollback_rolling "$target_version"
            ;;
    esac
    # 验证回滚
    if health_check "production"; then
        log_info "回滚成功"
    else
        log_error "回滚后系统异常,需要人工干预"
        alert_ops_team "回滚失败"
        exit 1
    fi
}
rollback_canary() {
    log_info "回滚金丝雀发布"
    # 停止金丝雀实例
    docker ps --filter "label=CANARY=true" -q | xargs -r docker stop
    # 恢复原始流量分配
    update_traffic_weight 0
    # 清理金丝雀容器
    docker ps -a --filter "label=CANARY=true" -q | xargs -r docker rm
}
backup_current_state() {
    local timestamp=$(date +%Y%m%d_%H%M%S)
    # 备份配置
    cp -r "$DEPLOY_DIR/config" "$ROLLBACK_DIR/config_$timestamp"
    # 备份负载均衡配置
    if [ -f "/etc/nginx/conf.d/$APP_NAME.conf" ]; then
        cp "/etc/nginx/conf.d/$APP_NAME.conf" "$ROLLBACK_DIR/nginx_$timestamp.conf"
    fi
}

完整部署流程

# 主部署函数
progressive_deploy() {
    local version=$1
    local strategy=${2:-"blue_green"}  # blue_green, canary, rolling
    log_info "=== 开始渐进式交付 ==="
    log_info "版本: $version"
    log_info "策略: $strategy"
    # 前置检查
    pre_deploy_checks "$version" || exit 1
    # 执行部署
    case $strategy in
        "blue_green")
            blue_green_deploy "$version"
            ;;
        "canary")
            canary_deploy "$version" 2  # 2个金丝雀实例
            ;;
        "rolling")
            rolling_update "$version"
            ;;
        *)
            log_error "未知的部署策略: $strategy"
            exit 1
    esac
    # 部署后验证
    post_deploy_validation
    log_info "=== 渐进式交付完成 ==="
}
pre_deploy_checks() {
    local version=$1
    # 检查版本包是否存在
    [ -d "$DEPLOY_DIR/packages/$version" ] || {
        log_error "版本包不存在: $version"
        return 1
    }
    # 检查系统资源
    check_system_resources || return 1
    # 检查当前服务状态
    check_current_service_state || return 1
    return 0
}
# 使用示例
main() {
    local VERSION=${1:-"v1.2.3"}
    local STRATEGY=${2:-"canary"}
    # 锁定部署
    acquire_deploy_lock
    # 执行部署
    progressive_deploy "$VERSION" "$STRATEGY"
    # 释放锁
    release_deploy_lock
}
# 执行脚本
if [ "$0" = "$BASH_SOURCE" ]; then
    main "$@"
fi

集成测试示例

# 测试脚本
test_progressive_deploy() {
    echo "测试渐进式部署..."
    # 模拟测试环境
    setup_test_environment
    # 测试金丝雀发布
    canary_deploy "test-v1" 1
    # 验证日志
    tail -f /var/log/deploy.log
    # 清理测试环境
    cleanup_test_environment
}

这个实现提供了完整的渐进式交付能力,支持多种部署策略并在出现问题时自动回滚,根据实际需求可以调整参数和增加更多监控指标。

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