V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
Recommended Services
Amazon Web Services
LeanCloud
New Relic
ClearDB
easterfan
V2EX  ›  云计算

冒死分析: Ingress 没有准备好成为"统一流量入口"

  •  1
     
  •   easterfan · 4 天前 · 3413 次点击

    目前在做的专有云领域,一个基于 k8s 的容器云迁云项目, 集群稳定运行一年后,有天突然出现 P0 事故,全平台入口宕机,事后将 ingress 架构一拆为三,写了一篇博客记录; 但是对 ingress 了解不深,观点可能有失偏颇

    所以发到 v2 上,给大佬们批评指正

    原文地址(博客托管在 github pages 上,加载可能很慢,请见谅):👇🏻

    冒死分析:Ingress 没有准备好成为"统一流量入口"

    54 条回复    2024-05-17 12:37:08 +08:00
    oaa
        1
    oaa  
       4 天前
    有点没懂。

    同时 Ingress 本身有一个 reload 机制,当检测到副本数从 N -> 0 或者 0 -> N 时,Ingress Controller 会同时触发两个 Ingress 的重载,开辟新的 worker 进程,并关闭老的 worker 进程;

    你的意思是,如果后端 pod 挂了,Nginx-Ingress 会 reload ?
    Zaden
        2
    Zaden  
       4 天前   ❤️ 3
    第一反应是 ingress 游戏……
    JoeJasper
        3
    JoeJasper  
       4 天前
    试试基于 envoy 的 Higress
    easterfan
        4
    easterfan  
    OP
       4 天前
    @oaa 是的,后端 pod 副本是 1 ,Crash 后,副本数 1->0; 然后 k8s 会重启这个 pod ,把他的副本又从 0->1; 但是 0->1, 1->0, 都会触发 ingress reload ,触发的很频繁
    lsk569937453
        5
    lsk569937453  
       4 天前   ❤️ 3
    有这么多 Ingress controller 的实现,包括但不限于 envoy,traefik,kong 。你不能因为一个 nginx ingress controller 出问题就否定整个 ingress 啊。
    billzhuang
        6
    billzhuang  
       4 天前
    TIL
    "Ingress 本身有一个 reload 机制,当检测到副本数从 N -> 0 或者 0 -> N 时,Ingress Controller 会同时触发两个 Ingress 的重载,开辟新的 worker 进程,并关闭老的 worker 进程"

    这个是 nginx ingress controller 干的么?
    easterfan
        7
    easterfan  
    OP
       4 天前
    @lsk569937453 感谢指正,哈哈哈 标题有点激进了,更正《冒死分析:nginx Ingress 没有准备好成为"统一流量入口"》
    defunct9
        8
    defunct9  
       3 天前
    pod crash ,这个才是要命的原因吧。说的更极端点,后端的 pod 掉光了,前面有啥也没用啊。
    easterfan
        9
    easterfan  
    OP
       3 天前
    @defunct9 是的,pod 没上测试集群,直接带缺陷上生产集群了;也是巧合,但是因为全平台入口宕机,事故影响面大,PaaS 平台得背锅 80% QAQ
    iv2ex
        10
    iv2ex  
       3 天前
    @Zaden Ingress 游戏还能玩不?我登录上去,地图资源加载不出来。攒了 3 、400 个 AXA
    Zaden
        11
    Zaden  
       3 天前
    @iv2ex afk 多少年了,游戏群都变成吹水群了
    adamwym
        12
    adamwym  
       3 天前
    如果 nginx 直接使用 service cluster ip 做 upstream 地址是不是就可以避免 pod 重启导致的 nginx 频繁 reload 了
    isno
        14
    isno  
       3 天前
    看到 [冒死分析] ,有点眼熟...

    你把 ingress 一分为三,但再碰到个“请求 CDP” 就 Crash 的 Pod 呢?

    这个问题的 root cause 是频繁重启的 Pod ,如果监测到这样的 Pod ,就临时把这个服务从 ingress 摘掉,这样是不是更好点?或者看看 kong 、apisix 怎么解决的
    egen
        15
    egen  
       3 天前
    可以看看 easegress
    defunct9
        16
    defunct9  
       3 天前
    要命也不是 ingress ,UDP 用 ng 来转发也不对,根本无状态。换成 haproxy 估计会好。
    cheng6563
        17
    cheng6563  
       3 天前
    nginx ingress 不知是不是非云原生的原因,好像是这类问题不少,我之前还见过在 ingress annotations 配置的东西插入了 nginx 的全局配置把 nginx 搞挂的。


    话说我司是用的 daemonset 跑的 traefik ingress
    feedcode
        18
    feedcode  
       3 天前
    > 一处理 UDP 请求,马上就 Crash 。首先出于 kubernetes 的自愈机制,deploy 控制器检测到副本数从 1 -> 0 后,会自动重启 pod ,控制副本数从 0 -> 1 ;

    pod crash 后不是 kubelet 负责重启的吗,与 Deploy Controller 没啥关系。deploy 变动会触发 replicate set 变动,然后 Replication Controller 负责 pod 更新, 也就是说 Deploy Controller 管不到 pod 副本数

    pod crash 后影响的是 Service 的 EndpointSlice , 不会直接影响 nginx config, 为啥会导致 nginx 重启
    feedcode
        19
    feedcode  
       3 天前
    @cheng6563 nginx ingress controller 有 validation webhook, enable 之后可以挡掉 99%的无效 annotation
    lasuar
        20
    lasuar  
       3 天前
    ```
    再同时供应商将 UDP 请求设置了一个超时机制,超时时间为 600s ,由于 pod 已经 crash ,所以连接一直在等待响应,虽然 Ingress 本身也有 worker 进程的超时时间,为 240s ,两者取最短,实际上 pod crash 状态出现时,每个 UDP 请求最多只等待 240s ,老的 worker 进程就会被关闭。但 240s 也是很长的时间了,已经足够发 N 多 UDP 请求,足够触发 N 次副本数 1->0, 0->1 的变化使 Ingress reload 多次,足够发生老的 nginx worker 进程被占用一直处于释放中,新的 worker 已经被用尽到无法创建。
    ```

    恕我直言,真看不太懂你这段描述,能否提供一个稳定复现的步骤呢?我和它们的疑问一样,为何服务 pod 重启会导致 ingress pod 重启。
    lasuar
        21
    lasuar  
       3 天前
    此外,你这个标题属实夸张!
    renmu
        22
    renmu  
       3 天前 via Android
    @iv2ex 能玩,只不过运营越来越不当人,玩得人越来越少了
    easterfan
        23
    easterfan  
    OP
       3 天前
    @billzhuang 是的,这个 bug 也是提在 ingress-ingress-controller 下的 https://github.com/kubernetes/ingress-nginx/issues/5492
    huihuimoe
        24
    huihuimoe  
       3 天前 via iPad
    有个问题不太理解,为何 udp 应用要接 ingress 。
    而不是使用 metallb 之类的 service lb 去承载?
    rushssss
        25
    rushssss  
       3 天前
    实际上 ingress-nginx 在处理后端 endpoint slices 变化时已经尽可能想办法避免频繁的 reload ,参考: https://kubernetes.github.io/ingress-nginx/how-it-works/#avoiding-reloads-on-endpoints-changes

    但是在 endpoint slices 从 0 -> 1 或是从 1 -> 0 的这两种情况下依然会触发 Reload, 或许楼主当时要是能给 Pod 多整几个副本就能正好绕过这个问题 :)

    当然正经解决方案还是可以考虑用 envoy 这类真正不用 reload 的中间件,或者直接把 TCP/UDP 流量直接通过 SLB 打到 nodeport 上
    svatyvabin
        26
    svatyvabin  
       3 天前
    @easterfan 而且我没记错的话,reload 好像还会把 websocket 断掉。
    jqknono
        27
    jqknono  
       3 天前 via Android
    这种 debug 经验没有任何分享价值
    anubu
        28
    anubu  
       3 天前
    大一统应该是 gateway api 吧,似乎很少看到相关分享。
    easterfan
        29
    easterfan  
    OP
       3 天前
    @anubu 是的,我们有 csb ,做熔断限流,路由转发,比 ingress 功能更丰富,但是现在还没启用
    easterfan
        30
    easterfan  
    OP
       3 天前
    @jqknono 坏的经验和好的经验一样 具有参考价值
    easterfan
        31
    easterfan  
    OP
       3 天前
    @svatyvabin websocket 暂时还没观察到,reload 把 worker 进程耗尽,倒是非常明显,ingress 独占的 8C16G 机器,worker 数是 8 ,基本 10 次左右,1min 内就可以复现 worker 进程耗尽的现象了
    easterfan
        32
    easterfan  
    OP
       3 天前
    @cheng6563 我也遇到过,最后发现是格式问题,最后好像是加了个 | 还是去掉个 | 解决的
    easterfan
        33
    easterfan  
    OP
       3 天前
    @adamwym 这个不太确定,nginx 频繁 reload ,是副本数变化导致的,跟 upstream 地址来源应该没关系吧?
    momo24672
        34
    momo24672  
       3 天前
    好奇这个 reload 是 nginx ingress 有,还是所有的 ingress 比如 kong 也会有。
    ysicing
        35
    ysicing  
       3 天前
    @cheng6563 traefik 性能咋样,计划后面用 traefik ,traefik 插件挺好用的😂
    easterfan
        36
    easterfan  
    OP
       3 天前
    @cheng6563 感谢提醒,我回去找一下这个报错
    1. annotation 引起格式问题导致 ngixn 挂
    2. 频繁 reload 场景耗尽 worker 进程,导致 ingress 挂

    使用 nginx-ingress 做全局流量入口,这两种场景是全局宕机的风险
    fsdrw08
        37
    fsdrw08  
       3 天前 via Android
    我的理解,ingress 只能算是反向代理的规则,至于反向代理是如何实现这些规则的还得看各家 ingress provider 的方法,所以不能说 ingress 不行,就案例来说,就是 nginx reload 导致的问题。当然,大项目,多后台的情况,应该考虑使用 api gateway
    corvofeng
        38
    corvofeng  
       3 天前 via Android
    看起来是转发 UDP 请求遇到的 如果是 HTTP 请求 是不会触发 reload 的 会由 Lua 来配置后端
    corvofeng
        39
    corvofeng  
       3 天前 via Android
    看起来是转发 UDP 请求遇到的 如果是 HTTP 请求 是不会触发整体 reload 的 会由 Lua 来配置 upstream 后端
    aitianci
        40
    aitianci  
       3 天前
    @Zaden #2 时代的眼泪😭
    privil
        41
    privil  
       3 天前
    @momo24672 基于 nginx openresty 的都会有的,kong ,apisix 都有这个问题。
    privil
        42
    privil  
       3 天前   ❤️ 1
    @JoeJasper 确实,之前看 Sealos 的网关选型经验 https://mp.weixin.qq.com/s/Ks1iOCQFFMyLJp8C7HtpaA
    iv2ex
        43
    iv2ex  
       3 天前
    @renmu 怎么解决定位的问题?登录成功之后应该是没有定位信息,所以加载不出来地图资源和聊天信息
    ExplodingFKL
        44
    ExplodingFKL  
       3 天前
    看架构里面最奇怪的是为啥要用 nginx 来做 udp 转发
    sampeng
        45
    sampeng  
       3 天前
    我很纳闷。。。udp 你一定要用 ingress 怪谁呢。。。
    sampeng
        46
    sampeng  
       3 天前
    在上 k8s 的时候 udp 入口就不要从 ingress 进来。这不是 ingress 干的事。或者说,不合理,不好用。ingress 就处理 http 就好了。
    sampeng
        47
    sampeng  
       3 天前
    既然是在云上。svc 直接挂在 nlb 上暴露出去即可。。压根不需要 ingress 来参与
    sampeng
        48
    sampeng  
       3 天前
    另一方面,health check 太糟糕。你这锅盖 ingress 上实在是不对。作为运维,你的监控系统和 nginx 的 health 检查居然不和你业务相结合。。。nginx 挂了你倒是自动重启 nginx 啊。。。

    所以两个小时核心是 udp 服务挂了两个小时??

    反正 lz 是懂起标题的
    clhlc
        49
    clhlc  
       3 天前
    slb 流量直接到 pod ,去掉 ingress 这一层
    easterfan
        50
    easterfan  
    OP
       2 天前
    @huihuimoe 主要是一开始 ingress 定位就是所有流量入口,没调研到 udp 场景,也是出了事故后,才知道供应商有 UDP 应用~
    metallb 我们目前还没有生产使用经验,感谢提醒,后面会调研下
    easterfan
        51
    easterfan  
    OP
       2 天前
    @rushssss 感谢回复!很靠谱的方案
    不过”UDP 流量直接通过 SLB 打到 nodeport 上“,这个方案可能不太合适

    1. 集群规模 100 多台机器,除了管控 node 常驻外,其他 worker node ,都是会存在主机上下线场景,nodeport 的 EIP 不好固定,UDP 流量都打到管控 node 的话,这几台机器高峰期压力很大

    2. 还是集群规模上,100 多台机器上都开 nodeport 端口,实际只有 1 2 台机器开 EIP + nodeport ,为一个业务开这么多端口,开销大,也显得浪费,所有供应商的对外服务暴露,没有必要情况,都要求首先走 ingress ,不走 nodeport

    3. 现在架构设计是 SLB 下挂了 2 台 ingress 主机,如果用 机器 EIP+nodeport 方式,让业务流量直接打到 worker 机器上,那现在这种负载均衡设计就没意义了啊

    cc @sampeng
    sampeng
        52
    sampeng  
       2 天前
    @easterfan 哦。你的网络模式是没和外部打通的?我一般云上建集群是使用 ip 模式。这样更灵活,网络吞吐也更好,因为从技术上来说,网络包是正儿八经的跟网卡绑定进行流转的,可以做更多的事。这种方式 slb 就是直接到 pod 。比如 nginx ingress 。我推测你现在的方式是 nginx 用的 host ,然后独占一台机器。然后把 slb 指向这个机器组。

    我从来就不用 nodeport 的方式。。。只会在开发环境自己懒得折腾就搞的 nodeport
    sampeng
        53
    sampeng  
       2 天前
    aws:

    https://kubernetes-sigs.github.io/aws-load-balancer-controller/v2.2/guide/service/annotations/#nlb-target-type

    service.beta.kubernetes.io/aws-load-balancer-nlb-target-type

    ip mode will route traffic directly to the pod IP.

    network plugin must use native AWS VPC networking configuration for pod IP, for example Amazon VPC CNI plugin.

    阿里云:
    https://help.aliyun.com/zh/ack/ack-managed-and-ack-dedicated/user-guide/add-annotations-to-the-yaml-file-of-a-service-to-configure-clb-instances#c049ddf4f5uba

    直接将 Pod ENI 挂载到 CLB 后端
    Annotation:service.beta.kubernetes.io/backend-type
    CLB 后端服务器类型。取值:

    eni:通过此配置将 Pod 挂载到 CLB 后端,可以提高网络转发性能。仅在 Terway 网络模式下生效。
    ecs:将 ECS 挂载到 CLB 后端。
    sampeng
        54
    sampeng  
       2 天前
    单机独占 host 的 nginx 。。你后面还会踩雷。。
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   实用小工具   ·   2275 人在线   最高记录 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 28ms · UTC 09:21 · PVG 17:21 · LAX 02:21 · JFK 05:21
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.