Istio 端口 与 组件#

Istio 的每个组件都监听一堆端口。对于初学者,可能很难弄明白每个端口的作用。这里,用 图:Istio 端口与组件 说明 Istio 在默认的部署下,各组件的通讯端口和相关的功能。

Istio端口与组件

图:Istio 端口与组件#

用 Draw.io 打开

上图需要说明的是:

  • 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 应用的同时,可观察性的工具和方法应该作出相应的变化。不然大规模使用后,问题的解决将花费相当大的代价。