Skip to content

Commit

Permalink
update 白话kubernetes网络组件flannel
Browse files Browse the repository at this point in the history
  • Loading branch information
yangpeng14 committed Apr 2, 2020
1 parent 3669b20 commit 88b8729
Show file tree
Hide file tree
Showing 3 changed files with 42 additions and 61 deletions.
Binary file added img/flannel-host-gw-1.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file removed img/flannel-host-gw.png
Binary file not shown.
103 changes: 42 additions & 61 deletions kubernetes/白话kubernetes网络组件flannel.md
Original file line number Diff line number Diff line change
@@ -1,108 +1,89 @@
## 前言

今天来聊聊 `Flannel``Flannel``Kubernetes` 默认网络组件,在聊 `Flannel` 时,我们得先明白一个叫 `CNI` 东东,`CNI` 是什么?做什么用的?下文会做出解释。
今天来聊聊 `Flannel``Flannel``Kubernetes` 默认网络组件,再聊 `Flannel` 时,我们得先明白一个叫 `CNI` 东东,`CNI` 是什么?能有什么用?下文会做出解释。

## CNI 简单介绍

`CNI`(Container Network Interface)是CNCF旗下的一个项目,由一组用于配置Linux容器的网络接口的规范和库组成,同时还包含了一些插件。CNI仅关心容器创建时的网络分配和当容器被删除时释放网络资源。Kubernetes 中已经内置了 `CNI`
`CNI`(Container Network Interface)`CNCF` 旗下的一个项目,由一组用于配置Linux容器网络接口的规范和库组成,同时还包含了一些插件。`CNI` 仅关心容器创建时的网络分配和当容器被删除时释放网络资源。Kubernetes 中已经内置了 `CNI`

`Container Runtime` 在创建容器时,先创建好 `network namespace`,然后调用CNI插件为这个 `network namespace` 配置网络,其后再启动容器内的进程。已成为 `CNCF` 一员,成为 `CNCF` 主推的网络模型。
`Container Runtime` 在创建容器时,先创建好 `network namespace`,然后调用CNI插件为这个 `network namespace` 配置网络,其后再启动容器内的进程。`CNI` 已成为 `CNCF` 一员,成为 `CNCF` 主推的网络模型。

> `CNI` 项目地址 https://github.com/containernetworking/cni
Kubernetes Pod 中的其他容器都是Pod所属 `Pause` 容器的网络,创建过程为:

- 1. kubelet 先创建pause容器生成network namespace
- 2. 调用网络CNI driver
- 3. CNI driver 根据配置调用具体的cni 插件
- 4. cni 插件给pause 容器配置网络
- 5. pod 中其他的容器都使用 pause 容器的网络
- 1.kubelet 先创建pause容器生成network namespace
- 2.调用网络CNI driver
- 3.CNI driver 根据配置调用具体的cni 插件
- 4.cni 插件给pause 容器配置网络
- 5.pod 中其他的容器都使用 pause 容器的网络

## Flannel 简介

`Flannel` 是CoreOS团队针对 Kubernetes 设计的一个网络规划服务,简单来说,它的功能是让集群中的不同节点主机创建的Docker 容器都具有全集群唯一的虚拟IP地址。它基于Linux TUN/TAP,使用UDP封装IP包来创建overlay网络,并借助etcd维护网络的分配情况。


## Flannel 原理

Flannel 实质上是一种 `覆盖网络(overlay network)`,也就是将TCP数据包装在另一种网络包里面进行路由转发和通信,目前已经支持 `UDP``VxLAN``Host Gw``AWS VPC``GCE``Ali Vpc`路由等数据转发方式。

