脚本如何快速回滚灰度版本

wen 实用脚本 31

本文目录导读:

脚本如何快速回滚灰度版本

  1. 核心原则:回滚不是重新部署,而是切换流量
  2. 方案一:基于 Kubernetes + Deployment(最常用)
  3. 方案二:基于 Nginx / OpenResty(蓝绿部署)
  4. 方案三:基于 Istio / Service Mesh(最精细)
  5. 方案四:通用脚本(非容器化环境)
  6. 几种方案的对比
  7. 一个“偷懒”但高效的思路:别名远程调用
  8. 建议

实现灰度版本的快速回滚,核心在于将回滚动作自动化、原子化,由于你提到“脚本”,这里提供几种不同架构下的快速回滚脚本方案,从最轻量到最完备。


核心原则:回滚不是重新部署,而是切换流量

最快的回滚不是把旧包重新解压、重启,而是:

  1. 保留旧版本实例:始终保留上一版本的容器/进程。
  2. 流量切换:通过网关或负载均衡,瞬间将流量从新版本切回旧版本。

基于 Kubernetes + Deployment(最常用)

Kubernetes 中灰度发布通常用 ServiceIngress 控制流量。

场景:

灰度版本通过 Deployment 滚动更新,旧版本 Deployment 未被删除,只是 ReplicaSet 数量被缩容。

快速回滚脚本 (Bash):

#!/bin/bash
# 脚本名:rollback_gray.sh
# 用途:快速回滚 K8s 中某个 Deployment 的上一个版本
set -e
NAMESPACE="${1:-default}"
DEPLOY="${2:-}"
ROLLBACK_TO="${3:-}" # 可选:指定版本号,revision=5
if [ -z "$DEPLOY" ]; then
  echo "Usage: $0 <namespace> <deployment_name> [revision]"
  exit 1
fi
echo "🔄 开始回滚灰度版本..."
echo "命名空间: $NAMESPACE"
echo "Deployment: $DEPLOY"
if [ -n "$ROLLBACK_TO" ]; then
  # 回滚到指定版本
  echo "回滚到指定版本: revision $ROLLBACK_TO"
  kubectl rollout undo deployment/${DEPLOY} -n ${NAMESPACE} --to-revision=${ROLLBACK_TO}
else
  # 快速回滚到上一个版本
  echo "回滚到上一个版本..."
  kubectl rollout undo deployment/${DEPLOY} -n ${NAMESPACE}
fi
# 检查回滚状态
echo "⏳ 等待回滚完成..."
kubectl rollout status deployment/${DEPLOY} -n ${NAMESPACE} --timeout=120s
if [ $? -eq 0 ]; then
    echo "✅ 回滚成功!当前版本已切换回旧版。"
else
    echo "❌ 回滚超时或失败,请检查 pod 状态。"
    kubectl get pods -n ${NAMESPACE} | grep ${DEPLOY}
fi

执行方式bash rollback_gray.sh production my-app-gray

优势:秒级回滚,K8s 自带历史版本管理。


基于 Nginx / OpenResty(蓝绿部署)

场景:

通过 Nginx 的 upstream 配置切换流量,脚本只需修改配置文件并 reload。

快速回滚脚本 (Python):

#!/usr/bin/env python3
# 脚本名:nginx_rollback.py
# 用途:通过修改 Nginx upstream 权重,快速切回旧版本
import subprocess
import sys
import os
NGINX_CONF = "/etc/nginx/conf.d/gray.conf"  # 灰度配置路径
def rollback():
    # 将 blue 组权重改为 100,green 组改为 0
    new_config = """
upstream backend {
    server 10.0.1.10:8080 weight=100;  # 旧版本 (蓝色)
    server 10.0.1.20:8080 weight=0;   # 新版本 (绿色,灰度)
}
"""
    with open(NGINX_CONF, 'w') as f:
        f.write(new_config)
    # 重新加载 Nginx 配置
    result = subprocess.run(['nginx', '-s', 'reload'], capture_output=True, text=True)
    if result.returncode == 0:
        print("✅ 回滚成功,流量已切回旧版本 (Blue)。")
    else:
        print(f"❌ Nginx reload 失败: {result.stderr}")
        sys.exit(1)
if __name__ == "__main__":
    rollback()

执行方式python3 nginx_rollback.py

优势:毫秒级切换,不重启服务。


基于 Istio / Service Mesh(最精细)

场景:

灰度版本通过 VirtualService 的权重控制。

快速回滚脚本 (Bash):

#!/bin/bash
# 回滚 Istio 灰度流量
kubectl patch virtualservice my-service -n default --type='json' \
  -p='[
    {"op": "replace", "path": "/spec/http/0/route/0/weight", "value": 100},
    {"op": "replace", "path": "/spec/http/0/route/1/weight", "value": 0}
  ]'
echo "✅ Istio 灰度流量已回滚,100% 流量切回主版本。"

执行方式:直接运行脚本。

优势:精细化流量控制,支持金丝雀发布一键回滚。


通用脚本(非容器化环境)

场景:

传统物理机/虚拟机,灰度版本与旧版本目录隔离。

快速回滚脚本 (Bash)

#!/bin/bash
# 脚本名:fast_rollback.sh
# 用途:切换软链接或重启旧版本进程
APP_DIR="/opt/myapp"
GRAY_DIR="${APP_DIR}_gray"
OLD_DIR="${APP_DIR}_old"
CURRENT_LINK="${APP_DIR}/current"
if [ ! -d "$OLD_DIR" ]; then
    echo "❌ 旧版本目录不存在 ($OLD_DIR),无法回滚。"
    exit 1
fi
echo "🔄 开始回滚..."
# 1. 切换软链接
ln -sfn "$OLD_DIR" "$CURRENT_LINK"
# 2. 停止新版进程,启动旧版进程
pkill -f "${GRAY_DIR}/bin/app" || true
${OLD_DIR}/bin/start.sh
echo "✅ 回滚完成,当前版本为旧版本。"

注意:此方案重度依赖于灰度发布脚本在发布时备份了一份完整的老版本,否则无法回滚这么迅速。


几种方案的对比

方案 回滚速度 复杂度 依赖项 适用场景
Kubernetes 秒级 K8s 容器化微服务
Nginx 权重 毫秒级 Nginx 蓝绿部署
Istio 毫秒级 Istio 服务网格、精细灰度
传统文件 分钟级 备份脚本 传统架构

一个“偷懒”但高效的思路:别名远程调用

如果你觉得写脚本还是太麻烦,可以将回滚命令封装成一个远程调用的别名

# 在你的 ~/.bashrc 或 ~/.zshrc 里添加:
alias rollback-gray='kubectl rollout undo deployment/my-app-gray -n production && kubectl rollout status deployment/my-app-gray -n production'

之后,你只需要在终端输入 rollback-gray 即可完成回滚。


建议

  1. 自动化监控:将回滚脚本接入监控告警,当灰度版本的错误率超过 5% 时,自动执行回滚脚本。
  2. 权限控制:回滚操作应记录审计日志。
  3. 保留多版本:建议至少保留最近 2-3 个版本的备份,以便应对复杂回滚场景。

如果你是容器化环境,推荐使用方案一(Kubernetes),回滚能力是内置的,最稳定、最快速。

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