【Docker】Swarm的overlay网络

news/2024/11/19 7:27:34/

对于理解swarm的网络来讲,个人认为最重要的两个点:

第一是外部如何访问部署运行在swarm集群内的服务,可以称之为入方向流量,在swarm里我们通过ingress来解决。

第二是部署在swarm集群里的服务,如何对外进行访问,这部分又分为两块:

  • 第一,东西向流量,也就是不同swarm节点上的容器之间如何通信,swarm通过overlay网络来解决;
  • 第二,南北向流量,也就是swarm集群里的容器如何对外访问,比如互联网,这个是通过Linux bridge + iptables NAT来解决的,这个与单个容器访问外网的原理是一致的。

这里主要了解下不同swarm节点上的容器之间如何通过overlay网络进行通信。

主机规划:

  • node1:172.19.177.14,角色为Leader
  • node2:172.19.188.123,角色为Worker
$ sudo docker node ls
ID                            HOSTNAME   STATUS    AVAILABILITY   MANAGER STATUS   ENGINE VERSION
6lj1g1gu1ojdixy7xyv49mk5d *   node1      Ready     Active         Leader           24.0.2
gi694i1yfoc4fh1yf8185kq9i     node2      Ready     Active                          24.0.2

创建overlay网络

在node1上创建一个名为mynet的overlay网络:

$ sudo docker network create -d overlay mynet
ysbj86zsjo3iieivgvkzbr4ly

创建服务

创建一个服务连接到这个overlay网络,name是app,replicas是2:

$ sudo docker service create --network mynet --name app --replicas 2 busybox ping 8.8.8.8
ldzod2s1ylgl0euauxlxfkoc1
overall progress: 2 out of 2 tasks
1/2: running   [==================================================>]
2/2: running   [==================================================>]
verify: Service converged

查看已经创建的服务:

$ sudo docker service ps app
ID             NAME      IMAGE            NODE      DESIRED STATE   CURRENT STATE            ERROR     PORTS
s0c03hrcjx7e   app.1     busybox:latest   node1     Running         Running 20 seconds ago
rv2ysokngn7p   app.2     busybox:latest   node2     Running         Running 20 seconds ago

可以看到这两个容器分别被创建在node1和node2两个节点上。

mynet这个网络在第一次使用的时候才会同步到所有的swarm节点上,在node2上可以查询到:

$ sudo docker network list | grep overlay
5knp2oqmdu4n   ingress           overlay   swarm
ysbj86zsjo3i   mynet             overlay   swarm

查看app.1的网络

在node1上找到app.1这个容器:

$ sudo docker container ls
CONTAINER ID   IMAGE            COMMAND          CREATED              STATUS          PORTS     NAMES
03be3938e6bc   busybox:latest   "ping 8.8.8.8"   About a minute ago   Up 59 seconds             app.1.s0c03hrcjx7e5glpf8mu0z0v6

查看app.1这个容器的IP:

$ sudo docker container exec -it 03be3938e6bc ip addr
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue qlen 1000link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00inet 127.0.0.1/8 scope host lovalid_lft forever preferred_lft forever
100: eth0@if101: <BROADCAST,MULTICAST,UP,LOWER_UP,M-DOWN> mtu 1450 qdisc noqueuelink/ether 02:42:0a:00:01:03 brd ff:ff:ff:ff:ff:ffinet 10.0.1.3/24 brd 10.0.1.255 scope global eth0valid_lft forever preferred_lft forever
102: eth1@if103: <BROADCAST,MULTICAST,UP,LOWER_UP,M-DOWN> mtu 1500 qdisc noqueuelink/ether 02:42:ac:12:00:03 brd ff:ff:ff:ff:ff:ffinet 172.18.0.3/16 brd 172.18.255.255 scope global eth1valid_lft forever preferred_lft forever

发现app.1这个容器有两个网卡eth0和eth1,其中eth0是连到了mynet这个网络,eth1是连到docker_gwbridge这个网络。

查看app.2的网络

在node2上找到app.2这个容器:

