Kubernets(k8s) 网络原理三:同主机内Pod相互访问

前两篇文章中我们介绍了pod怎么和宿主机通信以及pod怎么访问外网,这两种通信是理解pod间通信的基础。

关于pod间的相互访问,这里还需要细化一下。回想一下pod在k8s节点中的分布,两个pod可能分布在同一台宿主机上,也可能分布在不同宿主机上。这两种不同的拓扑结构,其组网模型也不一样。

本文先介绍第一种,同宿主内pod间如何访问

同宿主内pod间如何访问

关于同主机下的pod如何访问,有多种技术可以实现,因为这个pod发送的数据包,无论如何流转,始终不会出宿主机。

正如前文所说,要分析网络,总是离不开网络设备和路由表。

veth pair

既然之前文章我们说过,veth pair可以实现跨network namespace通信,最简单的我们可以用veth pair来做这件事情。

回想第一篇文章,我们的veth pair一端在pod的network namespace,另外一端在宿主机上,也就是root network namespace。如果我们将另外一端放到要通信pod的network namespace中不就可以了吗?

没错,这种模型完全可以。并且也很简单,但是要维护它却很困难。

因为这种模型类似一个点对点的结构,它要求pod两两之间都需要有veth pair。 

试想,如果同一个主机内存在N个Pod。那么每个pod ns中都会存在N-1个veth设备,以及N-1条路由规则,整个主机上存在N*N个veth pair。

那你可能会说了,node节点默认可运行的pod数目上限是110个,也不是天文数字,似乎也能接受

确实,但再试想一个场景,当一个pod的IP发生变化的时候,你需要做什么?这时候可能就需要修改其他所有pod的路由规则。

这样一想,似乎就不太好接受了,veth pair的数量和路由表的维护是一个麻烦事。

那如果有个角色,能够将这些veth pair 束口呢?


bridge

接着刚才那个问题,熟悉linux设备的同学可能马上会想到,Liunx网桥不就能干这件事情吗?

确实可以,Linux bridge可以让这些网络设备作为一个端口连接到网桥上来,如下图所示:

在这里,Linux bridge充当了一个二层交换机的角色。负责将来自不同veth设备的流量进行交换和转发。

网桥的定义:网桥是一个工作在数据链路层的网络设备,可以连接多个局域网段,它能够根据MAC地址来转发帧,使得多个网络段上的设备能够像在同一个网络中一样进行通信。
Linux网桥:在Linux系统中,网桥是通过软件模拟实现的。它允许系统管理员创建一个逻辑上的交换机,可以绑定多个物理或虚拟网络接口。

这个模型很简单,它解决了第一种模型下veth pair数量多和需要维护路由的问题。

还是以同一个主机下N个Pod为例,在这个模型下,每个Pod的network namespace下只需要存在一个veth设备,整个主机也只需要N个veth pair。同时pod间的路由规则不需要任何路由表来记录。

没了路由表,Linux bridge怎么知道发送给谁呢?

答案是广播和转发表

广播的含义是当Linux bridge一个端口收到报文,而转发表中没有目标地址的MAC时,就会广播所有连接到bridge上的网络接口。

转发表的含义是bridge会记录所有经过的报文的MAC地址,它是自学习的。

有了linux bridge,大大减少了管理的复杂度,下面通过一个小实验,感受一个pod间如何通信。

实验

本实验用到的命令在Kubernets(k8s) 网络原理一:Pod与宿主机通信文章中有简单介绍

如无特殊说明,我们实验都用network namespace代指pod

创建pod-1和pod-2

# ip netns add pod-1# ip netns add pod-2

创建eth0和veth1,并将eth0加入pod-1 ns

# ip link add eth0 type veth peer name veth1# ip link set eth0 netns pod-1

创建eth0和veth2,并将eth0加入pod-2 ns

# ip link add eth0 type veth peer name veth2# ip link set eth0 netns pod-2

分别给pod-1和pod-2中的eth0配置ip

# ip netns exec pod-1 ip addr add 10.10.1.10/32 dev eth0# ip netns exec pod-2 ip addr add 10.10.1.11/32 dev eth0

启动pod-1中veth pair,并添加路由,为什么添加路由请查看前一篇文章

# ip netns exec pod-1 ip link set eth0 up# ip link set veth1 up# ip netns exec pod-1  ip ro add default dev eth0

启动pod-2中veth pair,并添加路由

# ip netns exec pod-2 ip link set eth0 up# ip link set veth2 up# ip netns exec pod-2 ip ro add default dev eth0

