zoukankan      html  css  js  c++  java
  • Kubernetes Ingress诡异的502、503、504等奇葩问题(二)

    公众号原文:https://mp.weixin.qq.com/s/nEBMG8zdW1O-3XvygMSRVQ

     
    image

    上一篇《Kubernetes Ingress诡异的502、503、504等奇葩问题(一)》简要说明了使用基于 haproxy 的 ingress 时,遇到 503 的问题,这一篇记录使用基于 nginx 的 ingress 时,遇到的 502 的问题。

    启用 keep-alive,502 响应增加

    nginx-ingress-controller 0.20 之前的版本存在一个 bug,配置模版 nginx.tmpl 中没有在启用 keep-alive 时清除请求中的 “Connection: close”,反而是为所有转发给 upstream 的 http 请求加上了该请求头:

     
    image

    应该是

     
    image

    因为该 bug 的存在, 0.20 之前的版本即使在 config-map 中配置了 keep-alive,nginx 与 pod 之间的 http 通信依旧是短连接,每产生一个请求就建立一个连接。连接利用效率低,并且大量连接处于 time-wait 状态,浪费了数量有限的本地端口。

    发现该问题后,我们进行了及时修复,然后问题来了。

    nginx 的请求日志显示,keep-alive 真正生效以后,502 响应的数量有所增多,大部分业务系统对此不敏感,但有个别系统因 502 响应而频繁告警,这些系统在 keep-alive 没有生效之前,没有遇到 502 响应。

    调查工作开始。

    502 响应占比很少很少,并且出现的时机不明,一开始毫无头绪,通过翻阅 nginx 的日志和分析抓取的部分报文发现,出现 502 响应时,nginx 向 upstream 转发请求后,立即收到了 RST 报文:连接被 pod 断开了。

    Nginx 转发给 Pod 的请求中指定了 keep-alive,连接也持续了较长时间,来回有过多次请求了,为什么会突然被 Pod 断开连接呢?

    各种胡思乱想之后,将目标锁定为在 Pod 中运行的业务系统。在 Pod 中运行的业务系统是一个 tomcat 服务,tomcat 本身就是一个请求代理软件。

    事实上,客户端发起的请求经过了两次代理,第一次由 nginx 代理到 Pod 中的 tomcat,第二次由 tomcat 代理到处理该请求的进程。

    翻看 tomcat 的配置手册时,发现 tomcat 有几个和 nginx 类似的配置,它们分别指定了长连接的闲置超时时间(keepAliveTimeout)和长连接中的请求数量上限(maxKeepAliveRequest)。

     
    image
     
    image

    很巧的是,这两个配置项的默认值和 nginx 中类似配置的默认值相同,都是连接闲置 60s 秒后断开,以及连接中请求数量达到 100 后,断开连接。那么问题来了,nginx 和 tomcat 谁会先断开连接?

    从捕获的报文来看,有时候是 tomcat 先断开的,nginx 后知后觉依旧转发请求,结果收到了 RST 大礼包,继而回应 502。502 错误码含义正是:上游返回了非预期的数据。

    随后我们分析了另一个有同样问题的 python 服务,这个 python 服务也不是直接监听端口处理请求的,而是用 Gunicorn 代理。查了一下 Gunicorn 的默认配置,更夸张,它的连接闲置超时时间是 2 秒!

    分析该 python 服务的报文时还在纳闷,为什么它的连接很快就断开?一度让我们怀疑前面的假设,直到发现它的默认超时时间是 2 秒,才释然:报文显示,连接正是在闲置 2 秒之后,被 Pod 端主动断开的!

     
    image

    要避免 Pod 先断开连接,方法其实很简单,让 nginx 中的相关配置小于 Pod 中的代理软件的相关配置即可。譬如tomcat 的 maxKeepAliveRequest 是 100,那么 nginx 中配置成 99,确保连接是被 nginx 主动断开的。

    这里只大概说明一下原委,查看当时的调查记录,点击「阅读原文」。

    另外还有一个 504 的问题,504 其实是 kube-apiserver 的配置错误导致的,因为配置错误导致 endpoints 没有及时更新,继而导致 nginx 的配置文件没有更新。

    Nginx 的 upstream 配置中的 IP 地址早已不存在,或者已经分配给其它 Pod,从而导致客户端收到 504 响应或者得到的是另一个服务的响应。

    因为时间紧任务多的缘故,我们把配置修复以后,没有对此进行深入追究,如果有了进一步分析,再补发吧。感谢关注,感谢转发!

    上一篇:Kubernetes Ingress诡异的502、503、504等奇葩问题(一)

    关注返回作者微信,直接加,不闲扯

    (除非特殊情况,不帮忙解决问题)

     
    image

    公众号原文:https://mp.weixin.qq.com/s/nEBMG8zdW1O-3XvygMSRVQ

  • 相关阅读:
    使用 C# .NET 在 ASP.NET 应用程序中实现基于窗体的身份验证
    高性能 Windows Socket 组件 HPSocket
    Linux下的C编程实战
    Scrum实践
    hadoop之NameNode,DataNode,Secondary NameNode
    代码抽象层次
    分布式统计的思考以及实现
    GCC起步
    学习 easyui 之一:easyloader 分析与使用
    从Prism中学习设计模式之MVVM 模式简述MVVM
  • 原文地址:https://www.cnblogs.com/lijiaocn/p/11178859.html
Copyright © 2011-2022 走看看