Istio 端口 与 组件#
Istio 的每个组件都监听一堆端口。对于初学者,可能很难弄明白每个端口的作用。这里,用 图:Istio 端口与组件 说明 Istio 在默认的部署下,各组件的通讯端口和相关的功能。
图:Istio 端口与组件#
上图需要说明的是:
istio-proxy 容器与 应用容器(app container) 共享同一 Linux
network namespace
。network namespace
是内核内用于隔离多个不同网络配置的技术。其中一个配置就是 netfilter,即我们常说的 iptables。我们将在后面说说它的故事。
监听端口#
可以用以下方式查看监听的端口:
$ 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
连接#
图:Istio 端口与组件 中包含了一些在 Istio 中时行 pod 内部的 TCP 连接的说明(见其中的 ss
命令输出)。在此不再赘述。
运维杂项#
抓包#
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
神奇的 127.0.0.6#
出于非常多的原因,inbound 流量在由 Envoy 转到 app 时,Envoy 建立的 TCP 连接 bind 的 ip 地址是一个ip addr
也查不到的,在 lo
接口上的 127.0.0.6
。如果你好奇,可以看:
一点感想#
如果用传统 Linux 网络运维的方法,去解决 Istio 复杂实现下的网络问题,非常不直观和容易。在 Service Mesh 应用的同时,可观察性的工具和方法应该作出相应的变化。不然大规模使用后,问题的解决将花费相当大的代价。