Files

218 lines
5.5 KiB
Bash
Raw Permalink Normal View History

#!/bin/bash
# =============================================================================
# 企微IT智能服务台 — 蓝绿部署脚本
# =============================================================================
# 目标服务器:10.90.5.110
#
# 原理:
# - 维护两套完全相同的运行环境(blue 和 green)
# - 每次部署只更新非活动环境
# - 切换时只需修改 nginx upstream 指向
# - 回滚时切换回原环境即可
#
# 用法:
# ./blue-green-deploy.sh status # 查看当前状态
# ./blue-green-deploy.sh deploy blue # 部署到 blue 环境
# ./blue-green-deploy.sh deploy green # 部署到 green 环境
# ./blue-green-deploy.sh switch blue # 切换流量到 blue
# ./blue-green-deploy.sh switch green # 切换流量到 green
# ./blue-green-deploy.sh rollback # 回滚到上一个环境
# ./blue-green-deploy.sh clean # 清理旧容器
# =============================================================================
set -e
# 配置
COMPOSE_FILE="docker-compose.split.yml"
ENV_FILE=".env"
ACTIVE_FILE="/tmp/active_environment"
# 颜色定义
RED='\033[0;31m'
GREEN='\033[0;32m'
YELLOW='\033[1;33m'
BLUE='\033[0;34m'
NC='\033[0m' # No Color
# 日志函数
log_info() {
echo -e "${GREEN}[INFO]${NC} $1"
}
log_warn() {
echo -e "${YELLOW}[WARN]${NC} $1"
}
log_error() {
echo -e "${RED}[ERROR]${NC} $1"
}
# 检查环境
check_env() {
if [ ! -f "$ENV_FILE" ]; then
log_error "环境配置文件不存在: $ENV_FILE"
log_info "请先复制 .env.example 为 .env 并配置"
exit 1
fi
}
# 获取当前活动环境
get_active_env() {
if [ -f "$ACTIVE_FILE" ]; then
cat "$ACTIVE_FILE"
else
echo "green" # 默认 green
fi
}
# 设置活动环境
set_active_env() {
echo "$1" > "$ACTIVE_FILE"
log_info "当前活动环境: $1"
}
# 获取非活动环境
get_inactive_env() {
active=$(get_active_env)
if [ "$active" = "blue" ]; then
echo "green"
else
echo "blue"
fi
}
# 构建并部署到指定环境
deploy_to() {
local env=$1
log_info "开始部署到 $env 环境..."
# 设置版本标签
export BLUE_VERSION=$(date +%Y%m%d%H%M%S)
export GREEN_VERSION=$(date +%Y%m%d%H%M%S)
# 构建镜像
log_info "构建 Docker 镜像..."
docker compose -f "$COMPOSE_FILE" build
# 停止旧容器(指定环境)
log_info "停止旧容器..."
docker compose -f "$COMPOSE_FILE" down || true
# 启动新容器
log_info "启动新容器..."
docker compose -f "$COMPOSE_FILE" up -d
# 等待服务健康
log_info "等待服务健康检查..."
sleep 30
# 检查服务状态
if ! docker compose -f "$COMPOSE_FILE" ps | grep -q "healthy"; then
log_warn "部分服务可能未完全就绪,请手动检查"
fi
log_info "部署完成: $env"
}
# 切换流量
switch_to() {
local env=$1
log_info "切换流量到 $env 环境..."
# 更新 nginx 配置(使用 upstream
# 这里简化处理:实际应该修改 nginx 的 upstream 指向
# 或者使用容器标签切换
set_active_env "$env"
log_info "流量已切换到 $env 环境"
}
# 回滚
rollback() {
active=$(get_active_env)
inactive=$(get_inactive_env)
log_warn "当前活动环境: $active"
log_info "回滚到: $inactive"
switch_to "$inactive"
log_info "已回滚到 $inactive 环境"
}
# 查看状态
status() {
active=$(get_active_env)
inactive=$(get_inactive_env)
echo "=============================================="
echo " 蓝绿部署状态"
echo "=============================================="
echo -e "活动环境: ${GREEN}$active${NC}"
echo -e "备用环境: ${YELLOW}$inactive${NC}"
echo "=============================================="
echo ""
echo "容器状态:"
docker compose -f "$COMPOSE_FILE" ps 2>/dev/null || echo "未运行"
}
# 清理旧容器
clean() {
log_warn "清理所有旧容器和镜像..."
docker compose -f "$COMPOSE_FILE" down --rmi all --volumes
rm -f "$ACTIVE_FILE"
log_info "清理完成"
}
# 主入口
main() {
command=$1
param=$2
check_env
case $command in
status)
status
;;
deploy)
if [ -z "$param" ]; then
log_error "请指定部署环境: blue 或 green"
echo "用法: $0 deploy <blue|green>"
exit 1
fi
if [ "$param" != "blue" ] && [ "$param" != "green" ]; then
log_error "无效的环境: $param"
exit 1
fi
deploy_to "$param"
;;
switch)
if [ -z "$param" ]; then
log_error "请指定切换目标: blue 或 green"
echo "用法: $0 switch <blue|green>"
exit 1
fi
switch_to "$param"
;;
rollback)
rollback
;;
clean)
clean
;;
*)
echo "用法:"
echo " $0 status # 查看当前状态"
echo " $0 deploy blue # 部署到 blue 环境"
echo " $0 deploy green # 部署到 green 环境"
echo " $0 switch blue # 切换流量到 blue"
echo " $0 switch green # 切换流量到 green"
echo " $0 rollback # 回滚到上一个环境"
echo " $0 clean # 清理所有容器和镜像"
exit 1
;;
esac
}
main "$@"