kubernetes网络通信

  • 容器间的通信   pod内的容器通信(lo)
  • Pod之间的通信   pod IP <-----> pod IP
  • Pod与Service之间的通信 podIP <-----> ClusterIP
  • Service与集群外部的通信 ClusterIP <-----> 集群外部

CNI插件:

  • flannel
  • calico
  • canel
  • kube-route

解决方案:

  • 虚拟网桥
  • 多路复用  MacVLAN
  • 硬件交换  SR-IOV

Flannel

Flannel本身是一个框架,真正提供网络功能是他的后端实现。目前支持三种后端实现:

  • VXLAN
  • host-gw
  • UDP

UDP

UDP模式是Flannel早期支持的一种方式,却也是性能最差的一种方式。所以现在基本都弃用了。但是这种模式是最直接最容易理解的一种方式。

Node1的容器访问Node2的容器,Node1容器访问的目的地址不是在容器的路由规则里,所以会走默认路由到达宿主机的docker0 网桥上,从而出现在宿主机上,这个时候这个IP的下一步取决于这台宿主机的路由规则,这时候这条会使用flannel0的设备上,flannel是一个TUN设备,在Linux中,TUN设备是一种工作在三层的虚拟网络设备,TUN设备的功能是在操作系统内核和应用程序之间传递IP包。

当操作系统将一个IP包发送给flannel0设备后,flannel0 就会把IP包交给创建这个设备的应用程序,也就是flannel进行。这就是从内核态(Linux操作系统)到用户态(Flannel进程)的流动方向。

反之,如果flannel进程向flannel0设备发送一个IP包,那么这个IP包就会出现在宿主机网络栈,然后根据宿主机路由表进行下一步处理,这是用户态向内核态流动方向。

所以,当IP包从容器经过docker0出现在宿主机上,然后又根据宿主机路由表进入flannel0设备后,宿主机上的flannel进程就会收到这个IP包。然后,flannel看到了这个IP包的目的地址,就可以把他发送到Node2宿主机上。

flannel是如何知道目的IP地址对应的容器是运行在Node2上

源于flannel里的一个重要概念子网(Subnet)。事实上,在由Flannel管理的容器网络里,一台宿主机上的所有容器都属于该宿主机被分配的一个“子网”,所以flannel会根据目的IP地址找到对应的子网,从而在etcd里找到对应的宿主机。只要node1 和node2 互通,flannel进程一定会到达node2。

UDP模式的缺点

相比两台宿主机之间的直接通信,基于flannel UDP模式的容器通信网络多个一个额外的步骤,那就是flannel的处理过程,这个过程由于使用到了flannel0这个TUN设备,仅仅是发送IP包的时候,就需要三次用户态和内核态的数据拷贝。如图:

  1. 用户态容器进程发起IP包进过docker0网桥进入内核态
  2. IP包根据路由表进入TUN(flannel0)设备,从而回到用户态的flanneld进程
  3. flanneld 进行UDP封包之后重新进入内核态,将UDP包通过宿主机的eth0发出去

VXLAN

VXLAN全称虚拟可扩展局域网,是Linux内核本身就支持的一种网络虚拟化技术。所以说,VXLAN可以完全在内核态实现上述封装和解封工作,从而通过前面相似的“隧道机制”,构建出覆盖网络。

VXLAN覆盖网络的设计思想:在现有的三层网络之上,“覆盖”一层虚拟的,由内核VXLAN模块负责维护的二层网络,使得连接在这个VXLAN二层网络上的“主机”(可以是虚拟机也可以是容器)之间,可以像一个局域网里那样自由通信,当然,实际上,这些“主机”可能分布在不同的宿主机上,甚至可以分布在不同的物理机房里。

而为了能够在二层网络上打通“隧道”,VXLAN会在宿主机上设置一个特殊的网络设备作为“隧道”的两端。这个设备叫VTEP,既:虚拟隧道端点。而这个VTEP设备的作用,其实跟前面的flanneld进程非常相似。只不过,它进行封装和解封装的对象是二层数据帧。而且这个工作的执行流程全部是在内核里完成的(因为VXLAN本身就是内核模块)。如图:

从图里看每个宿主机都有一个flannel1的设备,就是VXLAN所需的VTEP设备,它既有IP地址也有MAC地址。现在我们是container1 访问 container2,相对UDP比较来看,当container1发出请求后,这个目的的地址是10.244.1.3的IP包,会先出现在docker0网桥,然后被路由到本机flanner1设备上处理,也就是说,来到了“隧道”的出口。既目的宿主机的VTEP设备。而这个设备信息正是每台宿主机上的flanneld进程负责维护的。

