Docker 和 nginx 上游零停机

Docker 和 nginx 上游零停机

我在尝试使用 nginx 的上游指令自动部署 docker 容器时遇到了一些奇怪的问题。出于某种原因,当我手动执行以下操作时,它可以工作,但当我尝试自动化时,我没有得到一致的结果。

基本上,我会拉取最新的图像停止,删除 2 个正在运行的容器中的 1 个,然后启动容器,然后更新 nginx 上游配置文件,重新加载 nginx 配置。对第二个容器重复上述操作。

看起来很简单,但出于某种原因,我无法始终在 bash 脚本中使用它。我正在使用 seige 对应用程序进行负载测试。

siege -d1 -t75S -c25 http://192.168.49.4:8087

我的脚本用于自动化部署,在运行脚本之前会提取最新的图像。

#! /bin/bash

appname=appnamexyz;
appport=8000;
host_ip=192.168.49.4;
registry=192.168.254.96;

echo "upstream api_servers {${nl}
  server $(docker port ${appname}-1 ${appport}) max_fails=2 fail_timeout=1s;${nl}
  server $(docker port ${appname}-2 ${appport}) max_fails=2 fail_timeout=1s;${nl}
}" > /etc/nginx/conf.d/api_upstream.conf

sed -i "s/server $(docker port $appname-1 $appport)/server xxx/g" /etc/nginx/conf.d/api_upstream.conf

docker stop $appname-1
docker rm -f $appname-1
docker run -d --name $appname-1 -p $host_ip::$appport $registry:5000/$appname -APIKey=e5e1c4b8e46d563c3 

sed -i "s/server xxx/server $(docker port $appname-1 $appport)/g" /etc/nginx/conf.d/api_upstream.conf
nginx -s reload



sleep 15s

sed -i "s/server $(docker port $appname-2 $appport)/server xxx/g" /etc/nginx/conf.d/api_upstream.conf

docker stop $appname-2
docker rm -f $appname-2
docker run -d --name $appname-2 -p $host_ip::$appport $registry:5000/$appname -APIKey=e5e1c4b8e46d563c350b7

sed -i "s/server xxx/server $(docker port $appname-2 $appport)/g" /etc/nginx/conf.d/api_upstream.conf
nginx -s reload
cat /etc/nginx/conf.d/api_upstream.conf

应用程序将返回 200 秒,然后在重新启动第二个容器时,我将收到 500,502 错误。这是我的应用程序的配置文件。

server {
  listen 8087;
  server_name 192.168.49.4;

  location / {
    proxy_pass http://api_servers;
    proxy_next_upstream     error timeout invalid_header http_500 http_502 http_504;
    proxy_connect_timeout   1;
  }
}

我应该怎样补救?

答案1

502 对应于后端超时,而 500 是服务器错误,表示配置错误。您可能希望首先修复以下问题:

在睡眠之前,你实际上api_upstream.conf

sed -i "s/server xxx/server $(docker port $appname-1 $appport)/g" /etc/nginx/conf.d/api_upstream.conf

(你甚至做了两次...目的?双重复制粘贴?)

但你当时还没有做的是替换第二行,它仍然是

server $(docker port ${appname}-2 ${appport}) max_fails=2 fail_timeout=1s;${nl}

我认为$appname$appport是空的,导致子 shell 失败/为空,这意味着这一行实际上被解释为

server max_fails=2 fail_timeout=1s;

当使用默认循环对请求进行负载平衡时,nginx 可能会遇到一个问题......

您应该确保api_upstream.conf在使用时始终包含有效数据。您可以server稍后在其中添加 s,但让部分写入的占位符不会产生任何好处。

答案2

我自己也遇到过同样的问题:容器的启动时间在图像的部署中并不相同......因此,从一个容器重新启动容器并不总是那么快......可能只是你必须在旋转另一个容器之前设置某种一致性检查...你甚至可能希望从 shell 脚本中点击容器进行健康检查,而不是等待任意的 15 秒......?

相关内容