$ sudo docker container ls
CONTAINER ID   IMAGE            COMMAND          CREATED         STATUS         PORTS     NAMES
7ba95286b2e2   busybox:latest   "ping 8.8.8.8"   2 minutes ago   Up 2 minutes             app.2.rv2ysokngn7pvf2bv3l7lnenp

查看app.2这个容器的IP:

$ sudo docker container exec -it 7ba95286b2e2 ip addr
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue qlen 1000link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00inet 127.0.0.1/8 scope host lovalid_lft forever preferred_lft forever
91: eth0@if92: <BROADCAST,MULTICAST,UP,LOWER_UP,M-DOWN> mtu 1450 qdisc noqueuelink/ether 02:42:0a:00:01:04 brd ff:ff:ff:ff:ff:ffinet 10.0.1.4/24 brd 10.0.1.255 scope global eth0valid_lft forever preferred_lft forever
93: eth1@if94: <BROADCAST,MULTICAST,UP,LOWER_UP,M-DOWN> mtu 1500 qdisc noqueuelink/ether 02:42:ac:14:00:03 brd ff:ff:ff:ff:ff:ffinet 172.20.0.3/16 brd 172.20.255.255 scope global eth1valid_lft forever preferred_lft forever

发现app.2这个容器有两个网卡eth0和eth1,其中eth0是连到了mynet这个网络,eth1是连到docker_gwbridge这个网络。

app.1和app.2这两个容器的网卡eth0在同一个网段,用来容器之间进行通讯使用。

在app.1中访问app.2:

$ sudo docker container exec -it 03be3938e6bc ping 10.0.1.4 -c 3
PING 10.0.1.4 (10.0.1.4): 56 data bytes
64 bytes from 10.0.1.4: seq=0 ttl=64 time=0.887 ms
64 bytes from 10.0.1.4: seq=1 ttl=64 time=0.461 ms
64 bytes from 10.0.1.4: seq=2 ttl=64 time=0.446 ms--- 10.0.1.4 ping statistics ---
3 packets transmitted, 3 packets received, 0% packet loss
round-trip min/avg/max = 0.446/0.598/0.887 ms

虽然app.1和app.2的网卡eth0在同一个网段,但是这两个容器是位于不同的宿主机上,他们是怎样进行通讯的呢?

查看overlay网络mynet的网络详情

mynet这个网络的ip为10.0.1.1,在两个宿主机上的ip都是这个,app.1app.2这两个容器连接在这个网络上,并通过这个网络进行通讯。

$ sudo docker network inspect mynet
[{"Name": "mynet","Id": "ysbj86zsjo3iieivgvkzbr4ly","Created": "2023-11-29T01:36:58.554703707Z","Scope": "swarm","Driver": "overlay","EnableIPv6": false,"IPAM": {"Driver": "default","Options": null,"Config": [{"Subnet": "10.0.1.0/24","Gateway": "10.0.1.1"}]},"Internal": false,"Attachable": false,"Ingress": false,"ConfigFrom": {"Network": ""},"ConfigOnly": false,"Containers": {"03be3938e6bc2b0b02104f43864c6c6f33eca4b00ad8a84f3cc0092919829c14": {"Name": "app.1.s0c03hrcjx7e5glpf8mu0z0v6","EndpointID": "fbc5326ba4f3655a2b4e43da9c1398e71df45267f164e3f7d0d4aa5518d3688d","MacAddress": "02:42:0a:00:01:03","IPv4Address": "10.0.1.3/24","IPv6Address": ""},"lb-mynet": {"Name": "mynet-endpoint","EndpointID": "6ed5bb4ca3745ddc987ed7bb85edb7062f6e0a6b75bb49b2f255203cfebce329","MacAddress": "02:42:0a:00:01:06","IPv4Address": "10.0.1.6/24","IPv6Address": ""}},"Options": {"com.docker.network.driver.overlay.vxlanid_list": "4097"},"Labels": {},"Peers": [{"Name": "a69283b7d627","IP": "172.19.177.14"},{"Name": "7826e8e0446d","IP": "172.19.188.123"}]}
]

