- VisualStudio2022插件的安装及使用-编程手把手系列文章
- pprof-在现网场景怎么用
- C#实现的下拉多选框,下拉多选树,多级节点
- 【学习笔记】基础数据结构:猫树
几种通过 iproute2 来打通不同节点间容器网络的方式 。
之前由于需要打通不同节点间的容器网络,对 flannel 进行修改增加了网络相关信息的获取逻辑,进而可以完整使用 backend 的功能。 最近想拿掉这个 flannel,所以分析一下 backend 的功能,使用 ip 命令来进行模拟 。
flannel 的 backend 提供了 7 种类型,这里只对以下 3 种内核提供的功能作模拟 。
容器使用网络命名空间隔离网络相关资源,为了操作简单直接使用网络命名空间作为测试环境.
vm1(192.168.32.245) 和 vm2(192.168.32.246) 是物理机上的两个虚拟机,操作系统为 CentOS 7.2.
目标为将 172.245.0.0/24 和 172.246.0.0/24 网段打通.
┌─────────────────────────────┐ ┌─────────────────────────────┐
│ vm1 │ │ vm2 │
│ ┌─────────────────┐ │ │ ┌─────────────────┐ │
│ │ ns245 │ │ │ │ ns246 │ │
│ │ 172.245.0.2 │ │ │ │ 172.246.0.2 │ │
│ │ eth0 │ │ │ │ eth0 │ │
│ └────────|────────┘ │ │ └────────|────────┘ │
│ │ │ │ │ │
│ veth245 │ │ veth246 │
│ │ │ │ │ │
│ br245 │ │ br246 │
│ 172.245.0.1/24 │ │ 172.246.0.1/24 │
│ │ │ │
│ │ │ │
│ 192.168.32.245/24 │ │ 192.168.32.246/24 │
│ eth0 │ │ eth0 │
└──────────────│──────────────┘ └──────────────│──────────────┘
│ │
└────────────────────────────────────────┘
需要打开 ip_forward 选项,让流量能够通过网桥进入命名空间 。
sysctl -w net.ipv4.ip_forward=1
设置网桥 。
# 创建网桥
ip link add br245 type bridge
# 启用网桥
ip link set br245 up
创建命名空间、设置虚拟网卡 。
# 创建网络命名空间
ip netns add ns245
# 创建 veth-peer,并且一端设置在 netns 中
ip link add veth245 type veth peer name eth0 netns ns245
# 启用 netns 中的 veth-peer
ip netns exec ns245 ip link set eth0 up
# 启用 host 中的 veth-peer
ip link set veth245 up
# 将 host 中的 veth-peer 挂载到 br245 网桥上
ip link set veth245 master br245
设置网卡地址和路由 。
# 设置网桥地址
ip addr add 172.245.0.1/24 dev br245
# 设置命名空间内的 veth-peer 地址
ip netns exec ns245 ip addr add 172.245.0.2/24 dev eth0
# 设置命名空间内的默认路由(新建容器也会存在一条这个默认路由)
ip netns exec ns245 ip route add default via 172.245.0.1 dev eth0
vm2 的设置只需将 245 替换为 246 即可 。
设置完成后,vm1 的网卡、地址和路由信息如下(略去无关网卡) 。
$ ip addr
2: eth0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UP group default qlen 1000
link/ether 52:54:00:ce:51:a5 brd ff:ff:ff:ff:ff:ff
inet 192.168.32.245/24 brd 192.168.32.255 scope global noprefixroute eth0
valid_lft forever preferred_lft forever
inet6 fe80::5054:ff:fece:51a5/64 scope link
valid_lft forever preferred_lft forever
9: br245: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP group default qlen 1000
link/ether 02:8d:b1:91:fa:7a brd ff:ff:ff:ff:ff:ff
inet6 fe80::7426:b5ff:fea9:d35/64 scope link
valid_lft forever preferred_lft forever
10: veth245@if2: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue master br245 state UP group default qlen 1000
link/ether 02:8d:b1:91:fa:7a brd ff:ff:ff:ff:ff:ff link-netnsid 0
inet6 fe80::8d:b1ff:fe91:fa7a/64 scope link
valid_lft forever preferred_lft forever
$ ip route
default via 192.168.32.1 dev eth0 proto static metric 100
172.245.0.0/24 dev br245 proto kernel scope link src 172.245.0.1
192.168.32.0/24 dev eth0 proto kernel scope link src 192.168.32.245 metric 100
$ ip netns exec ns245 ip addr
2: eth0@if10: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP group default qlen 1000
link/ether be:9c:d4:57:58:5a brd ff:ff:ff:ff:ff:ff link-netnsid 0
inet 172.245.0.2/24 scope global eth0
valid_lft forever preferred_lft forever
inet6 fe80::bc9c:d4ff:fe57:585a/64 scope link
valid_lft forever preferred_lft forever
$ ip netns exec ns245 ip route
default via 172.245.0.1 dev eth0
172.245.0.0/24 dev eth0 proto kernel scope link src 172.245.0.2
只需要在 vm 中设置一条指向对方的路由即可 。
# vm1
ip route add 172.246.0.0/24 via 192.168.32.246 dev eth0 onlink
# vm2
ip route add 172.245.0.0/24 via 192.168.32.245 dev eth0 onlink
在命名空间内测试 172.246.0.2 是否能通 。
$ ip netns exec ns245 ping -c 1 172.246.0.2
PING 172.246.0.2 (172.246.0.2) 56(84) bytes of data.
64 bytes from 172.246.0.2: icmp_seq=1 ttl=62 time=0.656 ms
--- 172.246.0.2 ping statistics ---
1 packets transmitted, 1 received, 0% packet loss, time 0ms
rtt min/avg/max/mdev = 0.656/0.656/0.656/0.000 ms
从 172.245.0.2 访问 172.246.0.2 的时序图如下(回包方向逻辑一致) 。
172.245.0.2 ns245:eth0 br245 vm1:eth0 vm2:eth0 br246 ns246:eth0 172.246.0.2
| | | | | | | |
| default | | | | | | |
| routing | | | | | | |
| --------> | | | | | | |
| | veth-peer | | | | | |
| | master | | | | | |
| | --------> | | | | | |
| | | 172.246.0.2 | | | | |
| | | routing | | | | |
| | | ----------> | | | | |
| | | | layer 2 | | | |
| | | | --------> | | | |
| | | | | 172.246.0.2 | | |
| | | | | routing | | |
| | | | | ----------> | | |
| | | | | | master | |
| | | | | | veth-peer | |
| | | | | | --------> | |
| | | | | | | 172.246.0.2 |
| | | | | | | ----------> |
| | | | | | | |
172.245.0.2 ns245:eth0 br245 vm1:eth0 vm2:eth0 br246 ns246:eth0 172.246.0.2
Q: 为何 host-gw 模式下的容器所在宿主机必须在同一网段(二层互通) A: 路由不会修改源IP,回包交换源目的 IP 后,网关查询路由表不能确定发包接口,二层互通不存在这个问题,不需要查询路由表,直接根据 MAC 地址选路 。
IPIP(IP-in-IP)协议是一种网络层隧道协议,用于在一个IP网络上传输另一个IP数据包。IPIP协议的主要目的是在网络之间提供透明的通信通道,使得内部网络的数据包可以通过外部网络传输,而不需要改变数据包的内容.
协议格式如下 。
// 原始 TCP 数据包
+--------------------------------+
| .... |
+--------------------------------+
| TCP |
+--------------------------------+
| IP |
+--------------------------------+
| Ethernet |
+--------------------------------+
// ipip 封装后的数据包
+--------------------------------+
| .... |
+--------------------------------+
| TCP |
+--------------------------------+
| IP |
+--------------------------------+
/ IP (tunnel) /
+--------------------------------+
| Ethernet |
+--------------------------------+
在 vm1 中设置 ipip 隧道 。
# 创建 IPIP 隧道接口
ip tunnel add tun245 mode ipip local 192.168.32.245 remote 192.168.32.246
# 配置 IPIP 隧道接口的 IP 地址
ip addr add 172.245.1.1/30 dev tun245
# 启用 IPIP 隧道接口
ip link set tun245 up
# 添加路由,使 172.246.0.0/24 网段的数据包通过 IPIP 隧道传输
ip route add 172.246.0.0/24 via 172.245.1.2 dev tun245
在 vm2 中访问 172.245.0.2 (增加访问 192.168.32.245 进行对比) 。
$ ping -c 1 192.168.32.245
$ ip netns exec ns246 ping -c 1 172.245.0.2
在 vm1 中对 eth0 进行抓包 。
$ tcpdump -s0 -i eth0 host 192.168.32.246 -nn
11:28:01.268176 IP 192.168.32.246 > 192.168.32.245: ICMP echo request, id 1730, seq 1, length 64
11:28:01.268299 IP 192.168.32.245 > 192.168.32.246: ICMP echo reply, id 1730, seq 1, length 64
11:28:08.697558 IP 192.168.32.246 > 192.168.32.245: IP 172.246.0.2 > 172.245.0.2: ICMP echo request, id 1708, seq 26, length 64 (ipip-proto-4)
11:28:08.697760 IP 192.168.32.245 > 192.168.32.246: IP 172.245.0.2 > 172.246.0.2: ICMP echo reply, id 1708, seq 26, length 64 (ipip-proto-4)
在 wireshark 更直观的看到 ipip 多了一层 ip,用来作为隧道通信.
Frame 3: 118 bytes on wire (944 bits), 118 bytes captured (944 bits)
Ethernet II, Src: 52:54:00:b9:5d:53 (52:54:00:b9:5d:53), Dst: 52:54:00:ce:51:a5 (52:54:00:ce:51:a5)
Internet Protocol Version 4, Src: 192.168.32.246, Dst: 192.168.32.245
Internet Protocol Version 4, Src: 172.246.0.2, Dst: 172.245.0.2
Internet Control Message Protocol
从 172.245.0.2 访问 172.246.0.2 的时序图如下(省略命名空间内的部分,回包方向逻辑一致) 。
br245 tun245 vm1:eth0 vm2:eth0 tun246 br246
| | | | | |
| 172.246.0.2 | | | | |
| routing | | | | |
| ----------> | | | | |
| | ipip pack | | | |
| | --------> | | | |
| | | layer 2 | | |
| | | --------> | | |
| | | | ipip unpack | |
| | | | ----------> | |
| | | | | 172.246.0.2 |
| | | | | routing |
| | | | | ----------> |
| | | | | |
br245 tun245 vm1:eth0 vm2:eth0 tun246 br246
Q: 和 host-gw 最大的区别是什么 A: 对容器(网络命名空间)所在节点的网络不再限制二层互通,只要节点网络(二层、三层)互通即可.
vxlan 旨在解决大型云数据中心和多租户环境中传统 vlan(虚拟局域网)技术的局限性。通过在 UDP 之上封装第二层以太网帧,实现在第三层(IP)网络上的二层网络扩展,从而允许创建多达 1600 万个隔离的虚拟网络,远超 vlan 的4096 个网络限制.
协议格式如下 。
// 原始 TCP 数据包
+----------------------------------------+
| .... |
+----------------------------------------+
| TCP |
+----------------------------------------+
| IP |
+----------------------------------------+
| Ethernet |
+----------------------------------------+
// vxlan 封装后的数据包
+----------------------------------------+
| .... |
+----------------------------------------+
| TCP |
+----------------------------------------+
| IP |
+----------------------------------------+
| Ethernet |
+----------------------------------------+
/ VXLAN Header (8 bytes) /
+----------------------------------------+
/ UDP (tunnel) /
+----------------------------------------+
/ IP (tunnel) /
+----------------------------------------+
/ Ethernet (tunnel) /
+----------------------------------------+
在 vm1 中设置 。
# 创建 VXLAN 隧道接口
ip link add vtep245 type vxlan id 1 local 192.168.32.245 dev eth0 dstport 8472 nolearning
# 配置 IP
ip addr add 172.245.0.0/32 dev vtep245
# 设置 MTU
ip link set vtep245 mtu 1450
# 启动 vtep
ip link set veth245 up
# 配置路由
ip route add 172.246.0.0/24 via 172.246.0.0 dev vtep245 onlink
vm2 中配置和 vm1 中相反,245 和 246 需要互换 。
查看虚拟网卡,看到设置的 vxlan id、网卡和本地 ip 。
root@vm1# ip -d link show vtep245
12: vtep245: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1450 qdisc noqueue state UNKNOWN mode DEFAULT group default qlen 1000
link/ether 52:3a:8c:c9:08:e8 brd ff:ff:ff:ff:ff:ff promiscuity 0
vxlan id 1 local 192.168.32.245 dev eth0 srcport 0 0 dstport 8472 nolearning ageing 300 noudpcsum noudp6zerocsumtx noudp6zerocsumrx addrgenmode eui64 numtxqueues 1 numrxqueues 1 gso_max_size 65536 gso_max_segs 65535
root@vm2# ip -d link show vtep246
10: vtep246: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1450 qdisc noqueue state UNKNOWN mode DEFAULT group default qlen 1000
link/ether 02:38:4a:12:3b:43 brd ff:ff:ff:ff:ff:ff promiscuity 0
vxlan id 1 local 192.168.32.246 dev eth0 srcport 0 0 dstport 8472 nolearning ageing 300 noudpcsum noudp6zerocsumtx noudp6zerocsumrx addrgenmode eui64 numtxqueues 1 numrxqueues 1 gso_max_size 65536 gso_max_segs 65535
查看监听 UDP 端口,看到内核监听了 8742 。
$ netstat -nulp
Proto Recv-Q Send-Q Local Address Foreign Address State PID/Program name
udp 0 0 0.0.0.0:8472 0.0.0.0:* -
当前的网络拓扑图如下 。
┌─────────────────────────────┐ ┌─────────────────────────────┐
│ vm1 │ │ vm2 │
│ ┌─────────────────┐ │ │ ┌─────────────────┐ │
│ │ ns245 │ │ │ │ ns246 │ │
│ │ 172.245.0.2 │ │ │ │ 172.246.0.2 │ │
│ │ eth0 │ │ │ │ eth0 │ │
│ └────────|────────┘ │ │ └────────|────────┘ │
│ │ │ │ │ │
│ veth245 │ │ veth246 │
│ │ │ │ │ │
│ br245 │ │ br246 │
│ 172.245.0.1/24 │ │ 172.246.0.1/24 │
│ │ │ │
│ vtep245 │ │ vtep246 │
│ vni:1 172.245.0.0 │ │ vni:1 172.246.0.0 │
│ │ │ │
│ 192.168.32.245/24 │ │ 192.168.32.246/24 │
│ eth0 │ │ eth0 │
└──────────────│──────────────┘ └──────────────│──────────────┘
│ │
└────────────────────────────────────────┘
在 vm1 上尝试通过 172.245.0.2 访问 172.246.0.2,无法访问,通过 tcpdump 诊断流量到达虚拟网卡 vtep245,但是不知道网关 172.246.0.0 的 MAC 地址 。
$ ip netns exec ns245 ping -c 1 172.246.0.2
$ tcpdump -s0 -i vtep245 -nn
tcpdump: verbose output suppressed, use -v or -vv for full protocol decode
17:44:26.916277 ARP, Request who-has 172.246.0.0 tell 172.245.0.0, length 28
在上面已经知道了网关的 MAC 地址,直接进行手动设置(flannel 中有 etcd 进行集中管理) 。
# vm1
ip neigh add 172.246.0.0 dev vtep245 lladdr 02:38:4a:12:3b:43
# vm2
ip neigh add 172.245.0.0 dev vtep246 lladdr 52:3a:8c:c9:08:e8
解决 MAC 地址问题后,还有一个问题:vxlan 封的包如何发送出去,这里使用 fdb 来根据 MAC 指定 vxlan 包发送的地址 。
fdb 是一个用于存储 MAC 地址及其对应端口的信息表,以便桥接设备能够高效地转发数据帧.
# vm1
bridge fdb add 02:38:4a:12:3b:43 dev vtep245 dst 192.168.32.246
# vm2
bridge fdb add 52:3a:8c:c9:08:e8 dev vtep246 dst 192.168.32.245
从 172.245.0.2 访问 172.246.0.2 的时序图如下(省略命名空间内的部分,回包方向逻辑一致) 。
br245 vtep245 vm1:eth0 vm2:eth0 vtep246 br246
| | | | | |
| 172.246.0.2 | | | | |
| routing | | | | |
| ----------> | | | | |
| | vxlan pack | | | |
| | ---------> | | | |
| | | udp 8742 | | |
| | | --------> | | |
| | | | vxlan unpack | |
| | | | -----------> | |
| | | | | 172.246.0.2 |
| | | | | routing |
| | | | | ----------> |
| | | | | |
br245 vtep245 vm1:eth0 vm2:eth0 vtep246 br246
Q: 为何 vm1 上的路由要使用 172.246.0.0 作为网关地址 A
从功能上看:
从性能上看:
最后此篇关于[解决方案]几种通过iproute2来打通不同节点间容器网络的方式的文章就讲到这里了,如果你想了解更多关于[解决方案]几种通过iproute2来打通不同节点间容器网络的方式的内容请搜索CFSDN的文章或继续浏览相关文章,希望大家以后支持我的博客! 。
这是我想做的 1 - 点击提交 2 - 隐藏 DIV 容器 1 3 - 显示 DIV 容器 2 4 - 将“PricingDisclaimer.php”中找到的所有 DIV 加载到 Div 容器 2
我有一个 ios 应用程序,它使用 iCloudcontainer 来保存用户的一些数据,例如用户的“到期日期”。我要用不同的方式创建应用程序的副本开发者账号。我要将用户从第一个应用程序迁移到第二个应
这是场景。 我有三个容器。 Container1、container2 和 container3(基于 Ubuntu 的镜像),其中 container2 充当容器 1 和容器 2 之间的路由器。 我
关闭。这个问题需要多问focused 。目前不接受答案。 想要改进此问题吗?更新问题,使其仅关注一个问题 editing this post . 已关闭 9 年前。 Improve this ques
我正在改造管道以使用声明式管道方法,以便我能够 to use Docker images在每个阶段。 目前我有以下工作代码,它执行连接到在 Docker 容器中运行的数据库的集成测试。 node {
我正在开发一个需要尽可能简单地为最终用户安装的应用程序。虽然最终用户可能是经验丰富的 Linux 用户(或销售工程师),但他们对 Tomcat、Jetty 等并不真正了解,我认为他们也不应该了解。 所
我从gvisor-containerd-shim(Shim V1)移到了containerd-shim-runsc-v1(Shim V2)。在使用gvisor-containerd-shim的情况下,
假设我们只在某些开发阶段很少需要这样做(冒烟测试几个 api 调用),让项目 Bar 中的 dockerized web 服务访问 Project Foo 中的 dockerized web 服务的最
各位,我的操作系统是 Windows 10,运行的是 Docker 版本 17.06.0-ce-win19。我在 Windows 容器中运行 SQL Server Express,并且希望将 SQL
谁能告诉我,为什么我们不能在 Azure 存储中的容器内创建容器?还有什么方法可以处理,我们需要在 azure 存储中创建目录层次结构? 最佳答案 您无法在容器中创建容器,因为 Windows Azu
#include template struct Row { Row() { puts("Row default"); } Row(const Row& other) { puts
按照目前的情况,这个问题不适合我们的问答形式。我们希望答案得到事实、引用或专业知识的支持,但这个问题可能会引发辩论、争论、投票或扩展讨论。如果您觉得这个问题可以改进并可能重新打开,visit the
RDF容器用于描述一组事物 例如,把一本书的所有作者列在一起 RDF容器有三种类型: <Bag> <Seq> <Alt> <rdf:
编辑:从到目前为止添加的答案和评论看来,我没有正确解释我想要什么。下面是一个例子: // type not supporting any type of comparison [] [] type b
我正在测试 spatie 的异步项目。我创建了一个这样的任务。 use Spatie\Async\Task; class ServiceTask extends Task { protecte
我想使用 Azure Blob 存储来上传和下载文档。有一些公司可以上传和下载他们的文档。我想保证这些文件的安全。这意味着公司只能看到他们的文件。不是别人的。 我可以在 blob 容器中创建多个文件夹
我正在尝试与 Azure 中的容器实例进行远程交互。我已执行以下步骤: 已在本地注册表中加载本地镜像 docker load -i ima.tar 登录远程 ACR docker登录--用户名--密码
我正在研究http://progrium.viewdocs.io/dokku/process-management/,并试图弄清楚如何从单个项目中运行多个服务。 我有一个Dockerfile的仓库:
我有一个想要容器化的单体应用程序。文件夹结构是这样的: --app | |-file.py <-has a variable foo that is passed in --configs
我正在学习 Docker,并且一直在为 Ubuntu 容器制作 Dockerfile。 我的问题是我不断获取不同容器之间的持久信息。我已经退出,移除了容器,然后移除了它的图像。在对 Dockerfil
我是一名优秀的程序员,十分优秀!