- `udp`:使用用户态udp封装,默认使用8285端口。由于是在用户态封装和解包,性能上有较大的损失
- `vxlan`:vxlan封装,需要配置VNI,Port(默认8472)和GBP
- `host-gw`:直接路由的方式,将容器网络的路由信息直接更新到主机的路由表中,仅适用于二层直接可达的网络 推荐使用,效率极高
- `aws-vpc`:使用 Amazon VPC route table 创建路由,适用于AWS上运行的容器
- `gce`:使用Google Compute Engine Network创建路由,所有instance需要开启IP forwarding,适用于GCE上运行的容器
- `ali-vpc`:使用阿里云VPC route table 创建路由,适用于阿里云上运行的容器
- `udp`:使用用户态udp封装,默认使用8285端口。由于是在用户态封装和解包,性能上有较大的损失,不推荐使用。
- `vxlan`:vxlan封装,需要配置VNI,Port(默认8472)[GBP](https://github.com/torvalds/linux/commit/3511494ce2f3d3b77544c79b87511a4ddb61dc89)
- `host-gw`:直接路由的方式,将容器网络的路由信息直接更新到主机的路由表中,仅适用于二层直接可达的网络推荐使用,效率极高
- `aws-vpc`:使用 Amazon VPC route table 创建路由,适用于AWS上运行的容器
- `gce`:使用Google Compute Engine Network创建路由,所有instance需要开启IP forwarding,适用于GCE上运行的容器
- `ali-vpc`:使用阿里云VPC route table 创建路由,适用于阿里云上运行的容器

本文介绍下 `vxlan``host-gw` 数据转发方式
## Flannel 架构简介

### Vxlan 模式
本文主要介绍下 `vxlan``host-gw` 数据转发方式

VXLAN 是Linux内核本身支持的一种网络虚拟化技术,是内核的一个模块,在内核态实现封装解封装,构建出覆盖网络,其实就是一个由各宿主机上的Flannel.1设备组成的虚拟二层网络,由于VXLAN由于额外的封包解包,导致其性能较差。
### Vxlan 模式

![](/img/flannel-vxlan.png)

### Host-gw 模式
flannel默认使用 `8285` 端口作为 `UDP` 封装报文的端口,`VxLan` 使用 `8472` 端口。

在主机路由表中创建到其它主机 subnet 路由条目,从而实现容器跨主机通信
> 两个节点中容器是如何相互通信的呢?
![](/img/flannel-host-gw.png)
- 1.假如 Frontend1 Pod(10.1.15.2/24) 要访问 Backend Service1 Pod(10.1.20.2/24),默认会通过容器内部的 eth0 发送出去
- 2.报文通过 `veth pair` 被发送到 `vethXXX`
- 3.`vethXXX` 是直接连接到虚拟交换机 `docker0` 网卡,报文通过虚拟 `bridge docker0` 网卡发送出去
- 4.查找路由表,外部容器ip的报文都会转发到 `flannel0` 虚拟网卡,这是一个 `P2P` 虚拟网卡,然后报文就被转发到监听在另一端的 `flanneld`
- 5.`flanneld` 通过 `etcd` 维护了各个节点之间的路由表,把原来的报文 `UDP` 封装一层,通过配置的 `iface` 发送出去
- 6.报文通过主机之间的网络找到目标Backend Service1 Pod(10.1.20.2/24)主机
- 7.报文继续往上,到传输层,交给监听在8285端口的 `flanneld` 程序处理
- 8.数据被解包,然后发送给 `flannel0` 虚拟网卡
- 9.查找本机路由表,发现对应容器的报文要交给 `docker0`
- 10.`docker0` 找到 Backend Service1 Pod(10.1.20.2/24),把报文发送过去
- 11.Backend Service1 Pod 处理完报文,按上面相同的步骤发送给 Frontend1 Pod

### Vxlan Directrouting 模式
### Host-gw 模式

VXLAN 还有另外一种功能,VXLAN 也支持类似 host-gw 的模式,如果两个节点在同一网段时使用 host-gw 通信,如果不在同一网段中,即当前pod所在节点与目标pod所在节点中间有路由器,就使用VXLAN这种方式,使用叠加网络。
![](/img/flannel-host-gw-1.png)

结合了 Host-gw 和 VXLAN ,这就是 VXLAN 的 Directrouting 模式
在主机路由表中创建到其它主机 subnet 路由条目,从而实现容器跨主机通信

```
$ etcdctl set /coreos.com/network/config'{"Network": "172.16.0.0/16", "Backend": {"Type": "VxLAN","Directrouting": true}}'
```
`Host-gw` 是把每个节点都当成一个网关,它会加入其它节点并设成网关,当数据包到达这个节点的时候,就根据路由表发送到下一跳,也就是节点IP,`各个节点必须是同一个网段`,直接通过2层把这个数据转发到另一个节点上,另一个节点再根据本机路由规则转发到docker0网桥,docker0网桥根据2层又转发到容器里面。一个是数据的流入,就是当数据包到达这个节点之后,然后发给谁,这是流入数据包。一个是数据包的流出,当从节点出来的数据包,应该转发到哪个node上,这些都是由flannel去维护的。

## 与 Docker集成
`局限`:每个node节点在2层都能通信,否则下一跳转发不过去,但是它的性能要比vxlan的性能高很多,不需要封包解封包,这种接近原生,性能也是最好的。

```bash
$ source /run/flannel/subnet.env
$ docker daemon --bip=${FLANNEL_SUBNET} --mtu=${FLANNEL_MTU} &
```
### Vxlan Directrouting 模式

## 与 CNI 集成
VXLAN 还有另外一种功能,VXLAN 也支持类似 host-gw 的模式,如果两个节点在同一网段时使用 host-gw 通信,如果不在同一网段中,即当前pod所在节点与目标pod所在节点中间有路由器,就使用VXLAN这种方式,使用叠加网络。

CNI flannel 插件会将flannel网络配置转换为`bridge`插件配置,并调用`bridge`插件给容器 network namespace 配置网络。比如下面的flannel配置
结合了 Host-gw 和 VXLAN ,这就是 VXLAN 的 Directrouting 模式。

```json
{
"name": "mynet",
"type": "flannel",
"delegate": {
"bridge": "mynet0",
"mtu": 1400
}
}
```

会被cni flannel插件转换为

```json
{
"name": "mynet",
"type": "bridge",
"mtu": 1472,
"ipMasq": false,
"isGateway": true,
"ipam": {
"type": "host-local",
"subnet": "10.1.17.0/24"
}
}
$ etcdctl set /coreos.com/network/config '{"Network": "172.16.0.0/16", "Backend": {"Type": "VxLAN","Directrouting": true}}'
```

## 与 Kubernetes 集成

## 总结

在 Kubernetes 中,网络插件选择 `Flannel` 时。所有节点都在同一个网段,并且二层网络可能通信,可以考虑选择 `Host-gw` 模式。反之节点之间不能通过二层网络通信,可能在不同 `vlan` 中,可以考虑选择 `Vxlan` 模式,也可以考虑使用 `Vxlan Directrouting` 模式(默认是 false)。

## 参考链接

- https://github.com/coreos/flannel
- https://sdn.feisky.xyz/rong-qi-wang-luo/index/index/index
- https://sdn.feisky.xyz/rong-qi-wang-luo/index/index/index-1
- https://www.wqblogs.com/2019/11/29/flannel%E5%B7%A5%E4%BD%9C%E5%8E%9F%E7%90%86
- https://blog.51cto.com/14143894/2462379

0 comments on commit 88b8729

Please sign in to comment.