kubernetes 容器网络接口(CNI) midonet 网络插件的设计与实现

2017-03-23 14:46:28 +08:00
 goodraincloud

相关原理概述

先来讲讲什么是 CNI?

CNI (容器网络接口)是一种操作容器网络规范,包含方法规范,参数规范等。 CNI 只关心容器的网络连接,在容器创建时分配网络资源,并在删除容器时删除分配的资源。因为这个焦点, CNI 有广泛的支持,规格易于实现。 CNI 接口只需要实现两个方法,一个创建容器时调用,一个删除容器时调用。

Kubernetes 如何支持和运行遵循 CNI 规范的插件

kubernetes 首先以插件的形式完成(pod)容器的网络资源设置。内置的插件包括:cni,kubenet,hostport 等。这里简单说说 kubenet 。这是一个简单的网络插件,每台机器上创建一个 br0 网桥,根据 PodCIDR 为每个 pod 设置 ip 连接到 br0 网桥上。次方式可结合一些网络路由工具完成一个小规模的集群网络 pod 互联。我们主要讲 CNI 插件。 kubernetes 以 cni 插件来支持 cni 规范,调用其他厂商和个人开发的遵循 cni 规范的各种网络插件,例如Calico,Flannel等。 k8s 默认情况下 cni 模式不支持端口映射等。 k8s 将容器网络设置 none,完全交给插件去管理容器网络资源。

上文多次提到的网络资源是什么?

容器网络资源包括:虚拟网卡,IP 地址, DNS,网络路由等等。容器使用独立的网络命名空间,可以具有自己的网络资源信息。这些信息数据由不同的 CNI 插件根据不同的 SDN 网络的实现给容器配置。

MidoNet SDN 网络

MidoNet 是由日本的 SDN 公司 Midkura 研发的一款网络虚拟化软件,其基于底层物理设施来实现网络虚拟化,具有分布式、分散、多层次的特点,主要作为 OpenStack 中的默认网络组件,可以让虚拟网络解决方案,特别是专为网络基础设施设计的方案,为云平台如 OpenStack 服务,并且将其网络存贮栈虚拟化。 MidoNet 为每个租户分配一个逻辑 router,租户与租户之间是相互隔离的,租户内部之间是能够相互通讯的, Midonet 支持 L2 交换、 L3 路由、 L4 负载均衡

有状态和无状态 NAT ,逻辑和分布式防火墙, BGP 与 ECMP 支持。其架构主要包含以下组件:

Midolman ( Midonet Agent ): Midonet

Agent 安装在各个计算节点,负责建立网络流量控制和提供分布式 Midonet 网络服务,路由, NAT 等他把相关的虚拟网络信息存放到 NSDB 。

Network State

Database(NSDB):存储网络配置和状态,网络拓扑,路由, Midonet 不集中处理网络功能,由 Midonet Agent 处理, Midonet Agent 会跟 NSDBs 做实时同步当有变化时候会及时同步并且更新 NSDB MidoNet 支持大规模 SDN 集群,其架构理论上支持上万节点。我们可以使用 MidoNet 完成 k8s 集群内租户内 Pod 网络互联。

MidoNet 多租户下网络结构模型

SDN(软件定义网络), Midonet 软件定义你所熟知的网络组件。以下简单介绍几个核心的软件定义概念:

基于 MidoNet 的 kubernetes CNI 插件实现

Midonet 数据交换工作在三层,但是其本身不提供 IP 地址管理(IPAM),因此基于 Midonet 的 cni 插件需要完成以下工作: IPAM,租户 Router 、 Bridge 创建,容器网卡创建,以及所有端到端连接和路由过滤规则创建。

IPAM

需要完成两个层面的 IP 管理, Router 级别的地址管理,每一个 Router 具有一个 IP 地址,且全局唯一不冲突。每一个 Bridge 具有一个唯一网段,连接的虚拟网卡具有全局唯一 IP 。
IPAM 有很多实现方式, CNI 插件是无状态应用,或许你需要一个守护进程来完成 IPAM 工作。基于简化架构的思路,我们使用 ETCD 来存储 IP 数据,直接由插件来操作 ETCD 。完成 IP 的使用和释放。

租户网络初始化

当新租户第一次创建容器时进行租户虚拟设备的初始化创建,上文我们已经介绍了一个租户需要创建的虚拟设备有哪些,这里我讲讲细节。 Midonet 提供了 Rest-API 来操作虚拟设备。这里注意,根据使用的不同版本的 Midonet 使用不同版本的 API 。 https://github.com/barnettZQG/golang-midonetclient
封装了 golang 版的 Midonet api 操作方法,支持 1.*和 5.*API 版本。 创建步骤如下:

  1. 创建租户,调用 Keystone API 。
  2. 创建 Router ,并包含创建进出 Chain 。
  3. 创建 PrivierRouter Port 并赋 IP,创建 Router Port 并赋 IP 。创建 PortLink 连接两个 Port 。
  4. 为前面创建的 Chain 创建对应的路由规则
  5. 为前面创建的 Port 创建包过滤规则
  6. 创建一个默认的 Bridge 。并创建 Port 连上 Router 。
  7. 存储以上创建的相关数据进 ETCD.

容器网卡创建和网络绑定

Virtual Ethernet Pair

简称 veth pair,是一个成对的端口,所有从这对端口一 端进入的数据包都将从另一端出来,反之也是一样.其两端可存在于不同的网络空间( Network Namespace )。容器创建成功后具有一个网络空间, k8s 此时调用 CNI 插件 ADD 方法进行网络设置。插件首先创建一对 Veth pair 。将其一端置于宿主机网络空间,调用 Midonet 绑定 API 将其与 Bridge 一个 Port 绑定。另一端在容器内并赋予 IP 地址,根据当前使用的 Bridge 网段。 与 Docker0 网卡部分原理一致。

设置容器内路由规则

将默认路由设置到上文创建的网卡上。例如上文创建的网卡命名为 eth0 。

设置 DNS

根据需要设置一些 DNS 信息。

怎么实现操作?

1.使用 shell 命令。

ip link *
ip netns *
ip address *
ip route *

以上命令详细使用方法网上很多了,这里不再描述。

  1. golang netlink library

https://github.com/vishvananda/netlink 定义了关于网卡相关与 linux 内核通信的用户空间的相关接口。

CNI 插件实现的注意事项

  1. CNI 插件的添加和删除操作应该具有幂等性,即同样的参数传入不管调用多少次都应该有相同的效果。
  2. CNI 插件应该支持并发性,主要是租户相关组件的创建和 IP 地址分配的强一致性。
  3. CNI 插件有一定的规范,请参考:https://github.com/containernetworking/cni

好雨云 Midonet cni 插件开源

好雨云开源基于 ETCD 版的的 midonet cni 插件具有上文提到的所有功能和特性。 github:https://github.com/goodrain/midonet-cni

2210 次点击
所在节点    云计算
0 条回复

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://www.v2ex.com/t/349740

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX