Istio Ambient 模式使用

下载 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 出站流量的透明流量劫持流程如下:

  1. Istio CNI 在节点上创建 istioout 网卡和 iptables 规则,将 Ambient mesh 中的出站流量通过 Geneve 隧道透明劫持到 pistioout 虚拟网卡;
  2. ztunnel 中的 init 容器创建 iptables 规则,将 pistioout 网卡中的所有流量转发到 ztunnel 中的 Envoy 代理的 15001 端口;
  3. 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:/#

路由表将按顺序执行,第一列表示的是路由表的优先级,第二列表示要查找或跳转的路由表。 从上到下的顺序进行评估:

  1. 优先级为0, 匹配所有流量并将其发送到local表。
  2. 优先级为100, 匹配防火墙标记为0x200/0x200的流量,转到优先级为32766这条规则。
  3. 优先级为101, 匹配防火墙标记为0x100/0x100的流量, 将其发送到101路由表。
  4. 优先级为102, 匹配防火墙标记为0x40/0x40的流量, 将其发送到101路由表。
  5. 优先级为103, 匹配所有流量并将其发送到100路由表。
  6. 优先级为32766, 匹配任意源地址,查询main路由表转发
  7. 优先级为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 入站流量的透明流量劫持流程如下:

  1. Istio CNI 在节点上创建 istioin 网卡和 iptables 规则,将 Ambient mesh 中的 Pod IP 加入 IP 集,并通过 netfilter nfmark 标记和路由规则,将 Ambient mesh 中的出站流量通过 Geneve 隧道透明劫持到 pistioin 虚拟机网卡;
  2. ztunnel 中创建 iptables 规则,将 pistioin 网卡中的所有流量转发到 ztunnel 中的 Envoy 代理的 15008 端口;
  3. Envoy 对数据包进行处理后转发给 Pod B。

参考资料

Get Started with Istio Ambient Mesh

关于 Istio 推出 Ambient 数据平面模式

Istio Ambient 模式中的透明流量劫持四层网络路由路径详解

0%