Table of Contents

1准备

1.1测试环境

1.2容器网和 nsenter

1.3验证基本连接

2个出口:Pod->主机-> VPC网络

2.1容器内部网络

1.2 Veth对连接到主机

1.3出口BPF代码

1.4主机路由表

2入口

2.1主机路由表

2.2入口BPF代码

2.3集装箱收货

3小结

参考文献

相关阅读


发表于2019-10-26 | 最后更新2019-10-26

这篇文章探讨了在AWS上由Cilium驱动的K8S集群中两个跨主机Pod之间的网络拓扑流量路径。我们将使用普通的Linux命令来完成此任务。在这篇文章的结尾,我们将获得如下图片:

1准备

1.1测试环境

我们有两个K8S主机:

  • 节点1: 10.5.2.48
  • 节点2: 10.5.2.58

和两个豆荚:

  • 节点110.5.2.11上的pod1
  • 10.5.2.22node2上的pod2

节点和Pod在同一VPC中,带有VPC网关10.5.2.1

注意:出于安全原因以及易于理解,我用伪造的IP / MAC地址代替了真实的IP / MAC地址。这不应破坏此职位的意义。

1.2容器网和 nsenter

我们将使用nsenter工具工具在主机上容器的网络名称空间中执行命令,格式为:

$ nsenter -t <pid> -n <command>

哪里,

  • -t <pid>:目标过程 <pid>
  • -n:输入网络名称空间
  • <command>:执行命令

这等效于docker exec <container> <command>,但比后者更灵活,因为通常缺少网络工具或容器内部没有特权,因此在主机上执行命令没有此限制。

获取容器进程ID:

root@node1 # docker inspect 04d740a33726 | grep Pid"Pid": 75869,

75869就是pid我们想要的。

1.3验证基本连接

从pod1 ping pod2,确保其可访问:

root@node1 # nsenter -t 75869 -n ping 10.5.2.22 -c 2
64 bytes from 10.5.2.22: icmp_seq=1 ttl=61 time=0.248 ms
64 bytes from 10.5.2.22: icmp_seq=2 ttl=61 time=0.208 ms

好!接下来,我们将探索这些数据包的确切路径,即网络设备,路由表,arp表,BPF挂钩。

2个出口:Pod->主机-> VPC网络

2.1容器内部网络

从pod1开始我们的旅程。检查pod1内的网络设备:

root@node1 # nsenter -t 75869 -n ip a
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN qlen 1000...
42: eth0@if43: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 9001 qdisc noqueue state UPlink/ether ee:14:d3:9a:62:42 brd ff:ff:ff:ff:ff:ff link-netnsid 0inet 10.5.2.11/32 brd 10.5.2.11 scope global eth0

可以看出,它具有一个loopbak接口lo和一个eth0 IP地址为IP的网络接口10.5.2.11

请注意42: eth0@if43,此特殊符号表示eth0具有 ifindex编号42,并且设备带有ifindex 4243 组成veth对。这ifindex在主机(在本例中为node1)中是唯一的,稍后我们将再次看到。

接下来,检查容器内的路由表:

root@node1 # nsenter -t 75869 -n route -n
Kernel IP routing table
Destination     Gateway         Genmask         Flags Metric Ref    Use Iface
0.0.0.0         10.5.2.191   0.0.0.0         UG    0      0        0 eth0
10.5.1.191   0.0.0.0         255.255.255.255 UH    0      0        0 eth0

可以看出,该Pod的网关为10.5.1.191,所有出口流量都将转发到该网关。在主机上查找网关:

root@node1 # ip a | grep 10.5.2.191 -B 2
31: cilium_host@cilium_net: <...> mtu 9001 ... qlen 1000link/ether 0a:ee:d6:5f:6c:32 brd ff:ff:ff:ff:ff:ffinet 10.5.2.191/32 scope link cilium_host

我们可以看到容器网关是由device持有的cilium_host。其实 cilium_hostcilium_net撰写另一VETH对,他们都对主机的网络空间,并将于纤毛代理开始创建。

接下来,检查容器内的ARP表:

root@node1 # nsenter -t 75869 -n arp -n
Address                  HWtype  HWaddress           Flags Mask            Iface
10.5.2.191            ether   86:05:d4:99:a9:f5   C                     eth0
10.5.2.48             ether   86:05:d4:99:a9:f5   C                     eth0