创建网桥cbr0并启动,需要安装bridge-utils

# brctl addbr cbr0# ip link set cbr0 up

将vteh1和veth2 添加进网桥

# brctl addif cbr0 veth1# brctl addif cbr0 veth2

查看vteh1和veth2是否正确添加到网桥

# brctl show
bridge name     bridge id               STP enabled     interfaces
cbr0            8000.d6821b81f256       no              veth1veth2

准备工作就绪,此时网络拓扑如下

我们尝试在pod-1中ping pod-2来模拟通信

# ip netns exec pod-1 ping -c 1 10.10.1.11
PING 10.10.1.11 (10.10.1.11) 56(84) bytes of data.
64 bytes from 10.10.1.11: icmp_seq=1 ttl=64 time=0.033 ms--- 10.10.1.11 ping statistics ---
1 packets transmitted, 1 received, 0% packet loss, time 0ms
rtt min/avg/max/mdev = 0.033/0.033/0.033/0.000 ms

一切顺利,可以ping通,我们抓包看看这个过程发生了什么

# ip netns exec pod-1 tcpdump -pne -i eth0
12:20:24.329781 12:35:c3:bb:69:bc > Broadcast, ethertype ARP (0x0806), length 42: Request who-has 10.10.1.11 tell 10.10.1.10, length 28
12:20:24.329812 7e:55:17:b0:dc:bb > 12:35:c3:bb:69:bc, ethertype ARP (0x0806), length 42: Reply 10.10.1.11 is-at 7e:55:17:b0:dc:bb, length 28
12:20:24.329814 12:35:c3:bb:69:bc > 7e:55:17:b0:dc:bb, ethertype IPv4 (0x0800), length 98: 10.10.1.10 > 10.10.1.11: ICMP echo request, id 48389, seq 1, length 64
12:20:24.329827 7e:55:17:b0:dc:bb > 12:35:c3:bb:69:bc, ethertype IPv4 (0x0800), length 98: 10.10.1.11 > 10.10.1.10: ICMP echo reply, id 48389, seq 1, length 64
12:20:29.340282 7e:55:17:b0:dc:bb > 12:35:c3:bb:69:bc, ethertype ARP (0x0806), length 42: Request who-has 10.10.1.10 tell 10.10.1.11, length 28
12:20:29.340285 12:35:c3:bb:69:bc > 7e:55:17:b0:dc:bb, ethertype ARP (0x0806), length 42: Reply 10.10.1.10 is-at 12:35:c3:bb:69:bc, length 28

 查看MAC地址与端口的映射关系

# brctl showmacs cbr0
port no mac addr                is local?       ageing timer1     12:35:c3:bb:69:bc       no                 2.302     7e:55:17:b0:dc:bb       no                 2.301     d6:82:1b:81:f2:56       yes                0.002     fe:c5:af:3f:03:b6       yes                0.00

值得说明的是,is local为no表示不是这个MAC地址不在root network namespace,上面回显中d6:82:1b:81:f2:56和fe:c5:af:3f:03:b6是veth1和veth2的mac地址,他们的is local为yes是因为veth1和veth2在root namespace。同时还可以看到相同端口号对应的正好是一对veth pair。

因此我们可以根据这两个信息总结关键流程如下:

  1. pod-1发起ICMP请求,因为无pod-2的MAC地址,于是先发起ARP请求
  2. pod-1 eth0发起ARP请求,希望获取10.1.10.11的mac地址
  3. cbr0收到广播的ARP请求,在转发表中记录MAC地址和端口
  4. 此时crb0中不存在pod-2中eth0的MAC地址,于是向所有将广播转发到其所绑定的所有端口,除了源veth
  5. pod-2 发现ieth0的ip刚好匹配,于是响应ARP请求,告诉自己的MAC地址
  6. crb0收到pod-2的ARP响应,在转发表中记录MAC地址和端口
  7. pod-1 向pod-2发起ICMP请求
  8. pod-2 响应ICMP请求

实验过程非常简单,这个模型能工作的原理就是利用了Linux bridge在二层通信。

实验环境清理

执行以下命令清理上文配置的设备

# ip netns del pod-1# ip netns del pod-2# ip link set cbr0 down# brctl delbr cbr0

小结

