Consul与Nginx集成SRV记录实现Nomad动态服务发现故障排查
问题本质
开源Nginx默认的resolve指令仅支持解析A/AAAA记录,完全不处理SRV记录里的端口信息——这就是你配置后仍跳转到欢迎页的核心原因:Nginx只拿到了服务IP,没获取到动态分配的端口。
最优解决方案推荐
方案1:nginx-upsync-module(首选)
这个模块成熟度高、维护活跃,能直接从Consul同步服务实例的IP和动态端口,还自带健康检查功能,完美匹配你的动态端口场景。
配置步骤
- 编译Nginx时集成模块(需提前下载源码):
./configure --add-module=/path/to/nginx-upsync-module --add-module=/path/to/nginx-upsync-module/src/ngx_http_upstream_check_module make && make install
- Nginx核心配置示例:
http { upstream zapper { # 从Consul Catalog API拉取服务实例,自动更新上游池 upsync http://127.0.0.1:8500/v1/catalog/service/zapper upsync_timeout=6m upsync_interval=500ms upsync_type=consul strong_dependency=off; # 模块要求必须有一个占位服务器(不会实际使用) server 127.0.0.1:11111; # 开启实例健康检查,自动剔除异常节点 check interval=3000 rise=2 fall=3 timeout=1000 type=http; check_http_send "HEAD / HTTP/1.0\r\n\r\n"; check_http_expect_alive http_2xx http_3xx; } server { listen 80; server_name your-domain.com; location / { proxy_pass http://zapper; proxy_set_header Host $host; proxy_set_header X-Real-IP $remote_addr; } } }
方案2:ngx_http_consul_backend_module(备选)
这个模块功能更单一,仅负责从Consul拉取后端信息,但成熟度和维护频率不如upsync。如果已经集成了该模块,配置示例如下:
http { upstream zapper { consul_backend 127.0.0.1:8500 service=zapper interval=5s; server 127.0.0.1:11111; } server { listen 80; server_name your-domain.com; location / { proxy_pass http://zapper; } } }
注意:该模块无内置健康检查,需依赖Consul的服务健康状态过滤,或额外配置Nginx健康检查规则。
方案3:Consul Template(无需编译Nginx)
如果不想折腾Nginx编译,可通过Consul Template动态生成Nginx配置并自动重载,适合快速落地场景。
配置步骤
- 安装Consul Template后,编写模板文件
nginx_zapper.ctmpl:
upstream zapper { {{ range service "zapper" }} server {{ .Address }}:{{ .Port }}; {{ end }} } server { listen 80; server_name your-domain.com; location / { proxy_pass http://zapper; proxy_set_header Host $host; } }
- 启动Consul Template监听服务变化:
consul-template -template "nginx_zapper.ctmpl:/etc/nginx/conf.d/zapper.conf:nginx -s reload"
缺点:Nginx重载时会有短暂连接中断,高并发场景需评估影响。
关键注意事项
- 确认Nomad服务注册配置正确:必须在Job的
service块中绑定动态端口,确保Consul能获取到端口信息,示例HCL:
job "zapper" { datacenters = ["dc1"] type = "service" group "zapper" { count = 2 task "zapper" { driver = "docker" config { image = "your-zapper-image:latest" ports = ["http"] } service { name = "zapper" port = "http" check { type = "http" path = "/" interval = "10s" timeout = "2s" } } } } }
- 若Consul启用了ACL,需确保Nginx或Consul Template拥有读取服务Catalog的权限。
内容的提问来源于stack exchange,提问作者lovestaco
相关产品推荐
相关产品推荐

