Use nginx upstream group with multiple ports
I would like to use the same upstream definition with multiple ports:
upstream production {
server 10.240.0.26;
server 10.240.0.27;
}
server {
listen 80;
server_name some.host;
location / {
proxy_pass http://production:1234;
}
}
server {
listen 80;
server_name other.host;
location / {
proxy_pass http://production:4321;
}
}
Using that configuration nginx -t
throws: upstream "production" may not have port 1234
and returns with exitcode 1.
When I try to define the proxy_pass
URL (or parts of) as a variable like:
set $upstream_url "http://production:1234"
set $upstream_host production;
set $upstream_port 1234;
proxy_pass $upstream_url;
# or
proxy_pass http://production:$upstream_port;
# or
proxy_pass http://$upstream:$upstream_port;
Nginx tries to resolve the name of my upstream via resolver:
*16 no resolver defined to resolve production, client: ...., server: some.host, request: "GET / HTTP/1.1", host: "some.host"
For me, the proxy_pass doc sounds as if exactly that should not happen;
A server name, its port and the passed URI can also be specified using variables:
proxy_pass http://$host$uri; or even like this:
proxy_pass $request; In this case, the server name is searched among the described server groups, and, if not found, is determined using a resolver.
Tested with nginx versions:
- 1.6
- 1.9
- 1.10
- 1.11
Am I missing something? Is there a way to work around this?
Solution 1:
You must define port in every server
entry in upstream
. If you don't nginx will set it to 80
. So server 10.240.0.26;
actually means server 10.240.0.26:80;
.
You could define several upstream blocks though:
upstream production_1234 {
server 10.240.0.26:1234;
server 10.240.0.27:1234;
}
upstream production_4321 {
server 10.240.0.26:4321;
server 10.240.0.27:4321;
}
server {
listen 80;
server_name some.host;
location / {
proxy_pass http://production_1234;
}
}
server {
listen 80;
server_name other.host;
location / {
proxy_pass http://production_4321;
}
}
Another option is to configure your local DNS to resolve hostname production
to several IPs, and in this case nginx will use them all.
http://nginx.org/r/proxy_pass: If a domain name resolves to several addresses, all of them will be used in a round-robin fashion.
server {
listen 80;
server_name some.host;
location / {
proxy_pass http://production:1234;
}
}
Solution 2:
When you use upstreams, the ports are defined in the upstream blocks:
upstream production {
server 10.240.0.26:8080;
server 10.240.0.27:8081;
}
In other words, nginx resolves proxy_pass
argument either to a upstream group or a host:port
pair. When you use a variable as argument, it only resolves to host:port
pair.