本文目录导读:

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