微服务之间的流量经过服务网格接管后,在微服务之间引入了多个代理层,微服务之间的通信变得更为复杂了。下图分析了一个客户端请求的流量是如何在服务网格中进行路由的。
备注:由于Istio Ingress Gateway的功能缺少API管理功能,因此下图采用了API Gateway + sidecar来作为Ingress,和原始的Istio Ingress有所不同,但流量转发逻辑类似。Istio Ingress和API Gateway的差异分析参见文章:https://zhaohuabing.com/post/2018-12-27-the-obstacles-to-put-istio-into-production/#service-mesh-and-api-gateway
从上图可以看到,客户端请求从进入系统入口的Ingress,到到达后端提供服务的应用,经过了多次IPtable的重定向和Envoy的转发。
其转发流程如下:(备注:为简略起见,本流程中未描述客户端端口)
1: Client IP ---> Ingress Public IP: Server Port
2: Ingress Internal IP ---> Service 1 IP: Server Port
2.1: Ingress Internal IP ----(IPtable DNAT)---> 127.0.0.1: 15001
2.2: Ingress Internal IP---> Service1 IP:Server Port
2.2.1: Ingress Internal IP ----(IPtable DNAT)---> 127.0.0.1: 15001
2.2.2: Service1 Sidecar IP ---> 127.0.0.1: Service1 Server Port
3: Service1 IP ---> Service2 Server Port
3.1: Service1 IP ----(IPtable DNAT)---> 127.0.0.1: 15001
3.2: Service1 IP ----> Service2 Server Port
......
如果Istio配置错误导致通信故障,从应用层面上很难直接查找原因。需要通过各种手段从TCP通讯层,Pilot,Envoy等多处获取信息,对故障进行分析。
Pilot提供了一个调试端口9093,可以通过向调试端口发送REST请求来分析和查看标准数据面接口(Envoy xDS API)的数据和Pilot内部存储的状态信息。
xDS接口相关调试信息
发送给Enovy的Listener,Filter及Route配置
curl http://127.0.0.1:9093/debug/adsz
各个Cluster中配置的Endpoint
curl http://127.0.0.1:9093/debug/edsz
Cluster信息
curl http://127.0.0.1:9093/debug/cdsz
备注:上述接口中的配置信息在Envoy第一次连接到Pilot中时才会生成,在此之前,通过接口无法获取到数据。
Pilot内部的配置信息
服务注册表信息
curl http://127.0.0.1:9093/debug/registryz
所有的endpoint
curl http://127.0.0.1:9093/debug/endpointz[?brief=1]
所有的配置信息
curl http://127.0.0.1:9093/debug/configz
Pilot自身的一些性能数据
curl http://127.0.0.1:9093/metrics
参考:https://github.com/istio/istio/tree/master/pilot/pkg/proxy/envoy/v2
Envoy在localhost:15000上提供了Admin端口,可以通过docker exec命令获取其Pilot向其下发的配置信息。
sudo docker exec a83696c9e7a2 curl http://127.0.0.1:15000/config_dump
除此以外,Envoy还提供了其他调试信息,可以通过help进行查询
sudo docker exec a83696c9e7a2 curl http://127.0.0.1:15000/help
admin commands are:
/: Admin home page
/certs: print certs on machine
/clusters: upstream cluster status
/config_dump: dump current Envoy configs (experimental)
/cpuprofiler: enable/disable the CPU profiler
/healthcheck/fail: cause the server to fail health checks
/healthcheck/ok: cause the server to pass health checks
/help: print out list of admin commands
/hot_restart_version: print the hot restart compatibility version
/listeners: print listener addresses
/logging: query/change logging levels
/quitquitquit: exit the server
/reset_counters: reset all counters to zero
/runtime: print runtime values
/runtime_modify: modify runtime values
/server_info: print server version/status information
/stats: print server stats
/stats/prometheus: print server stats in prometheus format
参考: https://www.envoyproxy.io/docs/envoy/latest/operations/admin
proxy_init 容器会将设置的IPtable内容输出到标准输出中,可以查看到对那些IP端进行了拦截。
sudo docker logs 3ad9
......忽略掉前面无关的内容......
# Generated by iptables-save v1.6.0 on Fri Jan 11 07:10:19 2019
*nat
:PREROUTING ACCEPT [0:0]
:INPUT ACCEPT [0:0]
:OUTPUT ACCEPT [0:0]
:POSTROUTING ACCEPT [0:0]
:ISTIO_OUTPUT - [0:0]
:ISTIO_REDIRECT - [0:0]
-A PREROUTING -m comment --comment "istio/install-istio-prerouting" -j ISTIO_REDIRECT
-A OUTPUT -p tcp -m comment --comment "istio/install-istio-output" -j ISTIO_OUTPUT
-A ISTIO_OUTPUT ! -d 127.0.0.1/32 -o lo -m comment --comment "istio/redirect-implicit-loopback" -j ISTIO_REDIRECT
-A ISTIO_OUTPUT -m owner --uid-owner 1337 -m comment --comment "istio/bypass-envoy" -j RETURN
-A ISTIO_OUTPUT -d 127.0.0.1/32 -m comment --comment "istio/bypass-explicit-loopback" -j RETURN
-A ISTIO_OUTPUT -d 172.168.40.4/32 -m comment --comment "istio/bypass-msb-ip" -j RETURN
-A ISTIO_OUTPUT -d 100.100.0.0/16 -m comment --comment "istio/redirect-ip-range-100.100.0.0/16" -j ISTIO_REDIRECT
-A ISTIO_OUTPUT -d 172.168.40.0/24 -m comment --comment "istio/redirect-ip-range-172.168.40.0/24" -j ISTIO_REDIRECT
-A ISTIO_OUTPUT -m comment --comment "istio/bypass-default-outbound" -j RETURN
-A ISTIO_REDIRECT -p tcp -m comment --comment "istio/redirect-to-envoy-port" -j REDIRECT --to-ports 15001
COMMIT
# Completed on Fri Jan 11 07:10:19 2019
如果采用了Consul作为Service Registry,可以通过下面的接口查看Consul中的服务注册信息,以和Pilot及Envoy中的服务信息进行对比分析。
查看Consul中注册的所有服务
curl http://172.167.40.2:1107/v1/catalog/services
查看某一个服务的具体内容
curl http://172.167.40.2:1107/v1/catalog/service/{service}
参考: https://www.consul.io/api/catalog.html
Strace是一个linux系统下的小工具,可以用于跟踪一个指定进程的系统调用和其接收到的数据。该工具可以查看写入/收到file descriptor的内容,可以被用于分析微服务间的HTTP通信。
首先通过ps找到需要跟踪的进程。
sudo ps -ef|grep istio-demo
然后使用strace来监控该进程的网络消息。
sudo strace -p 91558 -f -e trace=network -s 1000
下面是strace对一个HTTP请求的相关调试输出信息,可以看到该进程对外发出了一个http请求,并收到了一个404错误。可以从输出中查看到HTTP请求的完整内容,包括Method, URL, Header等内容。
[pid 93648] sendto(285, "GET /api/istioserver/v1/animals/panda HTTP/1.1\r\nHost: 100.100.0.112:9090\r\nConnection: Keep-Alive\r\nAccept-Encoding: gzip\r\nUser-Agent: okhttp/3.3.0\r\n\r\n", 149, 0, NULL, 0) = 149
[pid 93648] recvfrom(285, "HTTP/1.1 404 Not Found\r\ndate: Fri, 11 Jan 2019 04:59:07 GMT\r\nserver: envoy\r\ncontent-length: 0\r\n\r\n", 8192, MSG_DONTWAI
strace的使用方法可参考: http://man7.org/linux/man-pages/man1/strace.1.html