当所有Node启动后,我们可以在Node1 上可以看到多个flannel1 网卡的路由信息,是因为flanneld启动后创建的。

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

从上图看到10.244.1.0就是Node2的VTEP设备(就是flannel1 设备)的IP地址,而这些VTEP设备之间就需要想办法组成一个虚拟的二层网络,既:通过二层数据帧进行通信,而Node1上的VTEP设备收到原始IP包后,就要想办法把原始IP包加一个目的MAC地址,封装成二层数据帧,然后发送给目的VTEP设备。这里需要解决一个问题目的VTEP设备的MAC地址是什么?

根据路由表信息我们知道了目的VTEP设备的IP地址,而根据三层IP地址查询二层MAC地址正是ARP表的功能。而这里用ARP表的记录,也就是flanneld进程在Node2节点启动时,自动添加到Node1上的。如下:

$ ip neigh show dev flannel.
10.244.1.0 lladdr b2:ba:aa:a5::1a PERMANENT

有了这个MAC地址linux内核就可以开始二层封包了,上面提到的MAC地址,对宿主机的二层网络没有任何意义,所以上述封装的数据帧不能在宿主机的二层网络里传输,为了方便概述,我们把上述数据帧称为内部数据帧。所以Linux内核还要把内部数据帧进一步封装成宿主机网络的一个普通数据帧,好让他载着内部数据帧,通过eth0网卡进行传输。这次封装我们称为外部数据帧,为了实现这个搭便车的机制,Linux内核在封装内部数据帧前面,加上特殊的VXLAN头,用来表示这个乘客实际上是VXLAN使用的数据帧。而这个VXLAN头里有一个重要的标志VNI,它是识别某个数据帧是不是应该归属自己处理的标志。而flannel中,VNI的值是1,这也是为什么宿主机的VTEP设备都叫做flannel1的原因。这个时候linux内核会把这数据帧封装一个UDP包里发出去。虽然node1的flannel1知道node2的flannel2的MAC地址,但是不知道node2MAC的地址,也就是UDP该发往那台主机,实际上flannel1还要扮演一个网桥的角色,在二层网络进行UDP转发,而在Linux内核里面,网桥设备进行转发的依据来自FDB的转发数据库。这个flannel网桥对应的FDB信息,就是flannel进程维护的,他的内容如下:

$ bridge fdb show flannel.  | grep b2:ba:aa:a5::1a
b2:ba:aa:a5::1a dev flannel. dst 172.16.138.41 self permanent

我们可以看到发往的IP地址是172.16.138.41的主机,显然这台主机就是 Node2,UDP要转发的目的也找到了。接下来就是宿主机网络封包的过程了。

Flannel 在kubernetes上的应用

其实上述过程也是kubernetes的主要处理方法,只不过kubernetes是通过一个叫CNI接口维护一个单独网桥来代替docker0,这个网桥CNI网桥,默认叫做cni0。如图:

过程也是和VXLAN是一样的。需要注意的是,CNI网桥只是接管所有CNI插件负责的,既只是kubernetes创建的容器。

kubernetes之所以要设置这样一个与docker0网桥功能一样的CNI网桥,主要原因有两点:

  • kubernetes项目并没有使用Docker的网络模型,所以它不希望,也不具备配置docker0的能力。
  • 还与kubernetes如何配置Pod,也就是infra容器Network Namespace相关。

我们在部署kubernetes的时候,有一个步骤是安装kubernetes-cni包,他的目的就是宿主机上安装CNI插件所需要的基础可执行文件。

 ls /opt/cni/bin/
bridge dhcp flannel host-local ipvlan loopback macvlan portmap ptp sample tuning vlan

CNI的基础可执行文件,按照功能分三类:

  • Main插件 他是用来创建具体网络设备的二进制文件。例如:birdge(网桥设备)、ipvlan、lookback(lo 设备)、ptp(Veth Pair设备)、macvlan、vlan
  • IPAM插件 他是负责分配IP地址的二进制文件。例如:dhcp,这个文件会向dhcp服务器发起请求;host-local,则会使用预先配置的IP地址来进行分配。
  • CNI社区维护的内置CNI插件。例如 flannel,就是专门为Flannel项目提供的CNI插件。

从二进制文件来看,如果实现一个kubernetes用的容器网络方案,其实需要两部分工作,以Flannel下项目为例。

  • 首先实现这个网络本身,其实就是flanneld进程里主要逻辑,例如:创建和配置flannel.1设备,配置宿主机路由、配置ARP和FDB表。
  • 实现该网络方案对应的CNI插件,就是配置infra容器里的网络栈,并把他连接在CNI网桥上。