整个模型非常简单,完全是利用Linux Bridge的特性,没有什么好总结的,既然不总结,那就提几个问题

  • veth1和veth2为什么不需要配置IP?
  • bridge模型下主机内pod通信需要主机的eth0参与吗?
  • 如果主机内pod通信不需要eth0参与,那什么时候需要它参与呢?
  • cbr0网桥什么时候需要配置IP?

这些问题可能没有一个唯一的答案,但是能够触发我们思考。

直接点就是想说,要分析一种网络模型,你必须要知道这个网络下的各种网络设备作用。以及当网络诉求变化时,相关网络设备应该如何变化。


route table

bridge可以充当束口的角色,但是如果不想引入Linux bridge这个网络设备,又该如何处理呢?

我们知道一个主机打开ip_forward转发的时候,他自己就可以转发报文。

转发报文也就意味着从一个网络接口,转给另外一个网络接口,这个好理解,也就是说只要将veth pair的另一端连接到root network namesapce,让主机就能看到这个网络设备就可以做到。

问题在于第二个,如何转发?

话都到这了,肯定会想到路由表嘛

没错,在这个模型下,就是让主机承担这个转发的任务,同时将这些veth pair收拢到root network namesapce里面来。

通信模型如下。

在这个模型下,省去了网桥概念,通信模型更为简单,但是需要维护root network namespace中的route规则。不过好在这不会太多。

还是以同一个主机下N个Pod为例,在这个模型下,每个Pod的network namespace下只需要存在一个veth设备,整个主机也只需要N个veth pair,此外root network namespace中还需要有N条路由规则。

同理,我们也进行一个小实验来模拟

实验

建议先查看Kubernets(k8s) 网络原理一:Pod与宿主机通信,理解network namespace怎么和主机通信

老规矩,我们创建pod-1和pod-2 network namespace代表两个pod

以路由的方式配置nework namespace在上一篇文章中已经介绍了每一条命令的作用,因此这里只罗列命令

配置pod-1

# ip netns add pod-1# ip link add eth0 type veth peer name veth1# ip link set eth0 netns pod-1# ip netns exec pod-1 ip addr add 10.10.1.10 dev eth0# ip netns exec pod-1 ip link set dev eth0 up# ip netns exec pod-1 ip route add 169.254.1.1 dev eth0# ip netns exec pod-1 ip route add default via 169.254.1.1 dev eth0# ip link set dev veth1 up # echo 1 > /proc/sys/net/ipv4/conf/veth1/proxy_arp# echo 1 > /proc/sys/net/ipv4/ip_forward

配置pod-2

# ip netns add pod-2# ip link add eth0 type veth peer name veth2# ip link set eth0 netns pod-2# ip netns exec pod-2 ip addr add 10.10.1.11 dev eth0# ip netns exec pod-2 ip link set dev eth0 up# ip netns exec pod-2 ip route add 169.254.1.1 dev eth0# ip netns exec pod-2 ip route add default via 169.254.1.1 dev eth0# ip link set dev veth2 up # echo 1 > /proc/sys/net/ipv4/conf/veth2/proxy_arp# echo 1 > /proc/sys/net/ipv4/ip_forward

然后在主机上配置路由表

# ip route add 10.10.1.10 dev veth1 scope link# ip route add 10.10.1.11 dev veth2 scope link 

路由表的意思是说,所有发给10.10.1.10的报文都从veth1出去,同理,所有发给10.10.1.11的报文都从veth2 出去。

此时网络拓扑如下图所示:

此时我们尝试在pod-1中ping pod-2来模拟通信

# ip netns exec pod-1 ping -c 1 10.10.1.11
PING 10.10.1.11 (10.10.1.11) 56(84) bytes of data.
64 bytes from 10.10.1.11: icmp_seq=1 ttl=63 time=0.035 ms--- 10.10.1.11 ping statistics ---
1 packets transmitted, 1 received, 0% packet loss, time 0ms
rtt min/avg/max/mdev = 0.035/0.035/0.035/0.000 ms

没有问题,但是整个过程发生了什么呢,我们来抓包看一下

在pod-1中抓包

# ip netns exec pod-1 tcpdump -n -i eth0
09:53:29.297355 ARP, Request who-has 169.254.1.1 tell 10.10.1.10, length 28
09:53:29.382379 ARP, Reply 169.254.1.1 is-at be:7c:fa:0e:81:25, length 28
09:53:29.382386 IP 10.10.1.10 > 10.10.1.11: ICMP echo request, id 36618, seq 1, length 64
09:53:29.541810 IP 10.10.1.11 > 10.10.1.10: ICMP echo reply, id 36618, seq 1, length 64

