下载 Ambient Mesh 预览版
1
curl -L https://istio.io/downloadIstio | ISTIO_VERSION = 1.18.0-alpha.0 TARGET_ARCH = x86_64 sh -
利用 kind 创建 k8s 集群
1
2
3
4
5
6
7
8
9
kind create cluster --config= - <<EOF
kind: Cluster
apiVersion: kind.x-k8s.io/v1alpha4
name: ambient
nodes:
- role: control-plane
- role: worker
- role: worker
EOF
注意kind 安装的k8s版本大于等于 1.23
安装 Ambient profile
1
istioctl install --set profile = ambient --skip-confirmation
部署应用
1
2
3
kubectl apply -f samples/bookinfo/platform/kube/bookinfo.yaml
kubectl apply -f samples/sleep/sleep.yaml
kubectl apply -f samples/sleep/notsleep.yaml
default 名称空间开启 Ambient Mesh
1
kubectl label namespace default istio.io/dataplane-mode= ambient
流量劫持
Outbound 流量劫持
Ambient mesh 的 pod 出站流量的透明流量劫持流程如下:
Istio CNI 在节点上创建 istioout 网卡和 iptables 规则,将 Ambient mesh 中的出站流量通过 Geneve 隧道透明劫持到 pistioout 虚拟网卡; ztunnel 中的 init 容器创建 iptables 规则,将 pistioout 网卡中的所有流量转发到 ztunnel 中的 Envoy 代理的 15001 端口; Envoy 对数据包进行处理,并与上游端点建立 HBONE 隧道(HTTP CONNECT),将数据包转发到上游 Worknode 节点路由
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
# iptables-save |grep ztunnel
:ztunnel-FORWARD - [ 0:0]
:ztunnel-INPUT - [ 0:0]
:ztunnel-OUTPUT - [ 0:0]
:ztunnel-POSTROUTING - [ 0:0]
:ztunnel-PREROUTING - [ 0:0]
-A PREROUTING -j ztunnel-PREROUTING
-A INPUT -j ztunnel-INPUT
-A FORWARD -j ztunnel-FORWARD
-A OUTPUT -j ztunnel-OUTPUT
-A POSTROUTING -j ztunnel-POSTROUTING
-A ztunnel-FORWARD -m mark --mark 0x220/0x220 -j CONNMARK --save-mark --nfmask 0x220 --ctmask 0x220
-A ztunnel-FORWARD -m mark --mark 0x210/0x210 -j CONNMARK --save-mark --nfmask 0x210 --ctmask 0x210
-A ztunnel-INPUT -m mark --mark 0x220/0x220 -j CONNMARK --save-mark --nfmask 0x220 --ctmask 0x220
-A ztunnel-INPUT -m mark --mark 0x210/0x210 -j CONNMARK --save-mark --nfmask 0x210 --ctmask 0x210
-A ztunnel-OUTPUT -s 10.244.1.1/32 -j MARK --set-xmark 0x220/0xffffffff
-A ztunnel-PREROUTING -i istioin -j MARK --set-xmark 0x200/0x200
-A ztunnel-PREROUTING -i istioin -j RETURN
-A ztunnel-PREROUTING -i istioout -j MARK --set-xmark 0x200/0x200
-A ztunnel-PREROUTING -i istioout -j RETURN
-A ztunnel-PREROUTING -p udp -m udp --dport 6081 -j RETURN
-A ztunnel-PREROUTING -m connmark --mark 0x220/0x220 -j MARK --set-xmark 0x200/0x200
-A ztunnel-PREROUTING -m mark --mark 0x200/0x200 -j RETURN
-A ztunnel-PREROUTING ! -i vethecd818c1 -m connmark --mark 0x210/0x210 -j MARK --set-xmark 0x40/0x40
-A ztunnel-PREROUTING -m mark --mark 0x40/0x40 -j RETURN
-A ztunnel-PREROUTING ! -s 10.244.1.9/32 -i vethecd818c1 -j MARK --set-xmark 0x210/0x210
-A ztunnel-PREROUTING -m mark --mark 0x200/0x200 -j RETURN
-A ztunnel-PREROUTING -i vethecd818c1 -j MARK --set-xmark 0x220/0x220
-A ztunnel-PREROUTING -p udp -j MARK --set-xmark 0x220/0x220
-A ztunnel-PREROUTING -m mark --mark 0x200/0x200 -j RETURN
-A ztunnel-PREROUTING -p tcp -m set --match-set ztunnel-pods-ips src -j MARK --set-xmark 0x100/0x100
:ztunnel-POSTROUTING - [ 0:0]
:ztunnel-PREROUTING - [ 0:0]
-A PREROUTING -j ztunnel-PREROUTING
-A POSTROUTING -j ztunnel-POSTROUTING
-A PREROUTING -m comment --comment "kubernetes service portals" -j KUBE-SERVICES
-A ztunnel-POSTROUTING -m mark --mark 0x100/0x100 -j ACCEPT
-A ztunnel-PREROUTING -m mark --mark 0x100/0x100 -j ACCEPT
PREROUTING
链最先运行,所有数据包将转进入到 ztunnel-PREROUTING
ztunnel-PREROUTING
进行一系列打标操作 1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
# iptables -t nat -nL
Chain PREROUTING ( policy ACCEPT)
target prot opt source destination
ztunnel-PREROUTING all -- 0.0.0.0/0 0.0.0.0/0
Chain INPUT ( policy ACCEPT)
target prot opt source destination
Chain OUTPUT ( policy ACCEPT)
target prot opt source destination
Chain POSTROUTING ( policy ACCEPT)
target prot opt source destination
ztunnel-POSTROUTING all -- 0.0.0.0/0 0.0.0.0/0
/* 此处省略 kubernetes 和 docker 的规则 */
Chain ztunnel-POSTROUTING ( 1 references)
target prot opt source destination
ACCEPT all -- 0.0.0.0/0 0.0.0.0/0 mark match 0x100/0x100
Chain ztunnel-PREROUTING ( 1 references)
target prot opt source destination
ACCEPT all -- 0.0.0.0/0 0.0.0.0/0 mark match 0x100/0x100
通过执行以上 iptables 规则,可以确保 Ambient Mesh 仅拦截 ztunnel-pods-ips IP 集 Pod 中的数据包并给数据包打上 0x100/0x100 标记,而不影响其他 Pod。
1
2
3
4
5
6
7
8
9
10
11
12
13
root@ambient-worker2:/# ip rule
0: from all lookup local
100: from all fwmark 0x200/0x200 goto 32766
101: from all fwmark 0x100/0x100 lookup 101
102: from all fwmark 0x40/0x40 lookup 102
103: from all lookup 100
32766: from all lookup main
32767: from all lookup default
root@ambient-worker2:/# ip route show table 101
default via 192.168.127.2 dev istioout
10.244.1.9 dev vethecd818c1 scope link
root@ambient-worker2:/#
路由表将按顺序执行,第一列表示的是路由表的优先级,第二列表示要查找或跳转的路由表。
从上到下的顺序进行评估:
优先级为0, 匹配所有流量并将其发送到local表。 优先级为100, 匹配防火墙标记为0x200/0x200的流量,转到优先级为32766这条规则。 优先级为101, 匹配防火墙标记为0x100/0x100的流量, 将其发送到101路由表。 优先级为102, 匹配防火墙标记为0x40/0x40的流量, 将其发送到101路由表。 优先级为103, 匹配所有流量并将其发送到100路由表。 优先级为32766, 匹配任意源地址,查询main路由表转发 优先级为32767, 匹配任意源地址,查询default路由表转发 可以看到所有带有 0x100/0x100 标记的数据包将查找 101 路由表;查看101路由表,可以看到 101 路由表中带有关键字 via ,这表示数据包将通过网关传输 。所有数据包被通过 istioout 网卡发送到网关(IP 是 192.168.127.2)
ztunnel 路由
利用nsenter进入容器
1
2
root@ambient-worker:/# pid = $( ps -ef | grep ztunnel| grep -v grep| awk '{print $2}' )
root@ambient-worker:/# nsenter --target ${ pid } --mount --uts --ipc --net --pid
进入 Ztunnel Pod,使用 ip -d a 命令检查它的网卡信息
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
# ip a
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1000
link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
inet 127.0.0.1/8 scope host lo
valid_lft forever preferred_lft forever
inet6 ::1/128 scope host
valid_lft forever preferred_lft forever
2: tunl0@NONE: <NOARP> mtu 1480 qdisc noop state DOWN group default qlen 1000
link/ipip 0.0.0.0 brd 0.0.0.0
3: ip6tnl0@NONE: <NOARP> mtu 1452 qdisc noop state DOWN group default qlen 1000
link/tunnel6 :: brd :: permaddr 468f:aa5f:366a::
4: eth0@if7: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP group default
link/ether 22:50:e4:49:5a:cd brd ff:ff:ff:ff:ff:ff link-netnsid 0
inet 10.244.2.5/24 brd 10.244.2.255 scope global eth0
valid_lft forever preferred_lft forever
inet6 fe80::2050:e4ff:fe49:5acd/64 scope link
valid_lft forever preferred_lft forever
5: pistioin: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1450 qdisc noqueue state UNKNOWN group default
link/ether 06:57:d7:62:d9:59 brd ff:ff:ff:ff:ff:ff
inet 192.168.126.2/30 brd 192.168.126.3 scope global pistioin
valid_lft forever preferred_lft forever
inet6 fe80::457:d7ff:fe62:d959/64 scope link
valid_lft forever preferred_lft forever
6: pistioout: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1450 qdisc noqueue state UNKNOWN group default
link/ether de:f1:1f:2b:a0:d1 brd ff:ff:ff:ff:ff:ff
inet 192.168.127.2/30 brd 192.168.127.3 scope global pistioout
valid_lft forever preferred_lft forever
inet6 fe80::dcf1:1fff:fe2b:a0d1/64 scope link
valid_lft forever preferred_lft forever
其中有两个网卡:
pistioin :IP 为 192.168.126.2 pistioout:IP 为 192.168.127.2 关于 pistioin 和 pistioout 网卡
这两个网卡都是由 ztunnel 中创建的 Geneve 类型的虚拟网卡
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
# iptables-save
/* 此处省略 */
-A PREROUTING -i pistioin -p tcp -m tcp --dport 15008 -j TPROXY --on-port 15008 --on-ip 127.0.0.1 --tproxy-mark 0x400/0xfff
-A PREROUTING -i pistioout -p tcp -j TPROXY --on-port 15001 --on-ip 127.0.0.1 --tproxy-mark 0x400/0xfff
-A PREROUTING -i pistioin -p tcp -j TPROXY --on-port 15006 --on-ip 127.0.0.1 --tproxy-mark 0x400/0xfff
-A PREROUTING ! -d 10.244.2.5/32 -i eth0 -p tcp -j MARK --set-xmark 0x4d3/0xfff
COMMIT
# Completed on Wed Mar 29 07:01:06 2023
查看 Ztunnel A 中的路由表
# ip rule
0: from all lookup local
20000: from all fwmark 0x400/0xfff lookup 100
20003: from all fwmark 0x4d3/0xfff lookup 100
32766: from all lookup main
32767: from all lookup default
# ip route show table 100
local default dev lo scope host
看到所有标记 0x400/0xfff 和 0x4d3/0xfff 的数据包应用 100 路由表,查看该路由表详情,可以看到这是一条本地路由,数据包发送到本地的回环网卡,即 127.0.0.1
Inbound 流量劫持
Ambient 模式的入站流量劫持与出站流量类似,同样使用 tproxy 和 HBONE 实现透明流量劫持。
Ambient mesh 的 pod 入站流量的透明流量劫持流程如下:
Istio CNI 在节点上创建 istioin 网卡和 iptables 规则,将 Ambient mesh 中的 Pod IP 加入 IP 集,并通过 netfilter nfmark 标记和路由规则,将 Ambient mesh 中的出站流量通过 Geneve 隧道透明劫持到 pistioin 虚拟机网卡; ztunnel 中创建 iptables 规则,将 pistioin 网卡中的所有流量转发到 ztunnel 中的 Envoy 代理的 15008 端口; Envoy 对数据包进行处理后转发给 Pod B。 参考资料
Get Started with Istio Ambient Mesh
关于 Istio 推出 Ambient 数据平面模式
Istio Ambient 模式中的透明流量劫持四层网络路由路径详解