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

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

  •  1
     
  •   easterfan · 15 天前 · 3742 次点击

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

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

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

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

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

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

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

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

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

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


    话说我司是用的 daemonset 跑的 traefik ingress
    feedcode
        18
    feedcode  
       15 天前
    > 一处理 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  
       15 天前
    @cheng6563 nginx ingress controller 有 validation webhook, enable 之后可以挡掉 99%的无效 annotation
    lasuar
        20
    lasuar  
       15 天前
    ```
    再同时供应商将 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  
       15 天前
    此外,你这个标题属实夸张!
    renmu
        22
    renmu  
       15 天前 via Android
    @iv2ex 能玩,只不过运营越来越不当人,玩得人越来越少了
    easterfan
        23
    easterfan  
    OP
       15 天前
    @billzhuang 是的,这个 bug 也是提在 ingress-ingress-controller 下的 https://github.com/kubernetes/ingress-nginx/issues/5492
    huihuimoe
        24
    huihuimoe  
       15 天前 via iPad
    有个问题不太理解,为何 udp 应用要接 ingress 。
    而不是使用 metallb 之类的 service lb 去承载?
    rushssss
        25
    rushssss  
       15 天前
    实际上 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  
       15 天前
    @easterfan 而且我没记错的话,reload 好像还会把 websocket 断掉。
    jqknono
        27
    jqknono  
       15 天前 via Android
    这种 debug 经验没有任何分享价值
    anubu
        28
    anubu  
       14 天前
    大一统应该是 gateway api 吧,似乎很少看到相关分享。
    easterfan
        29
    easterfan  
    OP
       14 天前
    @anubu 是的,我们有 csb ,做熔断限流,路由转发,比 ingress 功能更丰富,但是现在还没启用
    easterfan
        30
    easterfan  
    OP
       14 天前
    @jqknono 坏的经验和好的经验一样 具有参考价值
    easterfan
        31
    easterfan  
    OP
       14 天前
    @svatyvabin websocket 暂时还没观察到,reload 把 worker 进程耗尽,倒是非常明显,ingress 独占的 8C16G 机器,worker 数是 8 ,基本 10 次左右,1min 内就可以复现 worker 进程耗尽的现象了
    easterfan
        32
    easterfan  
    OP
       14 天前
    @cheng6563 我也遇到过,最后发现是格式问题,最后好像是加了个 | 还是去掉个 | 解决的
    easterfan
        33
    easterfan  
    OP
       14 天前
    @adamwym 这个不太确定,nginx 频繁 reload ,是副本数变化导致的,跟 upstream 地址来源应该没关系吧?
    momo24672
        34
    momo24672  
       14 天前
    好奇这个 reload 是 nginx ingress 有,还是所有的 ingress 比如 kong 也会有。
    ysicing
        35
    ysicing  
       14 天前
    @cheng6563 traefik 性能咋样,计划后面用 traefik ,traefik 插件挺好用的😂
    easterfan
        36
    easterfan  
    OP
       14 天前
    @cheng6563 感谢提醒,我回去找一下这个报错
    1. annotation 引起格式问题导致 ngixn 挂
    2. 频繁 reload 场景耗尽 worker 进程,导致 ingress 挂

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

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

    反正 lz 是懂起标题的
    clhlc
        49
    clhlc  
       14 天前
    slb 流量直接到 pod ,去掉 ingress 这一层
    easterfan
        50
    easterfan  
    OP
       14 天前
    @huihuimoe 主要是一开始 ingress 定位就是所有流量入口,没调研到 udp 场景,也是出了事故后,才知道供应商有 UDP 应用~
    metallb 我们目前还没有生产使用经验,感谢提醒,后面会调研下
    easterfan
        51
    easterfan  
    OP
       14 天前
    @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  
       13 天前
    @easterfan 哦。你的网络模式是没和外部打通的?我一般云上建集群是使用 ip 模式。这样更灵活,网络吞吐也更好,因为从技术上来说,网络包是正儿八经的跟网卡绑定进行流转的,可以做更多的事。这种方式 slb 就是直接到 pod 。比如 nginx ingress 。我推测你现在的方式是 nginx 用的 host ,然后独占一台机器。然后把 slb 指向这个机器组。

    我从来就不用 nodeport 的方式。。。只会在开发环境自己懒得折腾就搞的 nodeport
    sampeng
        53
    sampeng  
       13 天前
    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  
       13 天前
    单机独占 host 的 nginx 。。你后面还会踩雷。。
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   实用小工具   ·   2955 人在线   最高记录 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 26ms · UTC 13:46 · PVG 21:46 · LAX 06:46 · JFK 09:46
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.