这个过程其实我们已经在pod与宿主机通信文章中分析过了,这里简单梳理以下流程

  • pod-1中执行ping命令,通过socket调用给到pod-1协议栈
  • pod-1协议栈准备发起ICMP报文,查找路由表,获知从eth0出去,下一跳是169.254.1.1
  • pod-1协议栈查找Arp表,没有169.254.1.1的MAC地址,于是先发起Arp请求
  • veth1收到pod-1中eth0发来的Arp请求,因为配置了proxy_arp,于是响应自己的MAC地址
  • pod-1协议栈收到响应,组装ICMP报文,发送给veth-1
  • veth-1收到ICMP报文,交给自己的协议栈,即host协议栈
  • host协议栈因开启了ip_forward,于是查找本地路由表,发现应该从veth2设备发送
  • veth2和pod-2中eth0为veth pair关系,于是eth0收到pod-1发送的ICMP报文,交给pod-2协议栈
  • pod-2协议栈处理报文,按照原路返回响应报文。

小结

路由规则关心的是IP,而不是MAC地址,换句话说当跨物理网络时,路由模式的好处就显示出来了。虽然我们一台主机内不会存在跨网段,但是在后面我们总会用到的。

此外还值得说的一点是使用bridge的方式,Linux bridge会根据目的地址进行广播,所有设备都能收到,而L3 路由的方式则会隔离广播,请求的目的地址是固定的,因此广播限定在指定的广播域中,其它设备不会收到广播。

总结

本文分析两种主机内的组网模型,他们都可以达到主机内Pod相互通信的目的。只是采用不同的技术去实现,这两种方式没有严格的好坏之分,只是适用的场景不一样。

例如fiannel和docker就是采用bridge这种方式,依赖于一个网桥cni0(docker0)进行二层数据的转发。而calico就使用的L3路由的方式。

理解了主机内pod如何通信,在下一篇文章中,我们将分析整个容器组网最复杂的一部分,不同主机上的pod如何通信。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.rhkb.cn/news/391375.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

ECMAScript 12 (ES12, ES2021) 新特性

还是大剑师兰特:曾是美国某知名大学计算机专业研究生,现为航空航海领域高级前端工程师;CSDN知名博主,GIS领域优质创作者,深耕openlayers、leaflet、mapbox、cesium,canvas,webgl,ech…

PXE实验

实验前准备 关闭VMware的dhcp 点击 编辑 点击 虚拟网络编辑器 选择 NAT模式 将dhcp取消勾选 准备两台虚拟机 一台试验机,(网络环境正常并且有图形化的界面的rhel7) 一台测试机 init 5 --------------> 开启图形化界面 如…

element-plus框架+vue3+echart——后台页面

一、图表样式 图表组件:echarts https://echarts.apache.org/examples/zh/index.html element-plus框架: https://www.cwgj.xyz/zh-CN/ 1、折线图 栅格 一共24。 12代表占一半50%, 当页面缩小到一定程度 占整个屏幕的100%。 id"mo…

拉刀基础知识——拉刀的种类

如前面所说:近期要围绕拉削和拉刀这个话题,分享一些相关的内容,从最基础的知识开始,为此还专门买了本旧书——《拉刀设计》入门学习。废话不多说,直接开始。 拉刀最早由冲头演变而来,用于加工方孔&#xf…

C:关于static 和 extern 关键字的介绍-学习笔记

目录 1、作用域与生命周期 1.1 作用域 1.2 生命周期 1.3 变量的作用域和生命周期之间的关系 2、static 和 extern 2.1 static 修饰局部变量: 2.2 static 修饰全局变量(包含extern的作用): 2.3 static修饰函数&#xff1a…

由浅入深的了解进程(5)--环境变量

环境变量 前言环境变量1、更多的环境变量及添加和删除2、整体理解环境变量系统 3、内建命令 前言 在上一篇文章中简单的介绍了环境变量,但是没有讲述的比较全面了,所以现在再写一篇来介绍环境变量。 环境变量 在上一篇文章中,我们已经简单…

机械学习—零基础学习日志(高数18——无穷小与无穷大)

零基础为了学人工智能,真的开始复习高数 学习速度加快! 无穷小定义 这里可以记住,无穷小有一个特殊,那就是零。 零是最高阶的无穷小,且零是唯一一个常数无穷小。 张宇老师还是使用了超实数概念来讲解无穷小。其实是…

Mecanim Animation System

