通过 wireshark 快速排查客户现场微服务环境部署问题-案例分享
1 前言-关于tcp/ip数据包与wireshark
- 在网络世界里,所有的应用层协议(http/https,ssh/telnet,ftp,dns,kerberos,smb,dubbo/grpc/netty 等),其底层都是IP数据包以及IP数据包之上的TCP/UDP数据包(ip packet, tcp segment, udp datagram)。
- 一些常见的包嗅探和包分析工具,如 tcpdump/wireshark/tshark等,可以让我们清晰地看到网络通信在底层数据包层面的交互情况,为排查复杂环境的网络故障,网络性能,甚至应用性能,提供帮助。
- 本文分享一个通过wireshark快速排查客户现场微服务环境部署问题的案例,希望对大家有所帮助。
2 客户现场微服务部署问题概述
- 某应用系统采用微服务架构,基于 docker/k8s/helm 采用容器化方式进行开发和部署。
- 在公司内部容器平台上经开发测试验证后,所有功能一切正常,于是部署到了客户现场的容器管理平台并进行测试。但是验证发现客户现场所有功能都不能正常使用。
- 相关同学初步排查,发现k8s的deployment以及底层的Pod都是启动成功的(客户的容器管理平台和k8s pod 的相关event和日志都印证了这点),telnet测试宿主机和容器之间网络端口的连通性没有问题,排查业务日志发现微服务注册是成功的也收到了前段发起的请求,但前段响应异常。
- 客户现场容器管理平台上,业务应用对应的deployment页面如下:
- 长时间排查无果后,相关同学联系了更多技术专家包括笔者协助排查问题,并提供了相关pcap数据包。
3 通过 wireshark 分析数据包发现问题
3.1 数据包总览
通过 wireshark 打开现场同学提供的pcap数据包,查看专家信息(expert information),并没有发现严重的丢包和重传等问题,但是有大量Malformed数据包:
笔者不太清楚微服务之间的调用关系,为快速排查问题,直接以k8s deployment涉及的ip端口过滤数据包并跟踪tcp流进行排查,如下图所示(tcp.port eq 60270, then follow tcp stream):
3.2 端口60279问题
直接以k8s deployment涉及的60279端口过滤数据包并跟踪tcp流进行排查,发现60279端口上有HTTP请求和HTTP响应,其HTTP数据如下:
HEAD / HTTP/1.0 HTTP/1.1 426 Upgrade Required date: Mon, 19 Jun 2023 08:10:11 GMT server: istio-envoy connection: close
- 进一步了解发现,Istio使用Envoy作为数据面转发HTTP请求,而Envoy默认要求使用HTTP/1.1或HTTP/2,当客户端使用HTTP/1.0时就会返回426 Upgrade Required,而使用nginx进行proxy_pass反向代理时默认会用 HTTP/1.0,所以可能需要修改nginx的配置文件nginx.conf,显示指定代理proxy_http_version为1.1;
3.3 端口60270问题
直接以k8s deployment涉及的60270端口过滤数据包并跟踪tcp流进行排查,发现60270端口上相关数据如下:
y..y3=2.5=32.30=nginx_test_0AAEC680#5.31=xo5vVuS9ZKreq514M2E5uGTdF01n0pTn+yFvhHa7SK4i1z5NfK1g/tprfXmz41YaJXw=.62=hsiar_nginx.HTTP/1.1 400 Bad Request content-length: 11 content-type: text/plain date: Mon, 19 Jun 2023 08:10:01 GMT server: istio-envoy connection: close Bad Request
- tcp三次握手完毕后,客户端并没有发起http请求(仅仅Push了nginx_test_0AAEC680 tcp 数据包),但服务端却响应了HTTP/1.1 400 Bad Request并关闭了http连接,随后tcp挥手关闭了连接:
4 问题汇总分析与解决
通过使用wireshark对数据包进行分析可以发现,网络通信在数据包层面都是联通的是正常的,但使用具体协议解析TCP数据包时有问题而引起了报错(比如不支持http1.0,比如错将非http协议当作http协议进行解析),且这些报错都来自 istio-envoy,向业务人员进一步了解发现,我们公司内部部署微服务时没有集成使用istio,但客户这里的容器平台集成了istio,至此问题清晰,问题应该是在微服务跟istion的集成上:
- 客户这里的容器平台使用了istion 服务网格,Istio 从逻辑上分为数据平面和控制平面, 数据平面由一组智能代理(Envoy 4)组成, 这些代理负责协调和控制微服务之间的所有网络通信;
- istio支持http/http2/https/tcp/grpc等通信协议,具体使用的协议可以自动推导也可以显示指定(Automatic protocol selection or Explicit protocol selection);
- 由于istio自己推导协议容易错误(比如我们这里dump文件中将非http请求数据包当作http数据报解析出错,返回了bad request),最好在 pod 中显示指定协议:
- 将以上问题反馈后,修改pod显示指定协议,问题解决;
- 使用ISTIO时,有 sidecar 和 gateway 两种方式,两者对协议自动推导的支持不同,具体见官网:
- https://istio.io/latest/docs/ops/configuration/traffic-management/protocol-selection/ - Istio supports proxying any TCP traffic. This includes HTTP, HTTPS, gRPC, as well as raw TCP protocols. In order to provide additional capabilities, such as routing and rich metrics, the protocol must be determined. This can be done automatically or explicitly specified. - Istio can automatically detect HTTP and HTTP/2 traffic. If the protocol cannot automatically be determined, traffic will be treated as plain TCP traffic. - Protocols can be specified manually in the Service definition.This can be configured in two ways:By the name of the port: name: <protocol>[-<suffix>];In Kubernetes 1.18+, by the appProtocol field: appProtocol: <protocol>. - HTTP gateway protocol selection:Unlike sidecars, gateways are by default unable to automatically detect the specific HTTP protocol to use when forwarding requests to backend services. Therefore, unless explicit protocol selection is used to specify HTTP/1.1 (http) or HTTP/2 (http2 or grpc), gateways will forward all incoming HTTP requests using HTTP/1.1. -HTTP gateway protocol selection:Instead of using explicit protocol selection, you can instruct gateways to forward requests using the same protocol as the incoming request by setting the useClientProtocol option for a Service.