1. Network

在没有搭建 kubernetes 集群时,如果想让两台不同的物理节点上的容器之间进行通信,这就需要第三方工具来实现,常用的 calico 和 flannel。

2. docker 网络模式

docker 有四种网络模式:

  1. none :

    • 容器有独立的 Network namespace.

    • 将容器添加到一个容器专门的网络堆栈中,没有对外连接。

    • 只能使用 loopback 网络设备,容器只能使用 127.0.0.1 的本机网络。

  2. host :

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

    • 将容器添加到主机的网络堆栈中,没有隔离

    • 容器将不会虚拟出自己的网卡,配置自己的 IP 等,而是使用宿主机的 IP 和端口。

  3. bridge :

    • 默认网络方式

    • 为每一个容器分配 IP ,并将容器连接到一个 docker0 虚拟网桥

  4. 自定义网桥 :

    • 用户自定义网桥,有更多的灵活性、隔离性等。

  5. Network plugins :

    • 可以安装和使用第三方的网络插件

3. CNI

CNI(container network interface) CNCF下的一个项目,由coreOS提出

通过插件的方式统一配置:

  • flannel : 基于overlay 不支持网络策略

  • calico : 基于BGP 支持网络策略

  • canal : 支持网络策略

通过给 Kubelet 传递 CNI 选项:

  • –network-plugin=cni 命令行选项来选择 CNI 插件。

  • –cni-conf-dir (默认是 /etc/cni/net.d) 读取文件并使用该文件中的 CNI 配置来设置每个 pod 的网络。

  • –cni-bin-dir (默认是 /opt/cni/bin)配置引用的任何所需的 CNI 插件都必须存在于该目录下。

各种解决方案对比如下:

特性/方案FLANNELCALICOMACVLANOPENVSWITCH直接路由
方案特性通过虚拟设备 flannel0 实现对 docker0 的管理基于 BGP 协议的纯三层的网络方案基于 Linux Kernel 的 macvlan 技术基于隧道的虚拟路由技术基于 Linux Kernel 的 vRouter 技术
对底层网络的要求三层互通三层互通二层互通三层互通二层互通
配置难易度简单,基于 etcd简单,基于 etcd简单,直接使用宿主机网络,需要仔细规划IP地址范围复杂,需要手工配置各个节点的bridge简单,使用宿主机 vRoute 功能,需要仔细规划每个node的IP地址范围
网络性能host-gw > Vxlan > UDPBGP 模式性能损失小,IPIP模式较小性能损失可忽略效能损失较小性能损失小
网络连通性限制在不支持 BGP 协议的网络环境中无法使用基于 macvlan 的容器无法与宿主机网络通信在无法实现大二层互通的网络环境下无法使用

4. Flannel 网络原理

4.1 Flannel 简介

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

Flannel 实质上是一种覆盖网络(overlaynetwork)

overlay 覆盖网络:

  • 也就是将 TCP 数据包装在另一种网络包里面进行路由转发和通信

  • 在基础网络的基础上叠加的一种虚拟网络技术模式,该网络的主机通过虚拟链路连接起来。

目前已经支持udp、vxlan、host-gw、aws-vpc、gce 和 alloc 路由等数据转发方式,默认的节点间数据通信方式是 UDP 转发。

4.2 flannel 网络特点

Flannel 网络特点有:

  1. 使集群中的不同 Node 主机创建的Docker容器都具有全集群唯一的虚拟 IP 地址。

  2. 建立一个覆盖网络(overlay network),通过这个覆盖网络,将数据包原封不动的传递到目标容器。覆盖网络是建立在另一个网络之上并由其基础设施支持的虚拟网络。覆盖网络通过将一个分组封装在另一个分组内来将网络服务与底层基础设施分离。在将封装的数据包转发到端点后,将其解封装。

  3. 创建一个新的虚拟网卡 flannel0 接收 docker0 网桥的数据,通过维护路由表,对接收到的数据进行封包和转发(vxlan)。

  4. etcd 保证了所有 node 上 flanneld 所看到的配置是一致的。同时每个node上的 flanneld 监听 etcd 上的数据变化,实时感知集群中 node 的变化。

4.3 flannel 网络原理及通信流程

