Nginx 缓存服务器(番外)动态 upstream
2019-07-09 by dongnan
问题描述
在更新应用镜像(图中的App1)版本后,部分静态资源抛出 502
状态码。
先来看下 nginx缓存服务器日志,重点在"Host is unreachable"这里,顺着这个错误信息找到了错误源头,也有了这篇文章。
2019/06/18 09:46:15 [error] 11#11: *2926 connect() failed (113: Host is unreachable) while connecting to upstream,
client: 10.42.0.101, server: localhost, request: "GET /css/pc/layout.css?v= HTTP/1.1",
upstream: "http://10.42.200.140:8080/css/pc/layout.css?v=", host: "zongming.net", referrer: "https://zongming.net/"
项目环境
为了讲清楚问题原因,这里需要说明下项目运行环境,这个WEB项目运行在 Rancher
容器平台上,项目架构如图(参考 nginx 缓存服务器(上))。
项目基于Docker容器技术,通过jenkins
持续集成工具将代码(war包)附加到Tomcat
Docker镜像上,最后项目更新上线是通过升级镜像版本完成的。
排错过程
接下来开始排查问题,通过检查nginx配置文件,发现配置文件使用的是主机名demo-web
(rancher内部域名)。
配置文件
cat /etc/nginx/conf.d/default.conf
server {
listen 80;
server_name localhost;
location / {
proxy_pass http://demo-web:8080;
proxy_set_header Host $host:$server_port;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
# cache
proxy_cache proxyCache;
proxy_cache_valid 1d;
proxy_cache_key $uri$is_args$args;
#
expires 1d;
}
}
通过检查日志发现,日志中的 upstream服务器IP 10.42.200.140 与现有的 upstream服务器IP并不相同, 说明 upstream服务器运行期间IP地址发生了改变,这也是日志中"Host is unreachable"问题所在。
nslookup demo-web
Server: 169.254.169.250
Address: 169.254.169.250#53
Name: demo-web.irm.rancher.internal
Address: 10.42.216.46
Nginx DNS缓存机制
默认情况下Nginx的Resolver没有配置,Nginx将使用首次DNS查询获得的IP地址,之后将不会再查询DNS直到下一次重新加载配置(比如nginx -t)。
所以如果一条DNS记录解析在DNS缓存周期内变更,那么由于Nginx DNS缓存机制的存在,Nginx仍会使用旧的IP地址。
也就是说配置文件中所使用的demo-web
主机名在其运行期间IP地址发生了改变,最终导致了502
错误。
解决方法
知道了病因那么给出的药方就是为 nginx配置动态 upstream
,主动对主机名进行DNS解析,配置文件添加 resolver指令,如下:
cat /etc/nginx/conf.d/default.conf
server {
listen 80;
server_name localhost;
# dns
resolver 169.254.169.250 valid=8s ipv6=off;
set $upstream_server http://demo-web:8080;
location / {
proxy_pass $upstream_server;
proxy_set_header Host $host:$server_port;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
# cache
proxy_cache proxyCache;
proxy_cache_valid 200 206 304 302 7d;
proxy_cache_key $uri$is_args$args;
#
expires 7d;
}
}
- resolver 表示指定的DNS 169.254.169.250,注意这是
rancher
环境内部DNS地址。 - valid=8s 表示覆盖默认TTL(DNS缓存时间),指定TTL为8秒。
- ipv6=off 表示关闭 IPV6 解析。
- set 设置变量,并在proxy_pass指令中使用这个变量。
结束
至此 "nginx 动态 upstream" 这篇文章就完成了,本期就到这里,下期再见。