查看mynet网络命名空间

在创建mynet网络的同时会在宿主机上创建一个网络命名空间,其名称与mynet的ID前缀一致。

查询到mynet网络命名空间对应的ID为ysbj86zsjo3i

$ sudo docker network ls | grep overlay
5knp2oqmdu4n   ingress           overlay   swarm
ysbj86zsjo3i   mynet             overlay   swarm

再在docker创建的命名空间目录/run/docker/netns/下寻找ysbj86zsjo3i命名空间文件:

$ sudo ls /run/docker/netns/
1-5knp2oqmdu  1-ysbj86zsjo  b8fd600925b7  ingress_sbox  lb_ysbj86zsj

由于docker将命名空间文件放在了/run/docker/netns/目录下,而不是系统默认的目录/var/run/netns/,我们无法使用ip netns命令来直接访问docker创建的命名空间,我们这里借助nsenter命令来操作:

$ sudo nsenter --net="/run/docker/netns/1-ysbj86zsjo" ip addr
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1000link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00inet 127.0.0.1/8 scope host lovalid_lft forever preferred_lft forever
2: br0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1450 qdisc noqueue state UP group defaultlink/ether 7a:72:0e:c5:e1:4c brd ff:ff:ff:ff:ff:ffinet 10.0.1.1/24 brd 10.0.1.255 scope global br0valid_lft forever preferred_lft forever
97: vxlan0@if97: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1450 qdisc noqueue master br0 state UNKNOWN group defaultlink/ether 7a:72:0e:c5:e1:4c brd ff:ff:ff:ff:ff:ff link-netnsid 0
99: veth0@if98: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1450 qdisc noqueue master br0 state UP group defaultlink/ether da:73:88:00:81:1c brd ff:ff:ff:ff:ff:ff link-netnsid 1
101: veth1@if100: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1450 qdisc noqueue master br0 state UP group defaultlink/ether fe:43:7b:22:c2:8f brd ff:ff:ff:ff:ff:ff link-netnsid 2

可以看到mynet网络命名空间的ip为10.0.1.1/24,并在其中添加了vxlan。

vxlan

VXLAN(Virtual eXtensible Local Area Network,虚拟可扩展局域网),是一种虚拟化隧道通信技术。它是一种 Overlay(覆盖网络)技术,通过三层的网络来搭建虚拟的二层网络。

FDB(Forwarding Database entry,即转发表)是Linux网桥维护的一个二层转发表,用于保存远端虚拟机/容器的MAC地址,远端VTEP IP,以及VNI的映射关系,可以通过bridge fdb命令来对FDB表进行操作:

$ sudo nsenter --net="/run/docker/netns/1-ysbj86zsjo" bridge fdb
33:33:00:00:00:01 dev br0 self permanent
01:00:5e:00:00:01 dev br0 self permanent
7a:72:0e:c5:e1:4c dev vxlan0 master br0 permanent
02:42:0a:00:01:05 dev vxlan0 dst 172.19.188.123 link-netnsid 0 self permanent
02:42:0a:00:01:04 dev vxlan0 dst 172.19.188.123 link-netnsid 0 self permanent
da:73:88:00:81:1c dev veth0 master br0 permanent
33:33:00:00:00:01 dev veth0 self permanent
01:00:5e:00:00:01 dev veth0 self permanent
fe:43:7b:22:c2:8f dev veth1 master br0 permanent
33:33:00:00:00:01 dev veth1 self permanent
01:00:5e:00:00:01 dev veth1 self permanent

可以看到要想去02:42:0a:00:01:0502:42:0a:00:01:04这两个MAC地址需要通过172.19.188.123(node2),那么这两个MAC地址对应的ip是多少呢?

执行ip neigh,该指令效果等同于arp,即其会将ip地址解析成mac网卡地址。

