V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
NGINX
NGINX Trac
3rd Party Modules
Security Advisories
CHANGES
OpenResty
ngx_lua
Tengine
在线学习资源
NGINX 开发从入门到精通
NGINX Modules
ngx_echo
dzdh
V2EX  ›  NGINX

nginx 的 proxy_pass 后端一个 upstream 多个动态 IP 怎么破?

  •  
  •   dzdh · 2022-09-08 00:14:18 +08:00 · 3111 次点击
    这是一个创建于 831 天前的主题,其中的信息可能已经有所发展或是发生改变。

    环境是 k8s ,需要多个域名对应不同的容器或 svc ,同时因为历史原因,不可能去修改业务代码兼容集群环境如通过 configmap 配置。

    所以现在的能想到的配置类似如下:

    map $host $svc {
        a.com "vip-svc";
        b.com "normal-svc";
        c.com "mormal-svc";
        ..省略 1w 多
    }
    server {
       location / {
           proxy_pass http://$svc;
       }
    }
    

    这个 svc 就是不同的 service 。通过 http://svc-name 的形式可以访问到。但是有个问题是,nginx 会在一次请求后固定这个 host 的 ip 在内存中。导致如果对应 svc 的 pod 发生轮换或扩缩容则 ip 会变,然后再来新请求就 504 了。

    通过 ingress 由于 ingress 也是一个独立 pod 解决不了换 ip 的问题。

    upstream 的 resolve 需要 nginx plus 才有。三方插件如 dynamic-upstream 运行一段时间后 cpu 奇高。

    有什么更简单的解决方案吗。

    ps: 容器中的 nginx 配置文件通过监听 redis ( confd )实时变更。

    第 1 条附言  ·  2022-09-08 10:49:35 +08:00
    好的。是自己 sb 了。nginx 后的 svc 服务虽然是 clusterip 。但是开启了 headless 模式。关掉后就好了。这个 svc 的名称本身就有一个固定的 ip (非 pod 段)。现在好了。依靠 ipvs 做轮询转发。
    12 条回复    2022-09-08 10:34:43 +08:00
    fkdog
        1
    fkdog  
       2022-09-08 01:31:35 +08:00
    upstream 我记得是有参数配置域名解析 resolver 的缓存时常的,你可以把这个时间调短一点。
    对于访问到失效 ip 的问题,我觉得你可以配合 nginx 的故障迁移来解决。
    将失效 ip 产生 502 503 504 的 http 请求迁移到其他节点下。

    如果你的池子里节点总是有一台能正常访问的话,那么基本都没什么大问题的。
    mytsing520
        2
    mytsing520  
       2022-09-08 07:21:53 +08:00
    我们正在研究使用 resolver 参数,同时将 valid 时间调整到 30-60 秒。
    简而言之,故障肯定会有,核心是多久消灭
    gongshuiwen
        3
    gongshuiwen  
       2022-09-08 08:53:08 +08:00
    对 K8s 并不是很熟悉,但是记得 K8s 中定义的 Service 按理说 ClusterIP 会固定不变的才对,其本身就是解决 Pod 轮换或扩容缩容造成的 IP 改变问题的。可以照楼上的方法缩短 DNS 缓存的有效时长,但是会产生比较高的 DNS 负载的。

    以下内容来自 K8s 文档:

    虚拟 IP 和 Service 代理
    在 Kubernetes 集群中,每个 Node 运行一个 kube-proxy 进程。kube-proxy 负责为 Service 实现了一种 VIP (虚拟 IP )的形式,而不是 ExternalName 的形式。

    为什么不使用 DNS 轮询?
    时不时会有人问到为什么 Kubernetes 依赖代理将入站流量转发到后端。那其他方法呢? 例如,是否可以配置具有多个 A 值(或 IPv6 为 AAAA )的 DNS 记录,并依靠轮询名称解析?

    使用服务代理有以下几个原因:

    - DNS 实现的历史由来已久,它不遵守记录 TTL ,并且在名称查找结果到期后对其进行缓存。
    - 有些应用程序仅执行一次 DNS 查找,并无限期地缓存结果。
    - 即使应用和库进行了适当的重新解析,DNS 记录上的 TTL 值低或为零也可能会给 DNS 带来高负载,从而使管理变得困难。
    Bromine0x23
        4
    Bromine0x23  
       2022-09-08 09:12:43 +08:00
    没看懂不能使用 ingress 的原因,我觉得问题能通过 ingress 解决
    julyclyde
        5
    julyclyde  
       2022-09-08 09:37:41 +08:00
    为什么会 cpu 高呢?
    julyclyde
        6
    julyclyde  
       2022-09-08 09:37:52 +08:00
    @Bromine0x23 因为这就是“ingress 本身”
    dzdh
        7
    dzdh  
    OP
       2022-09-08 09:43:33 +08:00
    @julyclyde #5 nginx 三方插件的问题用了几个,都是五六年没更新过的。
    dzdh
        8
    dzdh  
    OP
       2022-09-08 09:43:56 +08:00
    @gongshuiwen #3
    还真没注意,阿里云的托管 k8s ackpro 。我去看看。
    julyclyde
        9
    julyclyde  
       2022-09-08 09:58:28 +08:00
    @dzdh 按说这东西也没啥可更新的
    试试那个 upstream by lua 吧
    auser
        10
    auser  
       2022-09-08 10:03:58 +08:00
    生产环境上有类似场景

    我目前的做法是:
    1 ) crontab 定期 nginx reload ,应对域名对应 IP 变更的情况(不在我们控制范围)
    2 )我们后台配置变更时候,通过 ssh 远程执行脚本的方式,让所有 nginx 节点执行 nginx reload
    killva4624
        11
    killva4624  
       2022-09-08 10:08:08 +08:00
    前段时间正好研究过 k8s 里跑 nginx 做转发。
    不会更新 ip cache 这个实际上是 nginx 的问题,如果 proxy_pass 里有变量,那么必须加 resolver ,不然 upstream 的 IP 不会更新。
    https://stackoverflow.com/questions/17685674/nginx-proxy-pass-with-remote-addr

    不过还是没明白为什么不用 ingress ...
    cheitu
        12
    cheitu  
       2022-09-08 10:34:43 +08:00
    @auser 同生产环境一样的处理。为了省成本用 aws 的竞价,导致集群后端服务器经常会变 IP 。写了一个程序,部署在跑 nginx 的服务器上面,定时通过 aws api 获取最新服务器 ip ,如果变化,更新一下 upstream 配置文件然后 reload nginx 。upstram 配置是单独一个配置文件,方便更新。
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   实用小工具   ·   860 人在线   最高记录 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 26ms · UTC 21:42 · PVG 05:42 · LAX 13:42 · JFK 16:42
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.