可以看出,容器的网关和主机IP都指向相同的MAC地址86:05:d4:99:a9:f5。让我们进一步确定哪个设备拥有该地址。

可以看出,容器的网关和主机IP都指向相同的MAC地址86:05:d4:99:a9:f5。让我们进一步确定哪个设备拥有该地址。

1.2 Veth对连接到主机

root@node1 # ip link | grep 86:05:d4:99:a9:f5 -B 1
43: lxc050ba70e11a8@if42: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 9001 qdisc ... qlen 1000link/ether 86:05:d4:99:a9:f5 brd ff:ff:ff:ff:ff:ff link-netnsid 1

而已!设备lxc050ba70e11a8持有它。请注意43: lxc050ba70e11a8@if42符号,并回想一下容器的eth0实际持有ifindex=42,因此我们现在确保:

  1. pod1通过veth对(if42 <--> if43或名称表示eth0 <--> lxc050ba70e11a8)连接到主机
  2. Pod中的默认网关指向cilium_host主机上的设备
  3. Pod生成流量的下一个L3跃点是 cilium_host
  4. Pod产生流量的下一个L2跳是第ve对(lxc050ba70e11a8)的主机端

这正是Pod出口流量从容器流向主机的方式。

1.3出口BPF代码

Cilium的强大功能之一是动态流量操纵。它通过利用BPF来实现。关于此主题的详细说明不在本文的范围之内,如果您有兴趣的话,请参阅官方文档《BPF和XDP参考指南》( 如果您可以阅读中文,请参阅我的 翻译)。

Cilium使用tcBPF过滤容器的进出流量。让我们看一下出口部分:

root@node1:~  # tc filter show dev lxc050ba70e11a8 egress
filter protocol all pref 1 bpf
filter protocol all pref 1 bpf handle 0x1 bpf_lxc.o:[from-container] direct-action not_in_hw tag db59e2ea8177ded3

注意:如果以上命令的输出未显示该 bpf_lxc.o:[from-container] direct-action not_in_hw tag db59e2ea8177ded3 信息,则可能是您的iproute2软件包太旧了,请尝试升级到新版本。

列出此主机(节点1)上所有已加载的BPF程序:

root@node1:~  # bpftool prog
288: sched_cls  tag a390cb0eda39ede9loaded_at Oct 22/10:48  uid 0xlated 808B  jited 637B  memlock 4096B  map_ids 182,169
...
294: sched_cls  tag 596c1921e0319e72loaded_at Oct 22/10:48  uid 0xlated 176B  jited 157B  memlock 4096B
297: sched_cls  tag db59e2ea8177ded3loaded_at Oct 22/10:48  uid 0xlated 19144B  jited 11706B  memlock 20480B  map_ids 285,169,171,286,287,172,277,183,283,173,179,167,180

让我们进一步了解BPF代码/规则是什么样的。转储解释的BPF代码:

root@node1:~  # bpftool prog dump xlated id 2970: (bf) r6 = r11: (b7) r7 = 02: (63) *(u32 *)(r6 +60) = r73: (63) *(u32 *)(r6 +56) = r74: (63) *(u32 *)(r6 +52) = r75: (63) *(u32 *)(r6 +48) = r76: (63) *(u32 *)(r6 +64) = r77: (18) r2 = 0xffffff5a9: (79) r1 = *(u64 *)(r6 +80)10: (79) r8 = *(u64 *)(r6 +216)...

转储JITed BPF代码:

root@node1:~  # bpftool prog dump jited id 2970:   push   %rbp1:   mov    %rsp,%rbp4:   sub    $0x228,%rspb:   sub    $0x28,%rbpf:   mov    %rbx,0x0(%rbp)13:   mov    %r13,0x8(%rbp)17:   mov    %r14,0x10(%rbp)1b:   mov    %r15,0x18(%rbp)1f:   xor    %eax,%eax21:   mov    %rax,0x20(%rbp)...

好的,无需进一步挖掘。如果出口流量没有被BPF代码/规则丢弃,它将到达主机,主机路由设施将对其进行处理。

1.4主机路由表

查看主机路由表:

root@node1:~  # ip rule list
9:      from all fwmark 0x200/0xf00 lookup 2004
100:    from all lookup local
32766:  from all lookup main
32767:  from all lookup default

我们看到,有4个路由表:2004localmaindefault。检查每个内容:

root@node1:~  # ip route show table 2004
local default dev lo scope hostroot@node1 $ ip route show table main
default via 10.5.2.1 dev eth0
10.5.2.0/24 dev eth0 proto kernel scope link src 10.5.2.48

