docker-compose+nginx实现服务不中断更新

思路是写一个脚本,docker-compose scale扩容,然后重写nginx配置文件,刷新负载均衡

nginx重写的配置文件,文件名service,里面只有upstream,例如:

upstream e-chatbot-server-dev {
 server 0.0.0.0:8080;
 server 0.0.0.0:8081;
}

脚本使用方法:

./rollupdate.sh --service=test-server --port=8080
需要注意的是docker-compose.yaml的服务test-server端口范围要比实例数多一个,yaml示例如下:
version: '3'
services:
  test-server:
    image: test-server:1.0
    restart: always
    networks:
      - dev
    ports:
      - "8080-8082:8080"
    healthcheck:
      test: ["CMD", "curl", "-f", "http://localhost:8080/actuator/health"]
      interval: 30s
      timeout: 10s
      retries: 3
      start_period: 60s
    deploy:
      resources:
        limits:
          cpus: 2
          memory: 1g
      replicas: 2
      update_config:
        parallelism: 1
        delay: 10s
      restart_policy:
        condition: on-failure
networks:
  dev:
    external: true
    driver: bridge

rollupdate.sh脚本如下:
service=
port=
# 循环处理所有命令行参数
for arg in "$@"
do
    case $arg in
        --service=*) # 如果参数以--service=开头
            service="${arg#*=}" # 截取等号后的部分作为服务名称
            ;;
        --port=*) # 如果参数以--port=开头
            port="${arg#*=}" # 截取等号后的部分作为端口号
            ;;
        *) # 如果参数不是以--service=或--port=开头,则跳过
            ;;
    esac
done

if [ -z "$service" ]; then
  echo "--service=?"
fi
if [ -z "$port" ]; then
  echo "--port=?"
fi
if [ -z "$service" ] || [ -z "$port" ]; then
  exit 1
fi

old_names=$(docker-compose ps $service --format "{{.Names}}")
if [ -z "$old_names" ]; then
   docker-compose up -d $service
   exit $?
fi
echo -e "服务$service,老的实例:\n $old_names"
docker-compose port $service $port > /etc/null
if [ "$?" != "0" ]; then
  exit 1
fi
replicas=$(docker-compose config $service --format="json" | jq ".services.\"$service\".deploy.replicas // 1")
if [ -z "$replicas" ]; then
  echo "未获取到副本数量"
  exit 1
fi
echo "old replicas: $replicas"
let replicas=replicas+1
echo "update replicas: $replicas"
for container_name in $old_names; do
    # 在这里可以添加其他针对每个容器名称的操作
    echo "服务:$service设置副本为$replicas,正在添加一个副本"
    docker-compose scale "$service=$replicas"
    if [ "$?" != "0" ]; then
       exit
    fi
    echo -n "等待新增副本就绪..."
    for i in {1..100}; do
      #服务需要监控检查
      start_count=$(docker-compose ps $service | grep "health: starting" | wc -l)
      if [ $start_count -eq 0 ]; then
        break
      fi
      echo -n "."
      sleep 5
    done
    echo ""
    if [ $start_count -gt 0 ]; then
        echo "超过最大等待时间"
        exit 1
    fi
    new_names=$(docker-compose ps $service --format "{{.Names}}")
    nx_conf="upstream $service {\n"
    for new_name in $new_names; do
      if [ "$new_name" != "$container_name" ]; then
        hport=$(docker port $new_name $port | head -n 1)
        nx_conf+="  server $hport;\n"
      fi
    done
    nx_conf+="}"
    echo "从nginx负载均衡移除实例$container_name"
    echo -e $nx_conf > /etc/nginx/conf.d/$service.conf
    nginx -s reload
    echo "docker stop $container_name"
    docker stop $container_name && docker rm $container_name
done

  

posted @ 2024-05-06 20:11  风的低吟  阅读(173)  评论(0编辑  收藏  举报