环境是 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 2022-09-08 07:21:53 +08:00
我们正在研究使用 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 配置是单独一个配置文件,方便更新。
|