Istio 1.21.0 版本 inpod ambient 模式源码解析
文章目录
版本说明
基于 istio 1.21.0 版本源代码,ambient 进行了大更新,从原来的主机网络命名空间中重定向更新为 in-Pod 网络命名空间重定向,解决了原有模式 Istio CNI 扩展的网络配置可能会和主流 CNI 实现的主机级网络配置互相干扰,导致流量中断和网络策略无法生效等问题,更新后理论将支持所有 CNI,经过实际测试,在 Flannel、Cilium 等网络 CNI 插件都能正常工作,详细参考 inpod 流量重定向 ambient 模式。
这里主要测试了在 cilium CNI 插件下,ambient 模式能够正常工作,并根据测试过程中的日志,从 cni 和 ztunnel 两个模块源码中分析 ambient 模式的实现细节。
部署
这里使用 k3s 集群来测试,因为 k3s 集群默认的 cni 插件是 flannel,路径为/var/lib/rancher/k3s/agent/etc/cni/net.d
,与 istio 中的默认的插件路径不一致,这里改为用 cilium cni 插件:
|
|
等 pods 起来后,使用下面的命令来部署 istio 和测试应用:
|
|
等网格所有服务 pods 启动后,部署测试应用,并测试在设置命名空间为 ambient 模式前后是否能正常请求:
|
|
cni 源码
为 pods 生成 iptables 规则
节点上的 istio-cni-node pods 会为在 ambient mesh 模式下的 pods 生成 iptables 规则,规则如下:
|
|
其中“169.254.7.127”为固定的 IP 地址,用来从 pod 内部可靠地识别 kubelet 健康探针。这些 iptable 规则,可以参考 istio 官网的两张图来理解:
设置 ambient 相关源码
在开启了“istio.io/dataplane-mode=ambient”标签的命名空间下,增加 pods 时会调用到以下代码:
|
|
这里通过函数 netnsRunner 来运行 CreateInpodRules 函数,会先把当前进程的网络命名空间 ns 切换到目标 pods 的 ns,然后执行 iptables 命令。执行完成后再调用 ztunnel 的 grpc 接口,通知 ztunnel 创建一个代理。
通过搜索看到,AddPodToMesh 这个函数在两个地方会调用,一个是 InformerHandlers 中,其通过 k8s informer 机制监听 pods 和命名空间的事件,在 pods 新增和更新事件中调用 AddPodToMesh 设置 iptables 规则:
|
|
另一个是 CniPluginServer,会在 cni 插件的 socket 地址“/var/run/istio-cni/pluginevent.sock” 监听事件,当有事件发生时,会调用 AddPodToMesh 设置 iptables 规则:
|
|
ztunnel 源码
在 ztunnel 中,收到 cni 发送的创建代理信息后,其处理日志为:
|
|
ztunnel 会创建 4 个监听端口,分别是 15008、15006、15001、15080。其中 15008 和 15006 用于入口流量,15001 用于出口流量,15080 用于 socks5 代理。入向 15008 的相关源码如下:
|
|
new_proxies_from_factory 函数逻辑如下,主要是调用 Proxy::from_inputs 函数来生成的:
|
|
这里看其中一个端口 15008 代理的逻辑,其初始化代码如下:
|
|
看下这里使用的 tcp_bind 函数实现逻辑:
|
|
最终执行到 netns.run(f) 这里,其代码如下,也在把当前进程的网络命名空间 ns 切换到目标 pods 的 ns,然后执行 f 函数,f 函数中会创建监听端口:
|
|
参考
文章作者 yefengzhichen
上次更新 2024-04-08