来自Pod1的出口流量将到达main桌面。

注意:更具体地说,Pod IP是从ENI分配的,每个ENI都有自己的路由表以用于出口流量。在我的情况下,Pod1的IP来自节点1的默认ENI(eth0),因此流量将到达main表中。如果您有多个ENI,则此处的路由应该有所不同。

main路由表也是节点1的默认路由表(不要”由误导default表上方,它只是一个名称表default,而不是主机的默认表)。

node1的默认网关为10.5.2.1(VPC网关)。因此,pod1的出口流量最终将被发送到VPC网关。

这样就完成了我们的交通旅程的出口部分。

2入口

如果VPC网络将流量正确路由到Node2(供应商的责任),则这些数据包将到达Node2的相应ENI。让我们来看看如何处理这些数据包。

2.1主机路由表

root@node2:~  # ip rule list
9:      from all fwmark 0x200/0xf00 lookup 2004
100:    from all lookup local
32766:  from all lookup main
32767:  from all lookup default
root@node2:~  # ip route show table 2004
local default dev lo scope hostnode2 $ ip route show table main
default via 10.5.1.1 dev eth0
10.5.2.22 dev lxcd86fc95bf974 scope link
...

可以看出,Pod2有一条专用的路由:

10.5.2.22 dev lxcd86fc95bf974 scope link

这意味着所有发10.5.2.22往的流量都将转发到 lxcd86fc95bf974

2.2入口BPF代码

Cilium将lxcxx为其创建的每个设备注入入口BPF规则。让我们检查一下这个:

root@node2:~  # tc filter show dev lxcd86fc95bf974 ingress
filter protocol all pref 1 bpf
filter protocol all pref 1 bpf handle 0x1 bpf_lxc.o:[from-container] direct-action not_in_hw tag c17fab4b3f874a54

如果您对确切的BPF代码感兴趣,那么以下步骤与我们之前的出口部分大致相同:

root@node2:~  # bpftool prog
156: sched_cls  tag a390cb0eda39ede9loaded_at Oct 22/10:59  uid 0xlated 808B  jited 637B  memlock 4096B  map_ids 46,33
...
165: sched_cls  tag c17fab4b3f874a54loaded_at Oct 22/10:59  uid 0xlated 19144B  jited 11706B  memlock 20480B  map_ids 155,33,35,156,157,36,147,47,153,37,43,31,44root@node2:~  # bpftool prog dump xlated id 165 | head -n 100: (bf) r6 = r11: (b7) r7 = 02: (63) *(u32 *)(r6 +60) = r73: (63) *(u32 *)(r6 +56) = r74: (63) *(u32 *)(r6 +52) = r75: (63) *(u32 *)(r6 +48) = r76: (63) *(u32 *)(r6 +64) = r77: (18) r2 = 0xffffff5a9: (79) r1 = *(u64 *)(r6 +80)10: (79) r8 = *(u64 *)(r6 +216)

2.3集装箱收货

如果流量没有被Cilium网络策略规则(入口BPF)丢弃,则数据包将通过主机端的veth对,并最终到达 eth0内部容器-我们旅程的最终目的地。

现在在这里重新描述全局数据流图:

3小结

这篇文章探讨了AWS上由Cilium驱动的K8S集群中两个Pod之间的主机间流量网络拓扑数据流。我们使用了常见的Linux命令行工具来完成此任务。希望对您有帮助!

参考文献

  1. Cilium:BPF和XDP参考指南
  2. Cilium:AWS ENI
  3. Cilium:AWS ENI数据路径

相关阅读


《深入理解 Cilium 的 eBPF(XDP)收发包路径:数据包在Linux网络协议栈中的路径》

《iptables详解(1):iptables概念》

《iptables详解(2):路由表》

《eBPF.io eBPF文档:扩展的数据包过滤器(BPF)》

《介绍Calico eBPF数据平面:Linux内核网络、安全性和跟踪(Kubernetes、kube-proxy)》

《Linux eBPF和XDP高速处理数据包;使用EBPF编写XDP网络过滤器;高性能ACL》

《深入理解 Cilium 的 eBPF 收发包路径》

《Understanding (and Troubleshooting) the eBPF Datapath in Cilium》

《kubernetes(K8s):管理云平台中多个主机上的容器化的应用》

