[Kubernetes][Kubernetes容器网络2]深入解析容器跨主机网络

目录

  • 深入解析容器跨主机网络

    • Flannel

      • Flannel UDP模式基本原理
      • UDP模式的缺陷
      • Flannel VXLAN 模式

深入解析容器跨主机网络



在Docker默认配置下,不同宿主机上的容器通过IP地址是无法相互通信的。

因此社区出现了很多用于解决容器跨主机通信问题的方案。

Flannel

Flannel 支持三种后端实现:

  1. VXLAN
  2. host-gw
  3. UDP

先以 UDP 模式为例

Flannel UDP模式基本原理

假设有两台宿主机:

  • Node1: container-1,IP 地址为 100.96.1.2,对应的 docker0 网桥的地址是 100.96.1.1/24
  • Node2:container-2,IP 地址为 100.96.2.3,对应的 docker0 网桥的地址为 100.96.2.1/24

如果 container-1 要和 container-2 通信,那么进程发起的 IP 包的目的地址为 100.96.2.3,该 IP datagram 被 docker0 转发到宿主机,Node-1 根据宿主机的路由表来决定该 IP 包的下一跳 IP 地址。

位于Node-1上的Flannel预先在Node-1上添加一系列路由规则,如下:

# 在Node 1上
$ ip route
default via 10.168.0.1 dev eth0
100.96.0.0/16 dev flannel0  proto kernel  scope link  src 100.96.1.0
100.96.1.0/24 dev docker0  proto kernel  scope link  src 100.96.1.1
10.168.0.0/24 dev eth0  proto kernel  scope link  src 10.168.0.2

可以看到,根据该路由表,目的 IP 为 100.96.2.3 的 IP 包会被发送给本机的 flannel0 接口。

这个flannel0接口是一个 TUN 设备(Tunnel 设备)。

在 Linux 中,TUN 设备是一个工作在网络层的虚拟网络设备,该设备的功能是在内核和用户应用进程之间传递 IP 包。这个用户应用进程就是创建了该 TUN 设备的进程,在我们这里当然就是宿主机上的 Flannel 进程。

所以,到这里,容器 container-1 发送的目的地址为 100.96.2.3 的 IP 包就被 Flannel 进程捕获,该 Flannel 进程在宿主机上的名称为 flanneld。

flanneld 需要根据该目的 IP,找到 Node-2 的 IP 地址才能继续进行转发。

这里就需要 Flannel 项目中的另一个非常重要的概念:子网。

在 Flannel 项目中,一台宿主机上的所有容器,都属于该宿主机被分配的一个子网,该子网地址就是该宿主机上 docker0 网桥的入口地址。比如在 Node-1 上,docker0 网桥所代表的子网的网络地址为 100.96.1.0/24,在 Node-2 上,docker0 网桥所代表的子网的网络地址为 100.96.2.0/24。

而这个对应关系是由Flannel项目维护的,所以站在上帝视角的 flanneld 进程通过 IP 包的目的地址就知道了目的 IP 所在的子网地址,它将所有的宿主机和子网地址的对应关系保存在 ETCD 中,就可以通过目的 IP 所在的子网地址找到该子网所在的节点。

$ etcdctl ls /coreos.com/network/subnets
/coreos.com/network/subnets/100.96.1.0-24
/coreos.com/network/subnets/100.96.2.0-24
/coreos.com/network/subnets/100.96.3.0-24

上面的指令查看出容器IP和子网的对应关系,100.96.2.3 所在的子网为 100.96.2.0/24

$ etcdctl get /coreos.com/network/subnets/100.96.2.0-24
{"PublicIP":"10.168.0.3"}

根据该子网地址,同样可以在 ETCD 中找到对应节点的 IP 地址为 10.168.0.3

