Nginx 动态DNS解析方案: resolver
Nginx 动态DNS解析方案: resolver
运维就要无所不能,无所不会
大家好,我是Stanley「史丹利」,你们已经回家我,而我还在学习「其实是因为撞车了,请假计划被打乱了...」。今天聊
nginx 动态dns 解析
。【似乎发现 Nginx 的一个 BUG】
问题排查过程比较长,不感兴趣的朋友可直接跳到文末看结论和 Nginx resolver 的注意点
文章目录如下:
- 一、背景
-
二、动态解析方案
- 方案一:每次dns有变化,重启Nginx
- 方案二:使用Nginx Resolver
- 方案三:使用 Nginx-upstream-dynamic-server
- 方案四:使用 ngx_upstream_jdomain
-
三、Nginx Resolver 方案测试【BUG】
- 3.1 排除粗心手误问题
- 3.2 排除测试方案问题
- 3.3 排除DNS配置问题
- 3.4 排除域名重复配置问题
- 四、排查过程总结及Nginx Resolver注意点
一、背景
PHP架构核心技术栈是LNMP,业务接口互调的主流方式:
- 方式一:程序内部路由
- 方式二:标准RESETful接口
- 方式三:通过 Nginx proxy 透传
最理想的方案是:方式一,但不同业务之间的接口,跨项目调用并不适用。
所以推荐方案是方式二。但对开发精力投入和codeing有挑战,在公司内部推行难度奇大,尤其初创期的公司基本不可能。光就这点而言,
SpringCloud
的统一网关架构
ZUUL
或
Gateway
确实要比
PHP
高明。
个人认为:随着IT互联网不断成熟,小步快跑不断被挑战的,慢就是快理念不断举起的意识下。轻量级PHP语言是否真的快,确实要不断被挑战。前有前端技术语言的快速迭代,纯静态页面逐步成为主流。后面golang新兴高并发语言,Java工程级别架构语言。PHP的定位确实很尴尬,这可能也是PHP市场不断萎缩的原因。吧
剩下的方式三,是我们现在应用比较多的场景。主要以 upstream 和 proxy_pass 为主。
- upstream方式
upstream upstream_1 {
ip_hash;
server 10.1.1.1:80 max_fails=3 fail_timeout=31s;
server 10.1.1.2:80 max_fails=3 fail_timeout=31s;
keepalive 10;
location /abc/ {
proxy_pass upstream_1;
如上为目录主流upstream方式
- Proxy url
location /out_ip/ {
out_ip.example.com;
该方式是
nginx proxy
和
ResetFul
结合的“变种”。通常情况下,
out_ip.example.com
是作为
ResetFul
的标准接口调用,但少数情况是
out_ip.example.com
同样是
Proxy
角色,后端会有转发或
upstream
到多台
Real Server
.
Proxy
最大的问题是:后端Real Server变更时, Nginx 不会主动更新DNS缓存,很不幸,我们还因此引发了一场小事故(对方变更,未通知我们重启nginx)
。
官网原文如下:
As NGINX starts up or reloads its configuration, it queries a DNS server to resolve backends.example.com . The DNS server returns the list of three backends discussed above, and NGINX uses the default Round Robin algorithm to load balance requests among them. NGINX chooses the DNS server from the OS configuration file /etc/resolv.conf . This method is the least flexible way to do service discovery and has the following additional drawbacks:
- If the domain name can’t be resolved, NGINX fails to start or reload its configuration.
- NGINX caches the DNS records until the next restart or configuration reload, ignoring the records’ TTL values.
-
We can’t specify another load‑balancing algorithm, nor can we configure passive health checks or other features defined by parameters to the
server
directive, which we’ll describe in the next section. - Nginx 在启动/重载的时候回去解析转发的域名
- 如果域名无法解析 Nginx 就无法启动
- 只有下次重启/重载的时候才会重新去解析,启动后无视TTL
https://www.nginx.com/blog/dns-service-discovery-nginx-plus/
二、动态解析方案
方案一:每次dns有变化,重启Nginx
坑1:会有遗漏通知的情况(我们就遇到了)
坑2:机器太多,麻烦
坑3:耦合性太高,如变更频繁,无法接入,且可能会影响现有应用
方案二:使用Nginx Resolver
声明 resolver 即可,Nginx core模块内置 ,无需新增编译模块。操作简单
// 但我们遇到了惊天“bug”...折腾了1.5天,也没找到原因..
方案三:使用 Nginx-upstream-dynamic-server
方案四:使用 ngx_upstream_jdomain
三、Nginx Resolver 方案测试【BUG】
Nginx Resolver
不需要额外编译Nginx,且配置简单。所以我们第一想法是采用该方案。
- 原配置
location /prod-url-test/ {
proxy_pass http://$proxy_url;
- 添加resolver后的配置
location /prod-url-test/ {
resolver 4.4.4.4 valid=10s;
set $proxy_url "prod-url-test.t1.test.example.com";
proxy_pass http://$proxy_url;
但实际测试结果如下:
- Dns 变更,nginx 并不能正常解析
- 重启 nginx 后,生效。
下面就开始了抓妖怪的曲折道路,因为过程较为曲折,我大致总结为如下几个阶段:
- 排除粗心手误问题
- 排除测试方案问题
- 排除DNS配置问题
- 排除域名重复配置问题
3.1 排除粗心手误问题
- 使用对比工具检查可能的拼写错误
- 检查 hosts ,确认域名没有绑定hosts
- 确认 Linux, Windows DNS 缓存机制并验证
3.2 排除测试方案问题
- 确认方案准确可行,无歧义
- 基于Y同学的方案,我全新重头又验证一遍。确认过程无疏忽错误
3.3 排除DNS配置问题
- 优化 DNS 默认 TTL 1D,修改为 10S
- 确认主从 DNS 同步机制,及 dig , nslookup确认解析生效
3.4 排除域名重复配置问题
确认没有模糊匹配的域名干扰
grep -iE '域名' /etc/nginx/ -R
一顿操作猛如虎,一看收入250。竟然没定位到问题,有点尴尬..
随后,我增加了如下测试方案:
- 方案一 : 新增域名
lst-dns-test.t1.test.example.com
为最大化模拟问题,域名的长短也保持一致。
为排除现有 DNS 潜在的问题,及技术人员响应不及时的情况。同时我自己又搭建了一套 DNS.
- 方案二:新增自建 DNS 服务
最终配置如下
location /lst-dns-test/ {
resolver 6.6.6.6 valid=10s; # 6.6.6.6 为自建DNS
set $proxy_url "lst-dns-test.t1.test.example.com";
proxy_pass http://$proxy_url;