搞定 Kubernetes 基于flannel 的集群网络

Posted K8S中文社区

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了搞定 Kubernetes 基于flannel 的集群网络相关的知识,希望对你有一定的参考价值。

一、Docker网络模式

在讨论Kubernetes网络之前,让我们先来看一下Docker网络。Docker采用插件化的网络模式,默认提供bridge、host、none、overlay、maclan和Network plugins这几种网络模式,运行容器时可以通过–network参数设置具体使用那一种模式。

  • bridge:这是Docker默认的网络驱动,此模式会为每一个容器分配Network Namespace和设置IP等,并将容器连接到一个虚拟网桥上。如果未指定网络驱动,这默认使用此驱动。

  • host:此网络驱动直接使用宿主机的网络。

  • none:此驱动不构造网络环境。采用了none 网络驱动,那么就只能使用loopback网络设备,容器只能使用127.0.0.1的本机网络。

  • overlay:此网络驱动可以使多个Docker daemons连接在一起,并能够使用swarm服务之间进行通讯。也可以使用overlay网络进行swarm服务和容器之间、容器之间进行通讯,

  • Network plugins:可以安装和使用第三方的网络插件。可以在Docker Store或第三方供应商处获取这些插件

在默认情况,Docker使用bridge网络模式,bridge网络驱动的示意图如下,此文以bridge模式对Docker的网络进行说明。

搞定 Kubernetes 基于flannel 的集群网络

1.1 bridge网络的构建过程如下:


通过 ifconfig 命令可以查看docker0网桥的信息:


搞定 Kubernetes 基于flannel 的集群网络

通过 docker network inspect bridge 可以查看网桥的子网网络范围和网关:

搞定 Kubernetes 基于flannel 的集群网络

2)运行容器时,在宿主机上创建虚拟网卡veth pair设备,veth pair设备是成对出现的,从而组成一个数据通道,数据从一个设备进入,就会从另一个设备出来。将veth pair设备的一端放在新创建的容器中,命名为eth0;另一端放在宿主机的docker0中,以veth为前缀的名字命名。通过 brctl show 命令查看放在docker0中的veth pair设备

搞定 Kubernetes 基于flannel 的集群网络

1.2 外部访问

bridge的docker0是虚拟出来的网桥,因此无法被外部的网络访问。因此需要在运行容器时通过-p和-P参数对将容器的端口映射到宿主机的端口。实际上Docker是采用 NAT的 方式,将容器内部的服务监听端口与宿主机的某一个端口port 进行绑定,使得宿主机外部可以将网络报文发送至容器。

1)通过-P参数,将容器的端口映射到宿主机的随机端口:

$ docker run -P {images}

2)通过-p参数,将容器的端口映射到宿主机的制定端口:

$ docker run -p {hostPort}:{containerPort} {images}

二、Kubernetes网络模式

Kubernetes与Docker网络有些不同。Kubernetes网络需要解决下面的4个问题:

集群内:

    容器与容器之间的通信

    Pod和Pod之间的通信

    Pod和服务之间的通信

集群外:

    外部应用与服务之间的通信

在本文主要分析容器与容器之间,以及Pod和Pod之间的通信;Pod和服务之间,以及外部应用与服务之间的通信请参考《Kubernetes-核心资源之Service》和《Kubernetes-核心资源之Ingress》。

2.1 同一个Pod中容器之间的通信

2.2 不同Pod中容器之间的通信

对于此场景,情况现对比较复杂一些,这就需要解决Pod间的通信问题。在Kubernetes通过flannel、calic等网络插件解决Pod间的通信问题。本文以flannel为例说明在Kubernetes中网络模型,flannel是kubernetes默认提供网络插件。Flannel是由CoreOS团队开发社交的网络工具,CoreOS团队采用L3 Overlay模式设计flannel, 规定宿主机下各个Pod属于同一个子网,不同宿主机下的Pod属于不同的子网。

搞定 Kubernetes 基于flannel 的集群网络