接下来进行第一步,在宿主机上安装flannel。而这个过程中,flanneld启动后会在每台宿主机上生成他对应的CNI配置文件(就是configmap),从而告诉kubernetes,这个集群要使用Flannel作为容器网络方案。

CNI配置文件内容如下:

cat /etc/cni/net.d/-flannel.conflist
{
"name": "cbr0",
"plugins": [
{
"type": "flannel",
"delegate": {
"hairpinMode": true,
"isDefaultGateway": true
}
},
{
"type": "portmap",
"capabilities": {
"portMappings": true
}
}
]
}

需要注意的是Kubernetes 目前不支持多个CNI混用,如果在/etc/cni/net.d/里放置多个CNI配置文件的话,只会加载字母排序第一个配置文件。但另一方面,CNI允许你在一个CNI配置文件里,通过plugins字段,定义多个插件协作。假如我们定义了flannel和protmap这两个插件,这个时候dockershim会把这个CNI配置文件加载起来,并把列表第一个插件,就是flannel插件设置为默认插件,然后执行过程中flannel和portmap会按照定义顺序被调用,从而一次完成“配置容器网络”和“配置端口映射”。

CNI插件工作原理

当kubelet组件需要创建pod时,他一个创建的一定是infra容器,所以这一步,dockershim 就会先调用Docker API创建并启动infra容器,紧着执行一个叫做SetUpPod的方法,这个方法的作用是:为CNI插件准备构建参数,然后调用CNI插件为infra容器配置网络。这里要调用CNI插件是/opt/cni/bin/flannel;而调用它所需的参数,分两部分:

第一部分,是由dockershim设置的一组CNI环境变量。其中,最重要的环境变量参数叫做:CNI_COMMAND。他的取值只有两种ADD和DEL。这个ADD和DEL操作,就是CNI插件唯一实现的两种方法。

  • ADD 把容器添加CNI网络里
  • DEL 把容器从CNI网络里移除

在网桥类型的CNI里,这两个操作说明把容器以“Veth Pair”方式插在CNI网桥上,或者从网桥上拔掉。

第二部分,是dockershim从CNI配置文件里加载到的默认插件的配置信息。这个配置信息在CNI中被叫作Network Configuration,dockershim会把Network Configuration 通过JSON数据的方式,通过标准输入的方式传递给Flannel CNI插件。

将Flannel插件的后端改成VXLAN+DriectRouting

以下操作不适合在生产环境操作,kubernetes的网络环境需要根据未来的业务环境选择。所以要集群配置前做好规划。

VXLAN+DriectRouting是首先采用直接路由的方式,如果不可以就使用VXLAN的方式。

Flannel的默认配置是VXLAN,但是我们可以配置多个插件协作,接下来我们就使用VXLAN+DriectRouting这两个插件协作。

下载Flannel配置文件

wget https://raw.githubusercontent.com/coreos/flannel/master/Documentation/k8s-manifests/kube-flannel-legacy.yml

修改kube-flannel-legacy.yml,在net-conf.json里的增加一个type。

$ vim kube-flannel-legacy.yml
.......
net-conf.json: |
{
"Network": "10.244.0.0/16",
"Backend": {
"Type": "vxlan",
"Type": "DriectRouting"
}
}
.....

删除flannel插件,重新生成配置文件。

$ kubectl delete ds kube-flannel-ds  -n kube-system
$ kubectl apply -f kube-flannel-legacy.yml

这样就修改完成了,切忌生成不可以直接操作。