$ sudo nsenter --net="/run/docker/netns/1-ysbj86zsjo" ip neigh
10.0.1.4 dev vxlan0 lladdr 02:42:0a:00:01:04 PERMANENT
10.0.1.5 dev vxlan0 lladdr 02:42:0a:00:01:05 PERMANENT

通过上述两个指令获取到对应结果信息后,我们的overlay网络需要发送数据包到app.2(10.0.1.4),根据arp解析后得知其发送的mac地址为02:42:0a:00:01:04,然后在fdb表中又得知了其映射的ip地址为172.19.188.123(node2),那么vxlan交换机就可以将这两个信息和数据包封装成VTEP包,发往172.19.188.123(node2)。

当node2收到这个VTEP包时,同样根据这两个表的数据进行解包,最后将数据包交给app.2(10.0.1.4)这个容器。


http://www.ppmy.cn/news/1260445.html

相关文章

conda旧环境快速复制新环境

在conda/envs下复制原始环境文件夹&#xff08;test&#xff09;到当前目录目标文件夹&#xff08;test_new&#xff09;修改目标文件夹中pip文件的python路径 可以先激活新环境 conda activate test_new参看pip地址 which pip&#xff0c;输出可能是~/miniconda3/envs/test_n…

SpringBoot使用自定义注解、AOP实现API接口日志记录

在后端服务中&#xff0c;对接口的每次请求入参、方法、出参、执行耗时等信息进行日志打印或记录&#xff0c;是很有必要的。有了日志记录&#xff0c;在后端服务出现问题的时候&#xff0c;可以快速定位问题所在&#xff0c;或者可以通过日志异常快速提醒相关人员进行服务维护…

Gitlab 安装手册

MD[Gitlab 安装手册] Gitlab 安装手册 说明: Gitlab最低配置1核2g,建议配置2核4g以上且单独部署,如有多项目CI/CD要求,可以4核8g 1. 安装相关依赖(安装policycoreutils) [rootsjclinux ~]# yum -y install policycoreutils openssh-server openssh-clients postfix 2. 启动s…

【Java】实现顺序表基本的操作(数据结构)

文章目录 前言顺序表1、打印顺序表2、增加元素3、在任意位置增加元素4、判断是否包含某个元素5、查找某个元素对于的位置6、获取任意位置的元素7、将任意位置的元素设为value8、删除第一次出现的关键字9、获取顺序表长度10、清空顺序表总结 前言 在了解顺序表之前我们要先了解…

编织魔法世界——计算机科学的奇幻之旅

文章目录 每日一句正能量前言为什么当初选择计算机行业计算机对自己人生道路的影响后记 每日一句正能量 人生就像赛跑&#xff0c;不在乎你是否第一个到达尽头&#xff0c;而在乎你有没有跑完全程。 前言 计算机是一个神奇的领域&#xff0c;它可以让人们创造出炫酷的虚拟世界…

Linux-网络服务和端口

域名&#xff1a;便于人们记忆和使用的标识符 www.baidu.com域名解析&#xff1a;将域名转换为与之对应的 IP 地址的过程 nameserver 8.8.8.8ip地址&#xff1a;网络设备的唯一数字标识符 域名ip地址localhost127.0.0.1 网络服务和端口 网络服务端口ftp21ssh22http80https…

ERP和MES的区别与联系,这篇接地气的文章终于讲明白了!

一、ERP和MES之间的“区别” ERP和MES系统在企业管理中都扮演着重要的角色&#xff0c;但它们的功能和职责各有不同。 既然今天要聊ERP和MES的区别&#xff0c;那肯定要给大家讲明白了才行。 所以&#xff0c;这里首先得从工厂的业务模式说起。 作为一个工厂&#xff0c;存…

深入理解mysql的explain命令

1 基础 全网最全 | MySQL EXPLAIN 完全解读 1.1 MySQL中EXPLAIN命令提供的字段包括&#xff1a; id&#xff1a;查询的标识符。select_type&#xff1a;查询的类型&#xff08;如SIMPLE, PRIMARY, SUBQUERY等&#xff09;。table&#xff1a;查询的是哪个表。partitions&…