本文目录导读:

实现灰度发布策略的Shell脚本通常需要结合负载均衡器(如Nginx、HAProxy)或服务注册中心进行操作,以下是几种常见的实现方案及示例代码。
基于Nginx的灰度发布
通过修改upstream配置,动态调整灰度服务器权重。
脚本示例
#!/bin/bash
# 灰度发布脚本 - Nginx版本
NGINX_CONF="/etc/nginx/conf.d/upstream.conf"
NGINX_BINARY="/usr/sbin/nginx"
BACKUP_DIR="/tmp/nginx_backup"
# 服务节点配置
PRODUCTION_SERVERS=("192.168.1.10:8080" "192.168.1.11:8080" "192.168.1.12:8080")
GRAY_SERVERS=("192.168.1.100:8080")
# 颜色输出
RED='\033[0;31m'
GREEN='\033[0;32m'
YELLOW='\033[1;33m'
NC='\033[0m' # No Color
# 函数:生成upstream配置
generate_upstream_conf() {
local gray_weight=$1
cat > "$NGINX_CONF" << EOF
upstream backend {
# 生产服务器
EOF
for server in "${PRODUCTION_SERVERS[@]}"; do
echo " server $server weight=10;" >> "$NGINX_CONF"
done
cat >> "$NGINX_CONF" << EOF
# 灰度服务器
EOF
for server in "${GRAY_SERVERS[@]}"; do
if [ "$gray_weight" -gt 0 ] 2>/dev/null; then
echo " server $server weight=$gray_weight;" >> "$NGINX_CONF"
fi
done
echo "}" >> "$NGINX_CONF"
}
# 函数:备份配置
backup_config() {
mkdir -p "$BACKUP_DIR"
local backup_file="$BACKUP_DIR/upstream.conf.$(date +%Y%m%d_%H%M%S)"
cp "$NGINX_CONF" "$backup_file"
echo -e "${GREEN}配置已备份到: $backup_file${NC}"
}
# 函数:检查Nginx配置
check_nginx() {
$NGINX_BINARY -t 2>&1
return $?
}
# 函数:重载Nginx
reload_nginx() {
$NGINX_BINARY -s reload 2>&1
return $?
}
# 函数:执行灰度发布
gray_deploy() {
local weight=$1
echo -e "${YELLOW}开始灰度发布...${NC}"
# 备份当前配置
backup_config
# 生成新配置
generate_upstream_conf "$weight"
# 检查配置
if check_nginx; then
echo -e "${GREEN}Nginx配置检查通过${NC}"
# 重载Nginx
if reload_nginx; then
echo -e "${GREEN}灰度发布完成${NC}"
echo -e "灰度权重: ${weight}/10"
return 0
else
echo -e "${RED}Nginx重载失败,回滚配置...${NC}"
# 回滚配置
latest_backup=$(ls -t "$BACKUP_DIR"/upstream.conf.* | head -1)
if [ -n "$latest_backup" ]; then
cp "$latest_backup" "$NGINX_CONF"
reload_nginx
fi
return 1
fi
else
echo -e "${RED}Nginx配置检查失败,保留配置供调试${NC}"
return 1
fi
}
# 主菜单
show_menu() {
echo "=== 灰度发布管理脚本 ==="
echo "1. 开始灰度发布 (10%流量)"
echo "2. 增加灰度流量 (20%)"
echo "3. 增加灰度流量 (50%)"
echo "4. 全量发布"
echo "5. 回滚到生产版本"
echo "6. 查看当前状态"
echo "0. 退出"
echo "======================"
}
# 主逻辑
while true; do
show_menu
read -p "请选择操作: " choice
case $choice in
1) gray_deploy 1 ;;
2) gray_deploy 2 ;;
3) gray_deploy 5 ;;
4) gray_deploy 10 ;;
5) gray_deploy 0 ;;
6)
echo -e "${YELLOW}当前配置状态:${NC}"
cat "$NGINX_CONF"
;;
0)
echo -e "${GREEN}退出脚本${NC}"
exit 0
;;
*) echo -e "${RED}无效选择${NC}" ;;
esac
echo ""
done
基于Consul的服务发现灰度
使用Consul的服务注册与健康检查实现灰度发布。
#!/bin/bash
# 灰度发布脚本 - Consul版本
CONSUL_BIN="/usr/local/bin/consul"
CONSUL_ADDR="http://localhost:8500"
# 服务配置
SERVICE_NAME="myapp"
TAG_PRODUCTION="production"
TAG_GRAY="gray"
REGION="us-east-1"
# 颜色输出
RED='\033[0;31m'
GREEN='\033[0;32m'
YELLOW='\033[1;33m'
NC='\033[0m'
# 函数:获取服务实例
get_service_instances() {
local tag=$1
$CONSUL_BIN catalog services \
-http-addr="$CONSUL_ADDR" \
-filter="ServiceName == \"$SERVICE_NAME\" and ServiceTags contains \"$tag\"" \
| jq -r '.[] | .Address + ":" + (.ServicePort|tostring)'
}
# 函数:注册灰度服务
register_gray_service() {
local instance_id=$1
local address=$2
local port=$3
cat > /tmp/gray_service.json << EOF
{
"ID": "$instance_id-gray",
"Name": "$SERVICE_NAME",
"Address": "$address",
"Port": $port,
"Tags": ["$TAG_GRAY", "$REGION"],
"Check": {
"HTTP": "http://$address:$port/health",
"Interval": "10s",
"Timeout": "5s",
"DeregisterCriticalServiceAfter": "30s"
}
}
EOF
$CONSUL_BIN services register \
-http-addr="$CONSUL_ADDR" \
/tmp/gray_service.json
echo -e "${GREEN}灰度服务 $instance_id-gray 注册成功${NC}"
}
# 函数:切换标签
switch_tags() {
local instance_id=$1
local to_tag=$2
# 获取当前服务信息
local service_info=$($CONSUL_BIN catalog service \
-http-addr="$CONSUL_ADDR" \
"$SERVICE_NAME-$instance_id" 2>/dev/null)
if [ -n "$service_info" ]; then
$CONSUL_BIN services deregister \
-http-addr="$CONSUL_ADDR" \
"id=$SERVICE_NAME-$instance_id"
fi
# 重新注册为新的tag
cat > /tmp/service_update.json << EOF
{
"ID": "$SERVICE_NAME-$instance_id",
"Name": "$SERVICE_NAME",
"Tags": ["$to_tag", "$REGION"]
}
EOF
$CONSUL_BIN services register \
-http-addr="$CONSUL_ADDR" \
/tmp/service_update.json
echo -e "${GREEN}服务 $instance_id 切换到 $to_tag${NC}"
}
# 函数:灰度策略 - 按比例
gray_deploy_by_percent() {
local percent=$1
local total_instances=$2
local gray_instances=$(( total_instances * percent / 100 ))
echo -e "${YELLOW}灰度发布 $percent% 流量...${NC}"
# 获取所有生产实例
local production_instances=($(get_service_instances "$TAG_PRODUCTION"))
local count=0
for instance in "${production_instances[@]}"; do
if [ $count -lt $gray_instances ]; then
# 切换到灰度标签
switch_tags "$instance" "$TAG_GRAY"
((count++))
else
break
fi
done
echo -e "${GREEN}灰度发布完成: $gray_instances/$total_instances 实例${NC}"
}
# 函数:灰度策略 - 按用户ID
gray_deploy_by_user_id() {
local user_id_range=$1
echo -e "${YELLOW}为特定用户ID范围 ($user_id_range%) 启用灰度...${NC}"
# 注册灰度版本并设置用户ID过滤
$CONSUL_BIN kv put \
-http-addr="$CONSUL_ADDR" \
"config/$SERVICE_NAME/gray/user_id_range" "$user_id_range"
echo -e "${GREEN}灰度范围已设置: $user_id_range%${NC}"
}
# 函数:全量发布
full_release() {
echo -e "${YELLOW}执行全量发布...${NC}"
# 将所有灰度实例切回生产
local gray_instances=($(get_service_instances "$TAG_GRAY"))
for instance in "${gray_instances[@]}"; do
switch_tags "$instance" "$TAG_PRODUCTION"
done
# 清除灰度配置
$CONSUL_BIN kv delete \
-http-addr="$CONSUL_ADDR" \
"config/$SERVICE_NAME/gray/user_id_range" 2>/dev/null
echo -e "${GREEN}全量发布完成${NC}"
}
# 函数:回滚
rollback() {
echo -e "${YELLOW}回滚到上一个生产版本...${NC}"
# 将灰度实例切回生产
local gray_instances=($(get_service_instances "$TAG_GRAY"))
for instance in "${gray_instances[@]}"; do
switch_tags "$instance" "$TAG_PRODUCTION"
done
# 清除灰度配置
$CONSUL_BIN kv delete \
-http-addr="$CONSUL_ADDR" \
"config/$SERVICE_NAME/gray/user_id_range" 2>/dev/null
# 重新部署上一版本
echo -e "${GREEN}回滚完成,重新部署上一版本...${NC}"
# 这里可以调用部署脚本重新部署旧版本
}
# 主菜单
show_menu() {
echo "=== 基于Consul的灰度发布管理 ==="
echo "1. 灰度发布 (10% 实例)"
echo "2. 灰度发布 (50% 实例)"
echo "3. 按用户ID灰度 (10%)"
echo "4. 按用户ID灰度 (50%)"
echo "5. 全量发布"
echo "6. 回滚"
echo "7. 查看当前灰度状态"
echo "0. 退出"
}
# 主逻辑
while true; do
show_menu
read -p "请选择操作: " choice
case $choice in
1) gray_deploy_by_percent 10 10 ;;
2) gray_deploy_by_percent 50 10 ;;
3) gray_deploy_by_user_id 10 ;;
4) gray_deploy_by_user_id 50 ;;
5) full_release ;;
6) rollback ;;
7)
echo -e "${YELLOW}当前灰度状态:${NC}"
echo "生产实例:"
get_service_instances "$TAG_PRODUCTION" | while read line; do
echo " - $line"
done
echo "灰度实例:"
get_service_instances "$TAG_GRAY" | while read line; do
echo " - $line"
done
echo "灰度配置:"
$CONSUL_BIN kv get \
-http-addr="$CONSUL_ADDR" \
"config/$SERVICE_NAME/gray/user_id_range" 2>/dev/null || echo " 未设置"
;;
0) exit 0 ;;
*) echo -e "${RED}无效选择${NC}" ;;
esac
echo ""
done
基于Kubernetes的灰度发布
使用Kubernetes的Deployment和Service实现灰度发布。
#!/bin/bash
# 灰度发布脚本 - Kubernetes版本
NAMESPACE="production"
DEPLOYMENT_NAME="myapp"
SERVICE_NAME="myapp-svc"
IMAGE_NEW="myapp:2.0.0"
IMAGE_OLD="myapp:1.0.0"
# 颜色输出
RED='\033[0;31m'
GREEN='\033[0;32m'
YELLOW='\033[1;33m'
NC='\033[0m'
# 函数:创建灰度Deployment
create_gray_deployment() {
local replicas=$1
kubectl create deployment "$DEPLOYMENT_NAME-gray" \
--namespace="$NAMESPACE" \
--image="$IMAGE_NEW" \
--replicas="$replicas" \
--dry-run=client -o yaml > /tmp/gray-deploy.yaml
# 添加标签和选择器
sed -i 's/app: myapp/app: myapp-gray/g' /tmp/gray-deploy.yaml
kubectl apply -f /tmp/gray-deploy.yaml
echo -e "${GREEN}灰度Deployment已创建: $replicas 副本${NC}"
}
# 函数:更新Service选择器
update_service_selector() {
local gray_weight=$1
# 备份原Service
kubectl get svc "$SERVICE_NAME" \
--namespace="$NAMESPACE" \
-o yaml > /tmp/svc-backup.yaml
# 修改Service选择器包含灰度标签
kubectl patch svc "$SERVICE_NAME" \
--namespace="$NAMESPACE" \
-p "{\"spec\":{\"selector\":{\"app\":\"myapp\",\"version\":\"${gray_weight}\"}}}"
echo -e "${GREEN}Service选择器已更新${NC}"
}
# 函数:灰度发布
gray_deploy() {
local percent=$1
echo -e "${YELLOW}开始灰度发布 $percent%...${NC}"
# 计算副本数
local total_replicas=$(kubectl get deployment "$DEPLOYMENT_NAME" \
--namespace="$NAMESPACE" \
-o jsonpath='{.spec.replicas}')
local gray_replicas=$(( total_replicas * percent / 100 ))
# 创建灰度Deployment
create_gray_deployment "$gray_replicas"
# 等待灰度Deployment就绪
kubectl rollout status deployment "$DEPLOYMENT_NAME-gray" \
--namespace="$NAMESPACE" \
--timeout=300s
# 更新Service指向灰度版本
update_service_selector "gray"
echo -e "${GREEN}灰度发布完成: $percent% 流量${NC}"
}
# 函数:全量发布
full_release() {
echo -e "${YELLOW}执行全量发布...${NC}"
# 更新主Deployment
kubectl set image deployment/"$DEPLOYMENT_NAME" \
--namespace="$NAMESPACE" \
"$DEPLOYMENT_NAME=$IMAGE_NEW"
# 等待更新完成
kubectl rollout status deployment/"$DEPLOYMENT_NAME" \
--namespace="$NAMESPACE" \
--timeout=300s
# 删除灰度Deployment
kubectl delete deployment "$DEPLOYMENT_NAME-gray" \
--namespace="$NAMESPACE"
# 恢复Service选择器
kubectl patch svc "$SERVICE_NAME" \
--namespace="$NAMESPACE" \
-p "{\"spec\":{\"selector\":{\"app\":\"myapp\"}}}"
echo -e "${GREEN}全量发布完成${NC}"
}
# 函数:回滚
rollback() {
echo -e "${YELLOW}执行回滚...${NC}"
# 回滚主Deployment
kubectl rollout undo deployment/"$DEPLOYMENT_NAME" \
--namespace="$NAMESPACE"
# 删除灰度Deployment
kubectl delete deployment "$DEPLOYMENT_NAME-gray" \
--namespace="$NAMESPACE" 2>/dev/null
# 恢复Service选择器
kubectl patch svc "$SERVICE_NAME" \
--namespace="$NAMESPACE" \
-p "{\"spec\":{\"selector\":{\"app\":\"myapp\"}}}"
echo -e "${GREEN}回滚完成${NC}"
}
# 主菜单
show_menu() {
echo "=== Kubernetes灰度发布管理 ==="
echo "1. 灰度发布 (10%)"
echo "2. 灰度发布 (50%)"
echo "3. 全量发布"
echo "4. 回滚"
echo "5. 查看当前状态"
echo "0. 退出"
}
# 主逻辑
while true; do
show_menu
read -p "请选择操作: " choice
case $choice in
1) gray_deploy 10 ;;
2) gray_deploy 50 ;;
3) full_release ;;
4) rollback ;;
5)
echo -e "${YELLOW}当前状态:${NC}"
echo "主Deployment:"
kubectl get deployment "$DEPLOYMENT_NAME" \
--namespace="$NAMESPACE" \
-o wide
echo ""
echo "灰度Deployment:"
kubectl get deployment "$DEPLOYMENT_NAME-gray" \
--namespace="$NAMESPACE" 2>/dev/null || echo " 未创建"
echo ""
echo "Service:"
kubectl get svc "$SERVICE_NAME" \
--namespace="$NAMESPACE" \
-o wide
;;
0) exit 0 ;;
*) echo -e "${RED}无效选择${NC}" ;;
esac
echo ""
done
使用注意事项
- 安全性:所有脚本需要在具有适当权限的环境中运行
- 备份:每次操作前备份配置,保证可回滚
- 监控:灰度发布期间密切监控指标
- 自动化:考虑集成到CI/CD流水线中
- 超时处理:设置合理的超时时间,避免长时间等待
这些脚本提供了基础的灰度发布功能,可以根据实际场景进行调整和扩展。
版权声明:NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
足球直播
足球直播
足球直播
篮球直播
篮球直播
篮球直播
NBA直播
NBA直播
NBA直播
CBA直播
CBA直播
CBA直播
亚冠直播
亚冠直播
亚冠直播
欧冠直播
欧冠直播
欧冠直播
英超直播
英超直播
英超直播
西甲直播
西甲直播
西甲直播
中超直播
中超直播
中超直播
足球直播
足球直播
足球直播
篮球直播
篮球直播
篮球直播
NBA直播
NBA直播
NBA直播
CBA直播
CBA直播
CBA直播
亚冠直播
亚冠直播
亚冠直播
欧冠直播
欧冠直播
欧冠直播
英超直播
英超直播
英超直播
西甲直播
西甲直播
西甲直播
中超直播
中超直播
中超直播
足球直播
足球直播
足球直播
篮球直播
篮球直播
篮球直播
NBA直播
NBA直播
NBA直播
CBA直播
CBA直播
CBA直播
亚冠直播
亚冠直播
亚冠直播
欧冠直播
欧冠直播
欧冠直播
英超直播
英超直播
英超直播
西甲直播
西甲直播
西甲直播
中超直播
中超直播
中超直播
足球直播
足球直播
足球直播
篮球直播
篮球直播
篮球直播
NBA直播
NBA直播
NBA直播
CBA直播
CBA直播
CBA直播
亚冠直播
亚冠直播
亚冠直播
欧冠直播
欧冠直播
欧冠直播
英超直播
英超直播
英超直播
西甲直播
西甲直播
西甲直播
中超直播
中超直播
中超直播
曼联直播
曼联直播
曼联直播
日职联直播
日职联直播
日职联直播
澳超直播
澳超直播
澳超直播
阿森纳直播
阿森纳直播
阿森纳直播
足球直播
足球直播
足球直播
NBA直播
NBA直播
NBA直播
曼联直播
曼联直播
曼联直播
日职联直播
日职联直播
日职联直播
澳超直播
澳超直播
澳超直播
阿森纳直播
阿森纳直播
阿森纳直播
足球直播
足球直播
足球直播
NBA直播
NBA直播
NBA直播
曼联直播
曼联直播
曼联直播
日职联直播
日职联直播
日职联直播
澳超直播
澳超直播
澳超直播
阿森纳直播
阿森纳直播
阿森纳直播
足球直播
足球直播
足球直播
NBA直播
NBA直播
NBA直播
曼联直播
曼联直播
曼联直播
日职联直播
日职联直播
日职联直播
澳超直播
澳超直播
澳超直播
阿森纳直播
阿森纳直播
阿森纳直播
足球直播
足球直播
足球直播
NBA直播
NBA直播
NBA直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
足球直播
足球直播
足球直播
足球直播
足球直播
英超直播
英超直播
英超直播
英超直播
英超直播
篮球直播
篮球直播
篮球直播
篮球直播
篮球直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
中超直播
中超直播
中超直播
中超直播
中超直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
足球直播
足球直播
足球直播
足球直播
足球直播
英超直播
英超直播
英超直播
英超直播
英超直播
篮球直播
篮球直播
篮球直播
篮球直播
篮球直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
中超直播
中超直播
中超直播
中超直播
中超直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播