动画系统简介 Unity 有一个非常丰富而又复杂的动画系统,官方称其为Mecanim。该系统具有以下功能: 支持从外部导入动画剪辑,如:fbx、mb | ma(Autodesk maya 原件)、.max(3ds Max原件&#xff09…

Final Shell for Mac 虚拟机连接工具【简单易操作,轻松上手】【开发所需连接工具】

Mac分享吧 文章目录 效果一、下载软件二、安装软件三、运行测试安装完成!!! 效果 一、下载软件 下载软件 链接:http://www.macfxb.cn 二、安装软件 三、运行测试 安装完成!!!

Redis学习[6] ——Redis缓存设计

八、Redis缓存设计 8.1 为什么Redis用作缓存? 一般来说,数据库的数据都是落在磁盘上的,会导致读写速度很慢。如果用户的请求量非常大,数据库很容易崩溃。由于Redis的数据保存在内存中,读写速度很快,所以R…

React(四):DOCX文件在线预览

效果 注意 ⚠️注意:部分文件预览存在问题 依赖 $ yarn add docx-preview $ yarn add jszip源码 import ./index.scss; import {useRef} from react; import type {UploadRequestOption} from rc-upload/lib/interface; import {Upload, Button, message} from an…

【时时三省】(C语言基础)一维数组

山不在高,有仙则名。水不在深,有龙则灵。 ——csdn时时三省 数组 数组就是一组数 数组的官方定义是一组相同类型元素的集合 一堆数组的创建和初始化 求组的创建 数组是一组相同类型元素的集合。数组的创建当时是: type_t arr&#x…

【过题记录】8.4(robocom补题,网络流)

今天robocom国赛,因为一个bool函数忘记return 1而裂开(错失21分) 以此为戒 贪心消消乐 其实就是一个求最大子矩阵和的板子题 利用最大子段和的思想 枚举矩阵中的上下界 压成一维后利用最大子段和 O ( n ) O(n) O(n)处理 复杂度 O ( n 3 ∗ k ) O(n^3*k) O(n3∗k) k为…

nginx: [error] open() “/run/nginx.pid“ failed (2: No such file or directory)

今天 准备访问下Nginx服务,但是 启动时出现如下报错:(80端口被占用,没有找到nginx.pid文件) 解决思路: 1、 查看下排查下nginx服务 #确认下nginx状态 ps -ef|grep nginx systemctl status nginx#查看端口…

[CTF]-PWN:格式化字符串漏洞题综合解析

printf型格式化字符串漏洞: 任意地址写: 32位: 例题(inndy_echo): 有格式化字符串漏洞,可以修改printf的got表内地址为system,传参getshell 解法一: 在32位中可以使…

vscode的json文件解析

vscode的json文件解析 0.参考链接1.什么是JSON2.JSON语法2.0数据类型2.1对象2.2数组2.3嵌套 3.vscode包含的JSON文件介绍4.vscode包含的JSON文件解析4.1 task.json4.2 launch.json4.3 settings.json4.4 c_cpp_properties.json4.5 package.json(详细的看参考链接&…

Python设计模式 - 抽象工厂模式

定义 抽象工厂模式是一种创建型设计模式,它提供了一种创建一系列相关或相互依赖对象的接口,而无需指定它们具体的类。 产品等级结构与产品族 为了更好地理解抽象工厂模式,先引入两个概念: 产品等级结构:就是产品的…

试用AWS全新神器:Amazon Bedrock的「Open Artifacts」版Claude.ai Artifacts

Claude.ai的Artifacts真是太方便了。 GitHub上的AWS Samples仓库中有一个仿制Artifacts的应用程序。 Open Artifacts for Amazon Bedrock https://github.com/aws-samples/open_artifacts_for_bedrockhttps://github.com/aws-samples/open_artifacts_for_bedrock本文将介绍「…

【C++】数组案例 五只小猪称体重

题目:给出五只小猪体重,找出最大的体重的值并打印 思路:利用数组写入五只小猪的体重,让每一个元素都赋值给一个整型变量并每赋值一次就于下一个数组中的元素比,若是大就继续赋值给这个变量,若是小则不赋值…

H81002S 1.7mm网络变压器:BMS汽车蓝牙接收器中的超薄共模电感科技

华强盛导读:在当今这个日新月异的汽车科技领域,每一处细节都蕴含着创新与突破。作为电动汽车心脏的电池管理系统(BMS),其高效稳定的运行不仅关乎续航与安全,更是智能化驾驶体验的基石。而在这背后&#xff…