使用NGINX代理实现Docker负载均衡

7
我正在尝试使用nginx和docker的本地DNS来负载均衡API服务器。
我希望nginx可以轮询所有可用服务器的API调用。但即使我将docker的DNS服务器指定为resolver,nginx也只会将请求转发到一个服务器。
以下是docker-compose.yml中相关部分:
proxy:
  restart: always
  build: ./src/nginx/.
  ports:
    - "8080:8080"
  links:
    - api:servers.api

nginx.conf

worker_processes 2;

events { worker_connections 1024; }

http {
    sendfile on;

    server {
        listen 8080;

        location / {
            resolver_timeout 30s;
            resolver 127.0.0.11 ipv6=off valid=10s;
            set $backend http://servers.api:80;
            proxy_pass          $backend;
            proxy_redirect      off;
        }
    }
}

如果我手动指定每个服务器,NGINX轮询负载均衡器可以工作,但我不想这样做,因为它不能自动扩展。

worker_processes 2;

events { worker_connections 1024; }

http{
    sendfile on;

    upstream api_servers{
        server project_api_1:80;
        server project_api_2:80;
        server project_api_3:80;
    }

    server{
        listen 8080;

        location / {
            proxy_pass          http://api_servers;
            proxy_redirect      off;
        }
    }
}

如何配置nginx以便它能够检测到新添加的容器并将它们包含在轮询中?
2个回答

3

Docker的DNS负责在这种情况下执行轮询。不要在您的组合中使用links选项,这是不必要的。看,我正在使用这个例子:

docker-compose.yml:

version: '3'
  services:
    api:
      image: my-api-image
    client:
      image: ubuntu:latest

我使用docker-compose up -d api启动我的应用程序,然后进行扩展:docker-compose scale api=10。现在,在客户端内(docker-compose run client bash):

root@ce3857690292:/# dig api
...
;; QUESTION SECTION:
;api.               IN  A

;; ANSWER SECTION:
api.            600 IN  A   172.19.0.6
api.            600 IN  A   172.19.0.9
api.            600 IN  A   172.19.0.7
api.            600 IN  A   172.19.0.8
api.            600 IN  A   172.19.0.11
api.            600 IN  A   172.19.0.2
api.            600 IN  A   172.19.0.10
api.            600 IN  A   172.19.0.3
api.            600 IN  A   172.19.0.5
api.            600 IN  A   172.19.0.4

使用curl命令可以查看轮询效果:

root@1719c10f864a:/# curl -vI api
* Rebuilt URL to: api/
*   Trying 172.19.0.6...
* Connected to api (172.19.0.6) port 80 (#0)
...
root@1719c10f864a:/# curl -vI api
* Rebuilt URL to: api/
*   Trying 172.19.0.7...
* Connected to api (172.19.0.7) port 80 (#0)
...
root@1719c10f864a:/# curl -vI api
* Rebuilt URL to: api/
*   Trying 172.19.0.8...
* Connected to api (172.19.0.8) port 80 (#0)

在你的情况下,你需要在我的docker-compose中将客户端服务替换为你的nginx,并将你的api作为上游使用(不使用links)。

那么,在这种情况下,我不必使用nginx来扩展(除非我需要least_conn或ip_hash负载均衡)吗?Docker是否能够进行基本的轮询负载均衡? - Raj
1
这个“负载均衡”仅适用于您的Docker网络中的其他应用程序。我建议使用nginx、ha代理或(最可能的)traefik:https://traefik.io/ - Jonathan Beber

2

我应该在nginx中使用SERVICE名称作为服务器名称,而不是ALIAS名称。

在nginx容器上运行nslookup显示:

/ # nslookup api
nslookup: can't resolve '(null)': Name does not resolve

Name:      api
Address 1: 172.20.0.7 project_api_1.project_default
Address 2: 172.20.0.5 project_api_3.project_default
Address 3: 172.20.0.6 project_api_2.project_default

/ # nslookup servers.api
nslookup: can't resolve '(null)': Name does not resolve

Name:      servers.api
Address 1: 172.20.0.7 project_api_1.project_default

编写 nginx.conf

worker_processes 2;

events { worker_connections 1024; }

http {
    sendfile on;

    server {
        listen 8080;

        location / {
            resolver_timeout 30s;
            resolver 127.0.0.11 ipv6=off valid=10s;
            set $backend http://api:80;
            proxy_pass          $backend;
            proxy_redirect      off;
        }
    }
}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接