Kubernetes

Istio Idle Timeout问题复现和解决

更新 2024-04-01 #

通过调整 tcp_proxy 的 idle_timeout 参数后,部分中间件(redis, mongo)的异常问题不再出现,但是 mysql(sharding-spere) 和 memcached 仍然存在 “invalid connection” 错误,所以还需要找到能够解决 mysql(sharding-spere) 和 memcached 的方法。

上述描述的现象非常主观,不一定正确也不能作为最终结论,但是 idle_timeout 配置确实没有解决所有的问题。

这里,需要知道 istio 在 inject 时会通过 iptables 对应用的流量进行劫持,对于 outbound 的流量 iptables 规则拦截转发到 OUTPUT 链。OUTPUT 的链转发流量到 ISTIO_OUTPUT,这个链会决定服务访问外部服务的流量发往何处。

这样产生的效果是,除了应用自己建立的连接之外 envoy 也会创建一个代理连接。

$ netstat -notp | grep 3307
tcp         0             172.23.105.25:41030        x.x.x.x:3307         ESTABLISHED -      off(0.00/0/0)
tcp         0             172.23.105.25:41022        x.x.x.x:3307         ESTABLISHED 1/./app      keepalive(0.88/0/0)

我遇到的问题可以确定问题就出在 envoy 建立的连接上,因为应用自己建立的连接是正常的,同时还可以看到应用自己的连接开启了 keepalive, 而 envoy 建立的连接没有开启。这样可能会出现这个连接会因为超时而被关闭的情况,或者其他原因导致连接被释放。那如果可以避免将中间件的流量通过 envoy 代理,这样就可以避免这个问题。

在官方的文档中也提到,https://istio.io/latest/zh/docs/tasks/traffic-management/egress/egress-control/ 对于外部服务,可以通过配置 excludeOutboundPorts 或者 excludeOutboundIPRanges 来使得某些服务的流量不经过 istio sidecar。其背后的原理是通过 iptables 的规则中排除这些端口或者 IP 地址。

...

Kubernetes中gRPC Load Balancing分析和解决

背景 #

第一次,线上遇到大量接口RT超过10s触发了系统告警,运维反馈k8s集群无异常,负载无明显上升。将报警接口相关的服务重启一番后发现并无改善。但是开发人员使用链路追踪系统发现,比较慢的请求总是某个gRPC服务中的几个POD导致,由其他POD处理的请求并不会出现超时告警。

第二次,同样遇到接口RT超过阈值触发告警,从k8s中查到某个gRPC服务(关键服务)重启次数异常,查看重启原因时发现是OOM KilledOOM killed并不是负载不均衡直接导致的,但是也有一定的关系,这个后面再说。前两次由于监控不够完善(于我而言,运维的很多面板都没有权限,没办法排查)。期间利用pprof分析了该服务内存泄漏点,并修复上线观察。经过第二次问题并解决之后,线上超时告警恢复正常水平,但是该 deployment 下的几个POD占用资源(Mem / CPU / Network-IO),差距甚大。

第二张图是运维第一次发现该服务OOM killed 之后调整了内存上限从 512MB => 1G,然而只是让它死得慢一点而已。 从上面两张图能够石锤的是该服务一定存在内存泄漏。Go项目内存占用的分析,我总结了如下的排查步骤:

1. 代码泄漏(pprof)(可能原因 goroutine泄漏;闭包)
2. Go Runtime + Linux 内核(RSS虚高导致OOM)https://github.com/golang/go/issues/23687
3. 采集指标不正常(container_memory_working_set_bytes)

2,3 是基于第1点能基本排除代码问题的后续步骤。

解决和排查手段:

1. pprof 通过heap + goroutine 是否异常,来定位泄漏点
运行`go tool pprof`命令时加上--nodefration=0.05参数,表示如果调用的子函数使用的CPU、memory不超过 5%,就忽略它。

2. 确认go版本和内核版本,确认是否开启了MADV_FREE,导致RSS下降不及时(1.12+ 和 linux内核版本大于 4.5)
3.  RSS + Cache 内存检查

> Cache 过大的原因 https://www.cnblogs.com/zh94/p/11922714.html 
// IO密集:手动释放或者定期重启

查看服务器内存使用情况: `free -g`
查看进程内存情况:      `pidstat -rI -p 13744`
查看进程打开的文件:    `lsof -p 13744`
查看容器内的PID:      `docker inspect --format "{{ .State.Pid}}" 6e7efbb80a9d`
查看进程树,找到目标:   `pstree -p 13744`

参考:https://eddycjy.com/posts/why-container-memory-exceed/

通过上述步骤,我发现了该POD被OOM killed还有另一个元凶就是,日志文件占用。这里就不过多的详述了,搜索方向是 “一个运行中程序在内存中如何组织 + Cache内存是由哪些部分构成的”。这部分要达到的目标是:一个程序运行起来它为什么占用了这么些内存,而不是更多或者更少。

...

访问量 访客数