Flannel是 CoreOS 团队针对 Kubernetes 设计的一个覆盖网络(Overlay Network)工具:

  • 目的在于帮助每一个使用 Kuberentes 的 CoreOS 主机拥有一个完整的子网。

  • 功能是让集群中的不同节点主机创建的 Docker 容器都具有全集群唯一的虚拟IP地址。让所有的容器相当于在同一个直连的网络,底层通过 UDP/VxLAN等进行报文的封装和转发。

其中,Overlay Network是覆盖网络,在基础网络的基础上叠加的一种虚拟网络技术模式,该网络的主机通过虚拟链路连接起来。

VXLAN:将原数据包包装在 UDP 中,并使用基础网络的 IP/MAC 作为外层报文头进行封装,然后在以太网上传输,到达目的地后由隧道端点解封并将数据发送给目标地址。其中,VXLAN网络结构如下:

Flannel:是 Overlay Network 的一种,也是将原数据包封装在另一种网络包里面进行的路由转发和通信,目前已经支持 UDP、VXLAN、AWS VPC和GCE路由数据转发方式

具体的通信流程,不同物理节点上的容器通信流程

  1. node1 节点的 容器 container1 产生数据,根据 容器的路由表,将数据发送给 cni0

    • Cni0 : 网桥设备,也就是 docker0 网桥,每创建一个 容器 都会创建一对 veth pair。其中一端是 容器 中的 eth0,另一端是 docker0 网桥中的端口(网卡)。容器 中从网卡 eth0 发出的流量都会发送到 docker0 网桥设备的端口(网卡)上。

  2. Cni0 根据节点的路由表,将数据发送到隧道设备 flannel0

    • Flannel0: overlay 网络的设备,用来进行 vxlan 或其他方式 报文的处理(封包和解包)。不同 node 之间的 pod 数据流量都从 overlay 设备以隧道的形式发送到对端。

  3. Flannel0 查看数据包的目的 ip,从 flanneld 获得对端隧道设备的必要信息,封装数据包。

    • Flanneld:flannel 在每个主机中运行 flanneld 作为 agent,它会为所在主机从集群的网络地址空间中,获取一个小的网段subnet,本主机内所有容器的 IP 地址都将从中分配。同时 Flanneld 监听 etcd 数据库,为 Flannel0 设备提供封装数据时必要的 mac,ip 等网络数据信息。

  4. Flanneld 将数据包通过本机网卡发送到对端设备。对端节点的网卡接收到数据包,发现数据包为 overlay 数据包,解开外层封装,并发送内层封装到flanneld 设备。

  5. Flannel0 设备查看数据包,根据路由表匹配,将数据发送给 Cni0 设备。

  6. Cni0 匹配路由表,发送数据给网桥上对应的端口。

注意:

  • Flannel 配置第三层 IPv4 Overlay 网络,会创建一个大型内部网络,并且跨越集群中的每个节点

  • 在 Overlay 网络中,每个节点都有个子网 subnet ,用于给容器分配ip地址

  • 同一主机中的 容器可以使用 docker0 直接通信,而不同主机上的容器需要使用 flanneld 进行封装在传输。

其中,一个具体的例子,Flannel 网络结构如下:

上图表示:

  • 数据从源容器 cache1 container 中(IP地址为10.1.15.2)发出后,经由所在主机的 Docker0 虚拟网卡转发到 flannel0 虚拟网卡,这是个 P2P 的虚拟网卡,flanneld 服务监听在网卡的另外一端。

  • Flannel 通过 Etcd 服务维护了一张节点间的路由。

  • 源主机的 flanneld 服务将原本的数据内容 UDP 封装后根据自己的路由表投递给目的节点的 flanneld 服务,数据到达以后被解包,然后直 接进入目的节点的 flannel0 虚拟网卡,然后被转发到目的主机的 Docker0 虚拟网卡,最后就像本机容器通信一下的有 Docker0 路由到达目标容器 backend1 container (IP地址为10.1.20.3)。

4.4 Flannel 网络的安装配置

可以直接使用 flannel 的 yaml 文件,在 kubernentes 中一键安装。

5. Calico 网络原理

5.1 Calico 简介

calico 是完全利用路由规则实现动态组网,通过 BGP 协议通告路由。

calico 的好处是 endpoints 组成的网络是单纯的三层网络,报文的流向完全通过路由规则控制,没有 overlay 等额外开销。

5.2 Calico 原理

Calico 原理:

  • Calico 在每一个计算节点利用 Linux Kernel 实现了一个高效的 vRouter 来负责数据转发

  • 每个 vRouter 通过 BGP 协议负责把自己上运行的 workload 的路由信息向整个 Calico 网络内传播——小规模部署可以直接互联,大规模下可通过指定的 BGP route reflector 来完成。

  • 保证最终所有的 workload 之间的数据流量都是通过 IP 路由的方式完成互联的。

  • Calico 节点组网可以直接利用数据中心的网络结构(无论是 L2 或者 L3),不需要额外的 NAT,隧道或者 Overlay Network。

  • Calico 基于 iptables 还提供了丰富而灵活的网络 Policy,保证通过各个节点上的 ACLs 来提供 Workload 的多租户隔离、安全组以及其他可达性限制等功能。

5.3 Calico 组网

组网示意图:

Copy to Clipboard

注意:

  • calico 组网的核心原理就是 IP 路由,每个容器或者虚拟机会分配一个 workload-endpoint(wl)。

    • endpoint : 接入到 calico 网络中的网卡称为 endpoint

    • workload-Endpoint : 虚拟机、容器使用的 endpoint

  • 从容器 ConA 中发送给 ConB 的报文被 nodeA 的 wl-A 接收,根据 nodeA 上的路由规则,经过各种 iptables 规则后,转发到nodeB。

  • 如果 nodeA 和 nodeB 在同一个二层网段,下一条地址直接就是 node-B,经过二层交换机即可到达。

  • 如果 nodeA 和 nodeB 在不同的网段,报文被路由到下一跳,经过三层交换或路由器,一步步跳转到 node-B。

  • nodeA 怎样得知下一跳的地址?答案是 node 之间通过 BGP 协议交换路由信息。

5.4 Calico 安装配置

5.4.1 搭建 etcd 集群

  1. 安装 etcd

    • 两台 etcd 集群,分别装有 docker
    • yum install -y etcd
  1. 配置 /etc/etcd/etcd.conf 配置文件, 根据节点不同修改 ip 地址

Copy to Clipboard
  1. 启动 etcd 集群

    • systemctl start etcd
  1. 配置 docker 的存储为 etcd , 在两个节点上 修改 docker 启动选项,添加:(配置为自己的etcd节点)

Copy to Clipboard

5.4.2 安装配置 calico

  1. 在两个节点上修改 calico 的配置

Copy to Clipboard
  1. 创建 calico 容器,用来进行两个物理节点上容器的互通, 在所有节点上执行

  • 下载安装 calicoctl, 地址:curl -O -L https://github.com/projectcalico/calicoctl/releases/download/v3.16.3/calicoctl

  • 添加可执行权限:chmod +x calicoctl

  • 建立 calico node 的容器,容器镜像为:quay.io/calico/node

Copy to Clipboard
  • 可以看到对方的主机的信息

Copy to Clipboard
  1. 创建 docker 网络,在任意主机上创建网络(可以同步给远端)

  • --driver calico 指定使用calico 的 libnetwork CNM driver。

  • --ipam-driver calico-ipam 指定使用 calico 的IPAM driver 管理IP。

  • calico 为 global 网络,etcd 会将 calnet1 同步到所有主机。

Copy to Clipboard
  1. 每在主机上创建一个容器,则会在物理机上创建一张虚拟网卡出来

    • 在 vms91 上创建一个容器 : docker run --name c91 --net calnet1 -itd busybox

    • 在 vms92 上创建一个容器 : docker run --name c92 --net calnet1 -itd busybox

    • 两个容器就可以互相通信了

5.5 calico 网卡分析

  1. 创建好 calico node 后,在没有创建容器时,只有 本地网卡和docker0网桥,没有其他网卡。

  2. 当创建一个busybox 容器后,在容器中 和 在 物理机中都多了一张网卡

    • 在容器中的网卡名称为:6: cali0@if7

    • 在物理机中的网卡名称为:7: calif6391d136be@if6

    • 可以看到:

  3. 在容器中的路由表 route -n,可以看到,所有的数据包的默认网关是 cali0 网卡

  4. 在物理集中查看路由表 route -n, 可以看到,

    • 凡是去往本机容器中的地址的数据包,默认网卡是 calif6391d136be

    • 凡是去往其他物理机中容器地址的数据包,默认网卡都是 本机的网卡出去

    • 也就是说,在calico的节点上,通过egb协议,相互学习路由

  5. 每台主机都知道不同的容器在哪台主机上,所以会动态的设置路由。