Native Routing
除了 overlay 的 vxlan 和 geneve ,通过支持 native routing 模式,L2 层直接互通可以直接使用,否则可以利用 bgp 等协议进行打通。
部署
修改配置
kubectl edit cm cilium-config -n kube-system
auto-direct-node-routes: "true"
ipv4-native-routing-cidr: 10.0.0.0/16 // 需要本地路由的地址段
tunnel: disabled // 关掉 tunnel
检查
# ip r
default via 172.18.22.1 dev ens3 proto static metric 101
10.0.0.0/24 via 10.0.0.161 dev cilium_host src 10.0.0.161
10.0.0.161 dev cilium_host scope link
10.0.1.0/24 via 192.168.100.112 dev ens10 // 到其他节点 pod 网段的路由
10.0.2.0/24 via 192.168.100.113 dev ens10
172.18.22.0/24 dev ens3 proto kernel scope link src 172.18.22.111 metric 101
192.168.100.0/24 dev ens10 proto kernel scope link src 192.168.100.111 metric 100
pod 到 同节点,跨节点 pod
同节点 pod 到 node
Pod 1<-> node111
10.0.0.225 <-> 172.18.22.111
Pod veth pair host 侧 ingress from-container
函数流程
|-cil_from_container
|-tail_handle_ipv4
|-__tail_handle_ipv4
|-->invoke_tailcall_if
...// svc 的查询等。
|-tail_handle_ipv4_cont // 根据 TAIL_CT_LOOKUP4,上一章节有介绍
|-handle_ipv4_from_lxc
|--> lookup_ip4_remote_endpoint // 根据目的 IP 从 IPCACHE map 找 endpoint
// 172.18.22.111/32 identity=1 encryptkey=0 tunnelendpoint=0.0.0.0 nodeid=0
// dst_id = 1
|--> lookup_ip4_endpoint // 根据目的 IP 从 ENDPOINTS_MAP 找 endpoint
// 172.18.22.111:0 (localhost)
|- redirect_ep // redirect HOST_IFINDEX flag BPF_F_INGRESS 到宿主机
回包 host -> pod
根据路由 10.0.0.0/24 via 10.0.0.161 dev cilium_host src 10.0.0.161 ,到 本地 pod 的流量会命中 cilium_host egress hook,即
from-host
|-cil_from_host
|-handle_netdev
|- do_netdev
|-->ep_tail_call(ctx, CILIUM_CALL_IPV4_FROM_HOST);
|-tail_handle_ipv4_from_host
|-tail_handle_ipv4
|-handle_ipv4
|->rewrite_dmac_to_host // 写目的 mac, cilium_net 的 mac
|->ep = lookup_ip4_endpoint(ip4); // 根据目的 mac 查 endpoint 10.0.0.225:0 id=213 flags=0x0000 ifindex=13 mac=72:15:17:10:C5:1C nodemac=5E:A1:FC:9D:FE:E5
|-ipv4_local_delivery // 本地 endpoint 进行处理
|-ipv4_l3 // 设置 ttl,mac,源 mac 为 ep->node_mac, 目的 mac 为 ep->mac, 即 veth 的两侧
|-redirect_ep // redirect 到 netns 里处理
跨节点 pod 到 node
Pod veth pair host 侧 ingress from-container
和上面流程相同,
在 lookup_ip4_remote_endpoint 时,获取到对面 node 的 ip
192.168.100.112/32 identity=6 encryptkey=0 tunnelendpoint=0.0.0.0 nodeid=0
在 ep = lookup_ip4_endpoint(ip4) 时,获取不到 endpoint,因为不是本地 endpoint
|- redirect_direct_v4
|- ipv4_l3 设置 ttl
|-> return CTX_ACT_OK 内核协议栈继续处理
内核协议栈根据路由表 192.168.100.0/24 dev ens10 proto kernel scope link src 192.168.100.111 metric 100,进行协议栈处理,将源 mac 该为 本地 ens10 的 mac,目的 mac 为对端 ens10 mac
ens10 出包挂载程序 to-netdev,未有什么动作
回包
收包后本地处理回包,根据路由 10.0.0.0/24 via 172.18.22.111 dev ens3,通过 ens3 网络通信,pod 所在节点 ens3 ingress
hook from-netdev
|-cil_from_host
|-handle_netdev
|- do_netdev
|-identity = resolve_srcid_ipv4() // 从 ctx 中提取 src identity
|-> lookup_ip4_remote_endpoint(ip4->saddr);
|-ctx_store_meta(ctx, CB_SRC_IDENTITY, identity); // 将 identity 存储到 ctx->cb[CB_SRC_IDENTITY]
|-->ep_tail_call(ctx, CILIUM_CALL_IPV4_FROM_NETDEV); //宏 CILIUM_CALL_IPV4_FROM_LXC
|-tail_handle_ipv4_from_netdev
|-tail_handle_ipv4
|-handle_ipv4
|-lookup_ip4_endpoint // 通过目的地址查询 endpoint
|->ipv4_local_delivery
|- ipv4_l3 // 写 ttl 和 mac
|-> tail_call_dynamic // 直接 tail endpoint BPF 这里是 to-container
|- to-container
|- handle_to_container
|-inherit_identity_from_host(skb, &identity)
|-tail_ipv4_to_endpoint
|-ipv4_policy
|- redirect_ep // 到 pod
跨节点 pod 到 pod
Pod veth pair host 侧 ingress from-container
和上面流程相同
在 lookup_ip4_remote_endpoint 时,获取到对面 pod 的 ip
10.0.1.230/32 identity=4502 encryptkey=0 tunnelendpoint=172.18.22.112 nodeid=797
在 ep = lookup_ip4_endpoint(ip4) 时,获取不到 endpoint,因为不是本地 endpoint
|- redirect_direct_v4
|- ipv4_l3 设置 ttl
|-> 处理根据 ENABLE_SKIP_FIB,如果 true,redirect_neigh,如果 false ,下一跳到系统路由网卡
目标节点网卡的 ingress 处理跟 上面一样