环境是 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 fkdog 2022-09-08 01:31:35 +08:00 upstream 我记得是有参数配置域名解析 resolver 的缓存时常的,你可以把这个时间调短一点。 对于访问到失效 ip 的问题,我觉得你可以配合 nginx 的故障迁移来解决。 将失效 ip 产生 502 503 504 的 http 请求迁移到其他节点下。 如果你的池子里节点总是有一台能正常访问的话,那么基本都没什么大问题的。 |
![]() | 2 mytsing520 PRO 我们正在研究使用 resolver 参数,同时将 valid 时间调整到 30-60 秒。 简而言之,故障肯定会有,核心是多久消灭 |
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 带来高负载,从而使管理变得困难。 |
![]() | 4 Bromine0x23 2022-09-08 09:12:43 +08:00 没看懂不能使用 ingress 的原因,我觉得问题能通过 ingress 解决 |
5 julyclyde 2022-09-08 09:37:41 +08:00 为什么会 cpu 高呢? |
6 julyclyde 2022-09-08 09:37:52 +08:00 @Bromine0x23 因为这就是“ingress 本身” |
![]() | 8 dzdh OP @gongshuiwen #3 还真没注意,阿里云的托管 k8s ackpro 。我去看看。 |
10 auser 2022-09-08 10:03:58 +08:00 生产环境上有类似场景 我目前的做法是: 1 ) crontab 定期 nginx reload ,应对域名对应 IP 变更的情况(不在我们控制范围) 2 )我们后台配置变更时候,通过 ssh 远程执行脚本的方式,让所有 nginx 节点执行 nginx reload |
![]() | 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 ... |
![]() | 12 cheitu 2022-09-08 10:34:43 +08:00 @auser 同生产环境一样的处理。为了省成本用 aws 的竞价,导致集群后端服务器经常会变 IP 。写了一个程序,部署在跑 nginx 的服务器上面,定时通过 aws api 获取最新服务器 ip ,如果变化,更新一下 upstream 配置文件然后 reload nginx 。upstram 配置是单独一个配置文件,方便更新。 |