在获得这个 IP 地址之后,flanneld 将原来的 IP 包封装进一个目的 IP 为 10.168.0.3 的 UDP 包,然后经过宿主机发送给 Node-2。此时,这个 UDP 包的源地址一定为 Node-1 节点的 IP 地址。当然,作为应用层的 flanneld 进程需要监听一个端口以捕获该 UDP 包中的内容,flanneld 进程的监听端口为 8285

当这个 UDP 包被发送到 Node-2 之后,首先经过 Node-2 上网络栈的层层解封,flanneld 进程将会获得 container-1 发出的 IP 包,然后它将该 IP 包通过 flanel0 接口再次发送给 Node-2 上的网络协议栈,Node-2 上的路由表:

# 在Node 2上
$ ip route
default via 10.168.0.1 dev eth0
100.96.0.0/16 dev flannel0  proto kernel  scope link  src 100.96.2.0
100.96.2.0/24 dev docker0  proto kernel  scope link  src 100.96.2.1
10.168.0.0/24 dev eth0  proto kernel  scope link  src 10.168.0.3

Node-2 的网络协议栈将该 IP 包匹配路由规则后,首先通过 docker0 向子网 100.96.2.0/24 上的所有设备发送一个 ARP 请求,获得 100.96.2.3 的对应的 MAC 地址后,将该数据包发送给二层的虚拟交换机 docker0 网桥,docker0 网络将该数据包转发给 container-2 容器,然后 container-2 容器的网络栈层层解封装,将数据最终传递给 container-2 容器中的某个进程。

基本原理图:

UDP模式的缺陷

我们可以看到,实际上 Flannel 项目最关键的步骤都是由 flanneld 进程完成的,该进程从 Linux 内核网络协议栈的网络层直接获取 IP 包,然后利用保存在 etcd 中的映射关系,重新将该 IP 包作为数据,封装出一个新的 UDP 包,再将该 UDP 包通过宿主机网络栈发送到目的主机,再考虑数据从 container-1 通过 eth0 发送的过程,仅发送阶段,数据就需要在用户进程和内核之间拷贝三次。

在 Linux 中,用户态操作以及数据在用户态和内核态之间的拷贝的代价是比较高的。这正是 Flannel UDP 模式性能不好的原因。

我们需要减少用户态和内核态的切换次数,并且把核心的处理逻辑都放在内核态进行。

Flannel VXLAN 模式

VXLAN:Virtual Extensible LAN(虚拟可扩展局域网),是Linux内核中支持的一种网络虚拟化技术。

其基本思想是在现有的三层网络之上,“覆盖”一层虚拟的、由内核中的VXLAN模块维护的二层网络,使得连接在这个二层网络上的所有设备(网络适配器)可以像在同一个LAN中那样自由通信。

VETP设备,同时具有IP地址也有MAC地址,可以被理解成一个虚拟网络适配器。VETP设备被连接到我们前述的虚拟的二层网络之上。

和 UDP 模式一样,容器内的进程通过 ARP 获得连接在docker0网桥上的VETP设备flannel.1的MAC地址,然后将容器内的Inner IP datagram封装进一个二层数据帧,docker0将该数据帧转发到flannel.1接口。

flannel.1收到该二层数据帧之后,通过Node-1的网络协议栈,将该数据帧解封,Node-1得到Inner IP datagram。同样,Node-1 上的 flannel 进程会在 Node-2 启动并且加入 Flannel 网络之后,在网络内所有节点上添加一条如下的路由规则:

$ route -n
Kernel IP routing table
Destination     Gateway         Genmask         Flags Metric Ref    Use Iface
...
10.1.16.0       10.1.16.0       255.255.255.0   UG    0      0        0 flannel.1

对照该规则,目的地址为 10.1.16.3 的 IP 数据包应该通过接口 flannel.1(源VETP设备) 发往网关 10.1.16.0,该目的网关正是 Node-2 的 flannel.1(目的VETP设备) 接口的 IP 地址,同时,在Node-2启动并且加入Flannel网络时,我们在Node-1上添加一条ARP table entry如下:

# 在Node 1上
$ ip neigh show dev flannel.1
10.1.16.0 lladdr 5e:f8:4f:00:e3:37 PERMANENT

这样我们就知道了目的VETP设备的MAC地址为5e:f8:4f:00:e3:37,IP地址为10.1.16.0。有了这个MAC地址,我们可以构建一个二层数据帧,目的MAC地址为5e:f8:4f:00:e3:37,其中IP datagram 中的目的IP 为10.1.16.0。

到这一步,根据计算机网络的知识。我们已经预设Node-1和Node-2上的VETP设备(理解为网络适配器)都“插”在了这个虚拟二层网络VXLAN之上,那么我们通过这个二层数据包就应当能够完成链路层的工作,目的VETP设备就可以获得该二层数据包。

VXLAN 的内部原理

至于该二层数据包是如何通过宿主机,利用实际网络进行传送的,则是内核中的VXLAN模块完成的。

我们前面所使用的所有的IP地址以及MAC地址,实际上对于宿主机网络来说并没有什么意义。因为这些设备都是“虚拟的”。

将前面得到的二层数据帧称为“内部数据帧”。所以我们需要将内部数据帧,作为数据,封装进UDP包,在真实宿主机网络上进行传输。

Linux内核会在“内部数据帧”之前田间一个特殊的VXLAN头,表示该数据是一个VXLAN要使用的数据帧,这样当目的主机网络栈进行解封的时候,就可以将该数据帧传递给它自己的VXLAN。

然后,Linux内核会将该数据帧封装进一个UDP包里面。

我们现在知道“虚拟的”VXLAN接口的MAC地址,还需要目的主机真实的IP地址才能继续。

flannel进程预先为我们维护了这个映射关系

# 在Node 1上,使用“目的VTEP设备”的MAC地址进行查询
$ bridge fdb show flannel.1 | grep 5e:f8:4f:00:e3:37
5e:f8:4f:00:e3:37 dev flannel.1 dst 10.168.0.3 self permanent

通过FDB转发数据库,我们可以查询到,目的主机的IP地址为10.168.0.3。接下来的流程就是正常的、宿主机网络上的封包工作。

目的主机上的收尾工作

当上述“外部数据帧”通过宿主机网络传递到目的主机的网络适配器之后,Node-2的内核网络栈将数据包逐步解封,一直到内核中的UDP模块获取到VXLAN头,根据其中的信息,决定将剩余数据帧转发给Node-2上的VETP设备,该设备(虚拟网络适配器)解封,获得 Inner IP datagram,然后根据其中的IP地址,通过ARP获得目的容器的eth0的MAC地址,再利用docker0进行转发,完成最后的步骤。

原文地址:https://www.cnblogs.com/hezhiqiangTS/p/11791244.html

时间: 2024-11-10 13:21:50

[Kubernetes][Kubernetes容器网络2]深入解析容器跨主机网络的相关文章

跨主机网络概述 - 每天5分钟玩转 Docker 容器技术(48)

前面已经学习了 Docker 的几种网络方案:none.host.bridge 和 joined 容器,它们解决了单个 Docker Host 内容器通信的问题.本章的重点则是讨论跨主机容器间通信的方案. 跨主机网络方案包括: docker 原生的 overlay 和 macvlan. 第三方方案:常用的包括 flannel.weave 和 calico. docker 网络是一个非常活跃的技术领域,不断有新的方案开发出来,那么要问个非常重要的问题了: 如此众多的方案是如何与 docker 集成

Docker网络之部署跨主机网络overlay

dcoker网络: none网络:什么都没有的网络.它的是使用常见:封闭空间意味着隔离,安全,比如生成随机码.host网络:网络配置与dockerhost完全相同.应用场景:性能好,但是没有灵活性,容易出现端口冲突问题.brigde网络: 默认的网络驱动默认,用以实现主机网络接口与虚拟网络接口间的通信. 部署网络的基本操作命令: //查看docker服务器中的网络:[[email protected] ~]# docker network ls//查看桥接网络:[[email protected