AWS上的Cilium网络拓扑和流量路径相关推荐

  1. AWS — AWS 上的 5G 网络及 MEC 边缘计算商业案例

    目录 文章目录 目录 AWS 与 Verizon 推出的 Private MEC AWS 与 Vodafone Business 合作推出 MEC 解决方案 AWS.ERICSSON 与 Telefo ...

  2. AWS — AWS 上的 5G 网络切片

    目录 文章目录 目录 5G 网络切片 AWS 上的 5G 网络切片 Native Solution Cloudify Solution 使用 Cloudify Catalog 作为管理 NSI 的一个 ...

  3. AWS — AWS 上的 5G 网络

    目录 文章目录 目录 AWS 上的 E2E 5G 网络 AWS 上的 5G Core Network Service Based Architecture CP 的高可用部署 UP 的多网络平面 St ...

  4. 无浮动IP的虚机出公网流量路径

    女主宣言 通过Neutron构建网络时涉及的知识点比较广,虚拟化网络实施上又具有非常大的灵活性,这往往会让刚接触的同学摸不着头脑.本文特意对"无浮动IP的虚机出公网流量路径"这一场 ...

  5. AWS — AWS 上的 DevOps

    目录 文章目录 目录 AWS 上的 DevOps AWS 上的 DevOps 在 AWS 上部署 5G 网络的好处之一是,用户可以根据需要,使用一系列的 AWS DevOps 开发者工具集来轻松快速地 ...

  6. 端口镜像 流量过滤_在 AWS 云环境中滥用 VPC 流量镜像抓取网络流量

    云环境下的网络检测问题 人们可能希望监视云环境中的网络流量有很多原因--出于攻击和防御的目的.被动的网络检查在云环境中可能很困难,而且在这之前需要对网络配置进行重大修改,以确保每台主机都被监控,并且不 ...

  7. 想做网上线上引流怎么做?如何通过网络获取流量?

    想做网上线上引流怎么做?如何通过网络获取流量? 现在很多人都在问关于"引流"."流量"的问题,对于这些问题实际上背后的道理都是一样的,我们需要了解的是: &qu ...

  8. Cilium网络概述

    K8s已经成为一线大厂分布式平台的标配技术.你是不是还在惆怅怎么掌握它?来这里,大型互联网公司一线工程师亲授,不来虚的,直接上手实战,3天时间带你搭建K8s平台,快速学会K8s,点击下方图片可了解培训 ...

  9. 最强 CNI 基准测试:Cilium 网络性能分析

    作者:Thomas Graf 译者:罗煜.张亮,均来自 KubeSphere 团队 Thomas Graf 是 Cilium 的联合创始人,同时也是 Cilium 母公司 Isovalent[1] 的 ...

最新文章

  1. hihoCoder #1142 : 三分求极值
  2. python 之三级菜单
  3. linux ar 命令详解
  4. openwrt x86 登录不上_求助,关于OpenWRT外接硬盘不识别的问题
  5. JUnit 5 Alpha版本简化了单元测试
  6. 清华大学操作系统OS学习(十二)——信号量与管程
  7. DPDK - flow Haripin
  8. 通过银行卡号获取银行名称和银行图标的ICON
  9. C++死锁与哲学家就餐问题
  10. 走火入魔的macfans,披着mac皮的ubuntu macbuntu安装指南
  11. 项目如行军——《孙子兵法》之九地篇
  12. 亲爱的,60句感人歌词,有没有一句触动了你
  13. 大厂软件测试流程完整版
  14. TSV文件与CSV文件的区别
  15. vue项目将px转为rem实践
  16. socketDemo套接字
  17. SpringBoot物流管理项目(源码下载)
  18. Android animation呼吸动画 心形动画
  19. CSSAPP稀里糊涂的读书笔记(一)计算机系统漫游
  20. 项目管理工具之apizza

热门文章

  1. ORA-01034: ORACLE not available
  2. SPSS 限制检索个案
  3. Netty 编解码器和 Handler 调用机制
  4. vue中的状态管理 vuex store
  5. python写exploit采集器
  6. [转载]如何做一个出色的程序员
  7. 3 - Spring AOP
  8. 输入法中的全角和半角是什么,角又是什么
  9. linux 启动tomcat 怎么显示日志文件,随着LINUX的启动,打开一个终端显示TOMCAT的日志文件,请问如何做到?...
  10. linux修改ip dhcp,Linux下在静态IP与动态DHCP之间切换的脚本