看一下flannel在Kubernetes中运行的整体过程:

1)设置集群网络

flannel默认使用etcd作为配置和协调中心,首先使用etcd设置集群的整体网络。通过如下的命令能够查询网络配置信息:

$ etcdctl ls /coreos.com/network/config

2)设置Node节点上的子网

基于在etcd中设置的网络,flannel为每一个Node分配IP子网。

#获取子网列表

$ etcdctl ls /coreos.com/network/subnets

#获取子网信息

$ etcdctl ls /coreos.com/network/subnets/{IP网段}

3)在每个Node上启动flannelid

flannel在每个Node上启动了一个flanneld的服务在flanneld启动后,将从etcd中读取配置信息,并请求获取子网的租约。所有Node上的flanneld都依赖etcd cluster来做集中配置服务,etcd保证了所有node上flanned所看到的配置是一致的。同时每个node上的flanned监听etcd上的数据变化,实时感知集群中node的变化。flanneld一旦获取子网租约、配置后端后,会将一些信息写入/run/flannel/subnet.env文件。

$ cat /var/run/flannel/subnet.env

搞定 Kubernetes 基于flannel 的集群网络

4)创建虚拟网卡

在Node节点上,会创建一个名为flannel.1的虚拟网卡。

$ ip addr show flannel.1

搞定 Kubernetes 基于flannel 的集群网络

5)创建Docker网桥

$ ip addr show docker0

6)修改路由表

flannel会对路由表进行修改,从而能够实现容器跨主机的通信。

$ route -n

2.3 数据传递过程

在源容器宿主机中的数据传递过程:

1)源容器向目标容器发送数据,数据首先发送给docker0网桥

在源容器内容查看路由信息:

$ kubectl exec -it -p {Podid} -c {ContainerId} -- ip route

2)docker0网桥接受到数据后,将其转交给flannel.1虚拟网卡处理

查看源容器所在Node的路由信息:

$ ip route

3)flannel.1接受到数据后,对数据进行封装,并发给宿主机的eth0

flannel.1收到数据后,flannelid会将数据包封装成二层以太包。

Ethernet Header的信息:

4)对在flannel路由节点封装后的数据,进行再封装后,转发给目标容器Node的eth0

由于目前的数据包只是vxlan tunnel上的数据包,因此还不能在物理网络上进行传输。因此,需要将上述数据包再次进行封装,才能源容器节点传输到目标容器节点,这项工作在由linux内核来完成。

Ethernet Header的信息:

IP Header的信息:

通过此次封装,就可以通过物理网络发送数据包。

在目标容器宿主机中的数据传递过程:

5)目标容器宿主机的eth0接收到数据后,对数据包进行拆封,并转发给flannel.1虚拟网卡;

6)flannel.1 虚拟网卡接受到数据,将数据发送给docker0网桥;

7)最后,数据到达目标容器,完成容器之间的数据通信。

参考资料

作者简介:
季向远,北京神舟航天软件技术有限公司产品经理。本文版权归原作者所有。


---END---

K8S培训推荐

Kubernetes线下实战培训,采用3+1新的培训模式(3天线下实战培训,1年内可免费再次参加),资深一线讲师,实操环境实践,现场答疑互动,培训内容覆盖:Docker架构、镜像、数据存储、网络、以及最佳实践。Kubernetes实战内容,Kubernetes设计、Pod、常用对象操作,Kuberentes调度系统、QoS、Helm、网络、存储、CI/CD、日志监控等。<>

北京场:12月28-30日,上海场:1月4-6日;

以上是关于搞定 Kubernetes 基于flannel 的集群网络的主要内容,如果未能解决你的问题,请参考以下文章

Kubernetes二进制部署——Flannel网络

Kubernetes二进制部署——Flannel网络

Kubernetes二进制部署——Flannel网络

Kubernetes二进制部署——Flannel网络

Kubernetes之NetworkPolicy,Flannel和Calico

Kubernetes — Flannel CNI