zoukankan      html  css  js  c++  java
  • 搞定 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服务和容器之间、容器之间进行通讯,

    • macvlan:此网络允许为容器指定一个MAC地址,允许容器作为网络中的物理设备,这样Docker daemon就可以通过MAC地址进行访问的路由。对于希望直接连接网络网络的遗留应用,这种网络驱动有时可能是最好的选择。

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

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

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

    1)安装Docker时,创建一个名为docke0的虚拟网桥,虚拟网桥使用“10.0.0.0 -10.255.255.255 “、”172.16.0.0-172.31.255.255″和“192.168.0.0——192.168.255.255”这三个私有网络的地址范围。

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

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

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

    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和服务之间的通信

    集群外:

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

    因此,Kubernetes假设Pod之间能够进行通讯,这些Pod可能部署在不同的宿主机上。每一个Pod都拥有自己的IP地址,因此能够将Pod看作为物理主机或者虚拟机,从而能实现端口设置、命名、服务发现、负载均衡、应用配置和迁移。为了满足上述需求,则需要通过集群网络来实现。

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

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

    这种场景对于Kubernetes来说没有任何问题,根据Kubernetes的架构设计。Kubernetes创建Pod时,首先会创建一个pause容器,为Pod指派一个唯一的IP地址。然后,以pause的网络命名空间为基础,创建同一个Pod内的其它容器(–net=container:xxx)。因此,同一个Pod内的所有容器就会共享同一个网络命名空间,在同一个Pod之间的容器可以直接使用localhost进行通信。

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

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

    flannel会在每一个宿主机上运行名为flanneld代理,其负责为宿主机预先分配一个子网,并为Pod分配IP地址。Flannel使用Kubernetes或etcd来存储网络配置、分配的子网和主机公共IP等信息。数据包则通过VXLAN、UDP或host-gw这些类型的后端机制进行转发。

    看一下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

    4)创建虚拟网卡

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

    $ ip addr show flannel.1

    5)创建Docker网桥

    并为容器配置名为docker0的网桥,实际是通过修改Docker的启动参数–bip来实现的。通过这种方式,为每个节点的Docker0网桥设置在整个集群范围内唯一的网段,从保证创建出来的Pod的IP地址是唯一。

    $ 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虚拟网卡处理

    docker0收到数据包后,docker0的内核栈处理程序会读取这个数据包的目标地址,根据目标地址将数据包发送给下一个路由节点:

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

    $ ip route

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

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

    Ethernet Header的信息:

    • From:{源容器flannel.1虚拟网卡的MAC地址}

    • To:{目录容器flannel.1虚拟网卡的MAC地址}

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

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

    Ethernet Header的信息:

    • From:{源容器Node节点网卡的MAC地址}

    • To:{目录容器Node节点网卡的MAC地址}

    IP Header的信息:

    • From:{源容器Node节点网卡的IP地址}

    • To:{目录容器Node节点网卡的IP地址}

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

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

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

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

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

    --------------------------另外一篇

    说明

    Flannel是Kubernets最早期的网络方案之一,也是现在常用的方案之一。当时只了解到它采用overlay的方式,于是重点学习calico了,后来发现用到flannel的公司还挺多,需要系统学习下。

    工作原理

    原理很简单,在每一个需要使用Flannel网络的机器上都运行有一个名为flanneld的服务。flanneld为所在的机器申请到一小段虚拟网络的地址空间,并负责将通过这些虚拟地址发送的报文封装后,用宿主机的网络送出。flanneld还要负责解读宿主机网络收到发送给虚拟网络的中的地址的报文。

    虚拟网络地址的分配情况直接写入etcd,或者通过kubernetes的api写入。

    核心是:Flannel是怎样通过宿主机网络传递虚拟机网络中的报文的? Flannel支持几种不同的方式,把它们叫做Backends

    已经支持的Backends

    @2018-10-09 16:47:10

    最推荐使用的是vxlan,使用linux kernel的vxlan实现。vxlan backend的配置项有以下几个:

    Type: string,backend类型,就是"vxlan"
    VNI:  number,vxlan协议中的vni编号,不同的vni号码代表不同网段,类似vlan号,默认是1
    Port: number,  宿主机的udp端口,用来发送封装后的报文,使用linux内核默认配置,8472
    GBP:  boolean,是否使用vxlan Group Policy,默认false
    DirectRouting:  boolean,是否启用直接路由,当两台宿主机位于同一个网段时,不封装通过路由直接送达,默认false
    

    GBP特性,参考:vxlan: Group Policy extension

    其次是host-gw的方式,通过直接路由的方式传送虚拟网络报文。这种方式要求所有宿主机是二层直达的(中间不经过路由),原理和vxlan中的DirectRouting相同。

    Vxlan DriectRouting是能够直接路由的时候采用直接路由的方式,否则就通过vxlan。 Host-gw要求所有宿主机都支持直接路由方式(在同一个二层网络中),并全部采用直接路由的方式。

    host-gw的配置项只有一个:

    Type: string,backend类型,就是"host-gw"
    

    udp只建议调试时使用,或者另外两种方式不能使用的时候(譬如宿主机内核不支持vxlan)使用。

    Type:string,backend类型,就是"udp"
    Port: number,宿主机udp端口,默认8285
    

    处于试验阶段的Backends

    @2018-10-09 16:47:23

    AliVPC,阿里云的VPC

    Type (string): alloc
    

    Alloc,这个没明白怎么回事,说是”performs subnet allocation with no forwarding of data packets”:

    Type (string): alloc
    

    AWS VPC,AWS的VPC:

    Type (string): aws-vpc
    RouteTableID (string): [optional] The ID of the VPC route table to add routes to. 
    

    GCE,Google的云服务:

    Type (string): gce
    

    IPIP,使用内核实现的ipip隧道:

    Type (string): ipip
    DirectRouting (Boolean):
    

    IPSec,使用内核实现的IpSec:

    Type (string): ipsec
    PSK (Boolean): Required. 
    UDPEncap (string): Optional
    ESPProposal (string): Optional
    

    其它内容?

    Flannel是一个特别简单的网络方案,文档也就特别简单。把上面的backends梳理完,文档基本上就全读完了。

    Kubernetes1.12从零开始(五):自己动手部署Kubernetes中讲到,Kubernetes设计的时候,就降低了对网络模型的要求。所以Flannel这样简单的网络方案,可以用于Kubernetes。

    不过要注意,Flannel这个项目小而精,缺少了一些功能。最直接的缺陷就是:不支持ACL,即Kubernetes中的Network Policy。

    根据Flannel项目Readme中的表述,这个项目似乎也不打算支持”network policy”:

    Flannel is focused on networking. For network policy, other projects such as Calico can be used.
    

    有意思一的是Calico启动了一个Canal项目,糅合了Calico和Flannel。Network policy功能有calico提供,network功能用flannel提供,也是醉了。

    糅合了Calico和Flannel的Kubernetes网络方案Canal

  • 相关阅读:
    Oracle 11g SQL Fundamentals Training Introduction02
    Chapter 05Reporting Aggregated data Using the Group Functions 01
    Chapter 01Restriicting Data Using The SQL SELECT Statemnt01
    Oracle 11g SQL Fundamentals Training Introduction01
    Chapter 04Using Conversion Functions and Conditional ExpressionsConditional Expressions
    Unix时代的开创者Ken Thompson (zz.is2120.bg57iv3)
    我心目中计算机软件科学最小必读书目 (zz.is2120)
    北京将评估分时分区单双号限行 推进错时上下班 (zz)
    佳能G系列领军相机G1X
    选购单反相机的新建议——心民谈宾得K5(转)
  • 原文地址:https://www.cnblogs.com/cheyunhua/p/10037730.html
Copyright © 2011-2022 走看看