kubernetes之flannel的更多相关文章

  1. 搞定 Kubernetes 基于flannel 的集群网络

    .Docker网络模式 在讨论Kubernetes网络之前,让我们先来看一下Docker网络.Docker采用插件化的网络模式,默认提供bridge.host.none.overlay.maclan和 ...

  2. Kubernetes之Flannel介绍

    Flannel是CoreOS团队针对Kubernetes设计的一个网络规划服务,简单来说,它的功能是让集群中的不同节点主机创建的Docker容器都具有全集群唯一的虚拟IP地址. 在Kubernetes ...

  3. kubernetes 使用flannel网络模式 错误分析

    今天按照网上和书上的要求,将目前的kubernetes网络换成flannel.其实配置起来还是很简单的,但是一旦出现了问题,将很难解决. 配置方法我这边不给出了.因为网上这样的教程一大把,在说下去也无 ...

  4. kubernetes部署 flannel网络组件

    创建 flannel 证书和私钥flannel 从 etcd 集群存取网段分配信息,而 etcd 集群启用了双向 x509 证书认证,所以需要为 flanneld 生成证书和私钥. cat > ...

  5. Kubernetes学习之路(五)之Flannel网络二进制部署和测试

    一.K8S的ip地址 Node IP:节点设备的IP,如物理机,虚拟机等容器宿主的实际IP. Pod IP:Pod的IP地址,是根据docker0网络IP段进行分配的. Cluster IP:Serv ...

  6. Kubernetes网络之Flannel工作原理

    目录 1.Docker网络模式 1.1 bridge网络的构建过程 1.2 外部访问 2.Kubernetes网络模式 2.1 同一个Pod中容器之间的通信 2.2 不同Pod中容器之间的通信 2.3 ...

  7. 基于 CentOS7 的 Kubernetes 集群

    一.环境 相关主机 master 192.168.12.197 minion 192.168.12.198~232 etcd 192.168.12.233~236 相关软件 OS CentOS 7 软 ...

  8. kubernetes学习笔记

    docker实现了更便捷的单机容器虚拟化的管理, docker的位置处于操作系统层与应用层之间; 相对传统虚拟化(KVM,XEN): docker可以更加灵活的去实现一些应用层功能, 同时对资源的利用 ...

  9. Centos7上安装Kubernetes集群部署docker

    一.安装前准备1.操作系统详情需要三台主机,都最小化安装 centos7.3,并update到最新 [root@master ~]# (Core) 角色 主机名 IPMaster master 192 ...

随机推荐

  1. jQuery元素操作

    jQuery中创建元素及追加元素 DOM中可以动态创建元素:document.createElement(“标签的名字”); jQuery中同样可以创建元素标签,并且返回的就是jQuery对象,可以直 ...

  2. android - TextView单行显示...或者文字左右滚动(走马灯效果)

    条件 TextView单行显示,文字左右滚动(走马灯效果)实现条件: 实现单行设置固定宽度或者设置权重都行 代码 TextView滚动必须写下面几个属性 android:singleLine=&quo ...

  3. 基于python的种子搜索网站,你懂得!

    该项目是基于python的web类库django开发的一套web网站,给师弟做的毕业设计.本人的研究方向是一项关于搜索的研究项目.在该项目中,笔者开发了一个简单版的搜索网站,实现了对数据库数据的检索和 ...

  4. 使用 Scrapy 爬取股票代码

    个人博客: https://mypython.me 源码地址: https://github.com/geeeeeeeek/scrapy_stock 抓取工具:scrapy scrapy 介绍 Scr ...

  5. 微信小程序推广技巧、营销方案

    小程序已经成功上线了!那么,小程序线下如何推广?线下门店如何玩转小程序呢? 1.附近的小程序,让商家曝光率更高 小 程序自带“附近的小程序”功能,利用LBS定位功能提高商家专属微信小程序的曝光度,用户 ...

  6. 手把手教新手小白在window把自己的项目上传到github

    作为一个开发者,写博客,上传项目到github好像是不可不会的技能,很多有经验的老司机都会这么建议你.本宝宝第一次要把项目传到github的时候,确实有点蒙蔽,什么鬼,传个东西有必要这么难吗? git ...

  7. Python第十四天 序列化 pickle模块 cPickle模块 JSON模块 API的两种格式

    Python第十四天 序列化  pickle模块  cPickle模块  JSON模块  API的两种格式 目录 Pycharm使用技巧(转载) Python第一天  安装  shell  文件 Py ...

  8. win10下Resin安装--入门(1)

     我个人采用是解压版的,直接解压亦可使用下载地址 开启该服务需要的环境:首先你的JDK必须安装成功 解压后你会看到 当我们运行程序时,需要修改配置文件中的相关配置: 1.端口:以免端口被占用 2.相应 ...

  9. python接口自动化-Cookie_绕过验证码登录

    前言 有些登录的接口会有验证码,例如:短信验证码,图形验证码等,这种登录的验证码参数可以从后台获取(或者最直接的可查数据库) 获取不到也没关系,可以通过添加Cookie的方式绕过验证码 前面在“pyt ...

  10. Linux 基础学习:文件权限与种类

    1.文件权限 linux系统中通过 “ls -al”,可查看当前目录的所有文件的详细信息. 第一列代表这个文件的类型与权限: 第一个字符表示文件类型: [d]:表示目录文件 [-]:表示普通文件 [l ...