共计 6112 个字符,预计需要花费 16 分钟才能阅读完成。
图片起源: Rowan Atkinson Goes to Battle in‘Man vs. Bee’
本文摘自我的开源书《Istio & Envoy 底细》中的 Istio 端口 与 组件。如图片不清,可回到原文。
最近,须要在 mTLS 的 Istio 1.12 环境下定位一些“神奇”的网络问题。经验过一些 tcpdump 抓取 Istio 流量的折腾,被迫又温习了一次 Istio 的网络魔术,固记录于本文。
前言
无论你抵赖与否,咱们习惯是缘用旧办法或工具去解决新问题。就算曾经达到 Cloud Natvie, Service Mesh 时代,人们也会默认持续用 tcpdump 去定位网络问题。这有问题吗?或者有,或者没有,我没答案。
tcpdump 的历史
https://en.wikipedia.org/wiki…
tcpdump was originally written in 1988 by Van Jacobson, Sally Floyd, Vern Paxson and Steven McCanne who were, at the time, working in the Lawrence Berkeley Laboratory Network Research Group. By the late 1990s there were numerous versions of tcpdump distributed as part of various operating systems, and numerous patches that were not well coordinated. Michael Richardson (mcr)&action=edit&redlink=1) and Bill Fenner created www.tcpdump.org in 1999.
对读者的假如
假如读者曾经理解过 Istio。想看看其 POD 内的流量魔术,以在排坑时有肯定套路和理论依据。
互动图片
📢 本文的失常关上办法是,点击“用 Draw.io 关上”后,进入互动图片状态。本文的大部分内容是放在图中了。看图比文字更重要。
Istio 的网络魔术预览
原始的我是个喜爱谈话直接了当的人(尽管社会曾经迫我学习和爱上绕圈子)。这里先间接贴上我的钻研后果图,前面会剖析。
图:Istio 端口与组件
用 Draw.io 关上
tcpdump 抓包办法
这里先给个论断。为面再讲原理和绕圈子。
Sidecar 抓包
图:Istio 端口与组件
中蕴含了一些在 Istio 中时行 tcpdump 的阐明。在此不再赘述。要补充一下是的 tcpdump 的抓包点。因为,这个点影响了,tcpdump 的过滤条件与输入。次要是这个点与 iptables 的 redirect 规定失效的前后问题。
tcpdump capture pinpoint:
tcpdump will see inbound traffic before iptables, but will see
outbound traffic only after the firewall has processed it.As a matter of fact, tcpdump is the first software found after the wire (and the NIC, if you will) on the way IN, and the last one on the way OUT.
- Wire -> NIC -> tcpdump -> netfilter/iptables
- iptables -> tcpdump -> NIC -> Wire
######## sidecar ########
sudo nsenter -t $PID_OF_SIDECAR_ENVOY -n -u
export ETH0_IP=$(ip addr show eth0 | grep "inet\b" | awk '{print $2}' | cut -d/ -f1)
export LOCAL_IP=$(ip addr show lo | grep "inet\b" | awk '{print $2}' | cut -d/ -f1)
# inbound mTLS
sudo tcpdump -i eth0 -n -vvvv "(dst port 8080 and dst $ETH0_IP) or (src port 8080 and src $ETH0_IP)"
# inbound 明文
sudo tcpdump -i lo -n -vvvv -A "(dst port 8080 and dst $ETH0_IP) or (src port 8080 and src $ETH0_IP)"
# outbound 明文
sudo tcpdump -i lo -n -vvvv -A "((dst port 15001 and dst 127.0.0.1) or (dst portrange 20000-65535 and dst $ETH0_IP))"
# outbound mTLS
sudo tcpdump -i eth0 -n -vvvv -A "((src portrange 20000-65535 and src $ETH0_IP) or (dst portrange 20000-65535 and dst $ETH0_IP))"
有一点比拟麻烦的是,outbound 明文
抓包,出向 ip packet 抓到的是 redirect 后的 127.0.0.1,入向 ip packet 抓到的是未 redirect 前的 ip 地址。如果你用 Wireshark 等工具剖析。是无奈 Follow TCP Stream 的。
Istio Gateway 抓包
个别,Istio Gateway 的 upsteam(Cluster 外部),与 downsteam(Cluster 内部)会在不同的 subnet,所以,能够用 CIDR 去辨别。
首先,看看 kubernetes cluster 的 pod 的 cidr 范畴:
ps -ef | grep cidr
root 48587 20177 0 Dec08 ? 00:21:25 kube-controller-manager ... --cluster-cidr=192.168.0.0/12 ...--service-cluster-ip-range=10.96.0.0/12 ...
这时,如果尝试间接应用下面的参数会出错:
$ sudo tcpdump -i br0 -vvvv -A net 192.168.0.0/12
tcpdump: non-network bits set in "192.168.0.0/12"
发现,tcpdump 对 cidr 的格局要求比拟严格,要求用首个可用 ip 段。应用 https://cidr.xyz/ 剖析出 192.168.0.0/12
的首个可用 ip 为 192.160.0.1
,固:
sudo tcpdump -i br0 -vvvv -A net 192.160.0.0/12
Istio 的网络魔术
监听端口
能够用以下形式查看监听的端口:
$ nsenter -n -t $PID_OF_ENVOY
$ ss -ln
u_str LISTEN etc/istio/proxy/SDS 34782 * 0 users:(("pilot-agent",pid=3406,fd=13))
u_str LISTEN etc/istio/proxy/XDS 34783 * 0 users:(("pilot-agent",pid=3406,fd=16))
u_str ESTAB etc/istio/proxy/XDS 1379729 * 1379728 users:(("pilot-agent",pid=3406,fd=8))
u_str ESTAB * 1379728 * 1379729 users:(("envoy",pid=3555,fd=37))
u_str ESTAB etc/istio/proxy/SDS 45274 * 46319 users:(("pilot-agent",pid=3406,fd=15))
u_str ESTAB * 46319 * 45274 users:(("envoy",pid=3555,fd=19))
tcp LISTEN 0.0.0.0:15021 0.0.0.0:* users:(("envoy",pid=3555,fd=40),("envoy",pid=3555,fd=34),("envoy",pid=3555,fd=22))
tcp LISTEN 0.0.0.0:15090 0.0.0.0:* users:(("envoy",pid=3555,fd=39),("envoy",pid=3555,fd=33),("envoy",pid=3555,fd=21))
tcp LISTEN 127.0.0.1:15000 0.0.0.0:* users:(("envoy",pid=3555,fd=18))
tcp LISTEN 0.0.0.0:15001 0.0.0.0:* users:(("envoy",pid=3555,fd=41),("envoy",pid=3555,fd=35),("envoy",pid=3555,fd=31))
tcp LISTEN 127.0.0.1:15004 0.0.0.0:* users:(("pilot-agent",pid=3406,fd=17))
tcp LISTEN 0.0.0.0:15006 0.0.0.0:* users:(("envoy",pid=3555,fd=42),("envoy",pid=3555,fd=36),("envoy",pid=3555,fd=32))
tcp ESTAB 172.21.206.227:40560 10.108.217.90:15012 users:(("pilot-agent",pid=3406,fd=19))
tcp ESTAB 172.21.206.227:43240 10.108.217.90:15012 users:(("pilot-agent",pid=3406,fd=14))
tcp LISTEN *:15020 *:* users:(("pilot-agent",pid=3406,fd=12))
tcp ESTAB 127.0.0.1:35256 127.0.0.1:15020 users:(("envoy",pid=3555,fd=43))
tcp ESTAB 127.0.0.1:35238 127.0.0.1:15020 users:(("envoy",pid=3555,fd=20))
tcp ESTAB [::ffff:127.0.0.1]:15020 [::ffff:127.0.0.1]:35238 users:(("pilot-agent",pid=3406,fd=6))
tcp ESTAB [::ffff:127.0.0.1]:15020 [::ffff:127.0.0.1]:35256 users:(("pilot-agent",pid=3406,fd=18))
iptables
$ iptables-save
# Generated by iptables-save v1.8.7 on Fri Dec 16 16:18:31 2022
*nat
:PREROUTING ACCEPT [104490:5433496]
:INPUT ACCEPT [105123:5471476]
:OUTPUT ACCEPT [24745:1633905]
:POSTROUTING ACCEPT [42627:2706825]
:ISTIO_INBOUND - [0:0]
:ISTIO_IN_REDIRECT - [0:0]
:ISTIO_OUTPUT - [0:0]
:ISTIO_REDIRECT - [0:0]
-A PREROUTING -p tcp -j ISTIO_INBOUND
-A OUTPUT -p tcp -j ISTIO_OUTPUT
-A ISTIO_INBOUND -p tcp -m tcp --dport 15008 -j RETURN
-A ISTIO_INBOUND -p tcp -m tcp --dport 15090 -j RETURN
-A ISTIO_INBOUND -p tcp -m tcp --dport 15021 -j RETURN
-A ISTIO_INBOUND -p tcp -m tcp --dport 15020 -j RETURN
-A ISTIO_INBOUND -p tcp -j ISTIO_IN_REDIRECT
-A ISTIO_IN_REDIRECT -p tcp -j REDIRECT --to-ports 15006
-A ISTIO_OUTPUT -s 127.0.0.6/32 -o lo -j RETURN
-A ISTIO_OUTPUT ! -d 127.0.0.1/32 -o lo -m owner --uid-owner 201507 -j ISTIO_IN_REDIRECT
-A ISTIO_OUTPUT -o lo -m owner ! --uid-owner 201507 -j RETURN
-A ISTIO_OUTPUT -m owner --uid-owner 201507 -j RETURN
-A ISTIO_OUTPUT ! -d 127.0.0.1/32 -o lo -m owner --gid-owner 201507 -j ISTIO_IN_REDIRECT
-A ISTIO_OUTPUT -o lo -m owner ! --gid-owner 201507 -j RETURN
-A ISTIO_OUTPUT -m owner --gid-owner 201507 -j RETURN
-A ISTIO_OUTPUT -d 127.0.0.1/32 -j RETURN
-A ISTIO_OUTPUT -j ISTIO_REDIRECT
-A ISTIO_REDIRECT -p tcp -j REDIRECT --to-ports 15001
COMMIT
这个 iptable 的原理网上说了很多,这里不再阐明了。
连贯
图:Istio 端口与组件
中蕴含了一些在 Istio 中时行 pod 外部的 TCP 连贯的阐明(见其中的 ss
命令输入)。在此不再赘述。
神奇的 127.0.0.6
出于十分多的起因,inbound 流量在由 Envoy 转到 app 时,Envoy 建设的 TCP 连贯 bind 的 ip 地址是一个 ip addr
也查不到的,在 lo
接口上的 127.0.0.6
。如果你好奇,能够看:
Why the bind magic
127.0.0.6
?
- Document the 127.0.0.6 magic #29603
- Inbound Forwarding
- Understanding the Sidecar Injection, Traffic Intercepting & Routing Process in Istio
- Upcoming networking changes in Istio 1.10
一点感想
如果用传统 Linux 网络运维的办法,去解决 Istio 简单实现下的网络问题,十分不直观和容易。在 Service Mesh 利用的同时,可察看性的工具和办法应该作出相应的变动。不然大规模应用后,问题的解决将破费相当大的代价。
其实,在可察看性方面,咱们曾经有所谓的 distributed tracing(全链路跟踪)
。为何不能 全链路跟踪 TCP 连贯的状态变动和事件源?如,是什么组件收回的 TCP RST/FIN/SYN。连贯的参与方是什么?影响是什么?
而这些事件源的采集上,能够利用 eBPF 等技术去捕捉连贯的重要事件。业界曾经有一些相似的开源实现。只是大家的器重水平未下来。
公司也好,业界也好,技术的演进大都是由解决问题来推动的,而很少是真正“设计”进去的。而要害的,可能是去发现变动和被动适应甚至利用变动。