centos7下安装docker(14.2跨主机网络-overlay)

为支持容器跨主机通信,Docker提供了overlay driver,使用户可以创建基于VxLAN的overlay网络.VxLAN可将二层数据封装到UDP进行传输,VxLAN提供与VLAN相同的以太网二层服务,但是拥有更强的扩展性和灵活性. Docker overlay网络需要一个key-value数据库用于保存网络信息状态,包括Network,Endpoint,IP等.Consul,Etcd和Zookeeper都是docker支持的key-value软件,今天讨论的是consul 试验环境描述

跨主机网络-overlay(18)

docker overlay跨主机网络 1.环境 docker版本 Docker version 18.02.0-ce, build fc4de44 3台主机 192.168.55.51 host1 192.168.55.52 host2 192.168.55.53 host2 2.部署Consul Docerk overlay 网络需要一个 key-value 数据库用于保存网络状态信息,包括 Network.Endpoint.IP 等.Consul.Etcd 和 ZooKeeper 都是 D

Docker 跨主机网络(十六)

一.跨主机网络概述 前面已经学习了 Docker 的几种网络方案:none.host.bridge 和 joined 容器,它们解决了单个 Docker Host 内容器通信的问题.本章的重点则是讨论跨主机容器间通信的方案. docker 原生的 overlay 和 macvlan.第三方方案:常用的包括 flannel.weave 和 calico. 二.准备 overlay 环境 为支持容器跨主机通信,Docker 提供了 overlay driver.Docerk overlay 网络需要

docker的跨主机网络Overlay,MacVlan网络的实现

让外网能否访问容器的端口映射方法: 1.手动指定端口映射关系 两台虚拟机,第一台映射端口(第二台访问宿主机端口,就是访问容器端口 curl 192.168.1.1:90 .)docker run -itd --name web1 -p 90:80 nginx:latest 2>从宿主机随机映射端口到容器,docker run -itd --name web2 -p 80 nginx:latest 3>从宿主机随机映射端口到容器,容器内所有暴漏端口,都会一一映射.docker run -itd

centos7下安装docker(15.3跨主机网络-macvlan)

除了ovrlay,docker还开发了另一个支持跨主机容器的driver:macvlan macvlan本身是linu kernel模块,其功能是允许在同一物理网卡上配置多了MAC地址,即:多个interface,每个interface可以配置自己的ip.macvlan本身是一种网卡虚拟化技术,Docker用macvlan实现容器网络就不奇怪了 macvlan最大的优点是性能极好,相比其他方案,macvlan不需要创建Linux bridge,而是直接通过以太interface连接到物理网络.

centos7下安装docker(15.6docker跨主机网络---Weave)

Weave是weaveworks开发的容器网络解决方案.weave创建的虚拟网络可以将部署在多个主机上的容器连接起来.对于容器来说,weave就像一个巨大的网络交换机,容器可以直接通信,无需NAT和端口映射.除此之外,weave的DNS模块是容器可以通过hostname访问 weave不依赖分布式数据库(例如:consul和etcd)交换网络信息,每个主机上只需要运行weave组件就能建立起跨主机容器网络,weave网络能够穿透防火墙并运行在部分连接的网络上,weave支持加密网络接连,用户可以

Docker跨主机网络联通之etcd实现

搭建ETCD集群 查看NODE1机器IP,并启动ETCD ubuntu@docker-node1:~$ ifconfig eth0 eth0: flags=4163<UP,BROADCAST,RUNNING,MULTICAST> mtu 1450 inet 172.16.1.15 netmask 255.255.255.0 broadcast 172.16.1.255 inet6 fe80::f816:3eff:fe33:11a8 prefixlen 64 scopeid 0x20<li