DockOne微信分享(一七七):苏宁容器云基于Kubernetes和Contiv的网络架构技术实现


【编者的话】容器云的发展和落地,使得越来越多的无状态服务迁移到容器云,加快容器云的落地。容器云的发展,使得更大限度的利用计算资源,这相对传统虚拟化技术来说,就有了很多优势,例如支持高可用时无缝切换、负载均衡、服务发现、自动扩展、自动化运维。但是新的技术和架构,也随之带来新的问题,大多数服务迁移到容器云之后,因为要面对复杂的数据中心、混合的虚拟机技术并存等等。在传统网络架构、网络设备硬件限制下,例如,白名单要求IP地址能够始终不变、云计算行业规则下的网络限速。

在苏宁容器云架构中,针对自身业务特点以及数据中心架构,基于Kubernetes和Contiv实现了Pod-IP固定、网络双向限速、支持多种虚拟网络加速等需求进行定制。在这个过程中,我们遇到很多问题和调整,涉及到架构重新设计、集成、研发、测试等。

该篇文章也是针对以上种种,为大家分享苏宁容器云的网络架构实现思路、以及我们踩过的bug。

Kubernetes CNI规范介绍

CNI 简介

CNI,Contianer Network Interface,是最早CoreOS发起的容器网络规范,后来和Kubernetes联合,成为了Kubernetes网络插件规范基础。CNI实现的基本思想为:

Contianer runtime在创建容器时,先创建好network namespace,这就是大家在实际操作过程中,首先创建出来的容器是Pause容器。之后调用CNI插件为这个netns配置网络,最后在启动容器内的进程。

CNI 组成

CNI Plugin负责为容器配置网络,包括两个基本接口:

配置网络:
AddNetwork(net NetworkConfig, rt RuntimeConf) (types.Result, error)

清理网络:
DelNetwork(net NetworkConfig, rt RuntimeConf) error


以上看,CNI的实现确实非常简单,把复杂的逻辑交给具体的Network Plugin实现。

IPAM Plugin负责给容器分配IP地址,主要实现包括host-local和DHCP。

Kubernetes Pod创建流程

1.png

  1. Kubelet接受到创建Pod请求
  2. Kubelet 首先创建Pause容器,并生成network namespace
  3. 将配置namespace 请求到CNI Driver
  4. CNI Driver(Contiv)根据具体配置调用具体的CNI插件
  5. CNI Driver(Contiv)给pause容器配置namespace,并返回
  6. 容器Pod中的其他容器都是使用Pause容器网络


Kubernetes CNI 插件对比

常用CNI插件

2.png

以上图看到5种网络插件,其实还有很多,这里只列举了部分。稍微解释一个不常用且有趣的网络插件,Cilium,该插件开源在https://github.com/cilium/cilium,是一个基于eBPF和XDP的高性能网络方案,其主要特色功能体现在网络安全、基于BPF的LB、以及提供了比较强大的监控和排错能力。

Contiv 对比

接下来我们详细对比我们着重提到的Contiv,我们将对比详细总结成为了表格。
b1.jpg

基于以上,我们选择Contiv。

Contiv Maclvan性能对比数据

326573989.jpg

从以上比对来看,Contiv在OVS模式下,其性能对比数据并不是最好的,但是综合了Contiv对租户隔离、网络限速策略、内置IPAM来看,可扩展行来看,最终选择了Contiv。

Contiv 网络架构

Contiv 是思科开源容器网络解决方案,同时支持CNI模型以及CNM模型,支持以下功能:

支持Tenant,支持租户隔离

3.png

在Contiv的定义看来,一个Tenant就是一个VRF(Virtual Routing Forwarding)实现。以上每一个小黑框就代表一个租户,网络属于Tenant,所有的网络接在contivVlanBridge。

支持多种网络模式

  • L2(VLAN)
  • L3(BGP)
  • Overlay(VXLAN)
  • Cisco SDN Solution(ACI)


苏宁容器云使用的是L2网络模式。

Network Poilcy

Network Policy描述了一组容器(Pod)上的网络资源使用、隔离策略、优先级等等。

在Contiv中有两种类型的Network policies:
  • Bandwidth,限制一个Application Group的整理网络资源使用
  • Isolation,限制一个组的网络访问。


苏宁容器云Contiv和Kubernetes部署架构

部署架构

下面的架构图中展示了部署架构图的Kubernetes集群、Contiv集群、etcd集群以及租户Pod:
4.png

  1. 图中是多个Kubernetes Master架构。
  2. 图中所示Netmaster、Netplugin、Auth_proxy都是以容器形式存在的,网络链接方式通过Contianer link方式到pause容器。
  3. Auth_proxy作为认证代理,提供基于RBAC认证,通过认证后,将请求转发给Netmaster。
  4. 在Contiv原生版本中,并不支持多Netmaster存在,我们多配置文件做了些修改,使Netmaster和Netplugin都是以DaemonSet资源形式存在。
  5. Contiv开源版本中默认使用的OVS Driver,我们也做了改造,使其支持多网络驱动,比如SR-IOV,DPDK。
  6. 最后Kubernetes和Contiv的数据都会写到ectd分布式存储中。


苏宁容器云使用的是Bridge VLAN模式:
5.png

实现多网络Driver支持:
6.png

苏宁容器云Pod-IP固定实现原理

实现Pod-IP固定的需求

  • 内部防火墙系统需要依据IP地址进行白名单或者黑名单设置
  • 内部RSF系统需要容器具有固定的IP地址
  • 利于运维或者研发调试修正问题


对Kubernetes支持的资源类型

系统实现Pod-IP固定支持三种资源:
  • Deployment
  • Stateful set
  • Replica set


Pod-IP固定流程

下面我们将详细流程介绍一下。
7.png

创建Pod:
  1. 上图展示了Kubernetes创建Pod请求IP流程,由kubelet向Contiv Netplugin发起请求。
  2. Contiv Netplugin整合Pod信息(Pod所属资源,所属资源副本数等信息)发送给Netmaster。
  3. Netmaster根据Pod请求的网络信息分配一个IP与Mac返回给Netplugin,并在etcd中维护一个该Pod所属资源的ip-pool映射关系
  4. Contiv Netplugin接收到IP Mac信息后,从网络命名空间(namespace)中配置ip/mac/GW,同时请求OVS创建好对应的port和interface。
  5. 最终Contiv Netplugin返回kubelet,网络配置完成。


重新调度Pod:
8.png

  1. Pod在发生异常退出(可能是被删除或者宿主机重启)进行重新调度时,Kubernetes会先删除异常Pod,Netmaster会把ip-pool中异常pod-ip设置成可用状态。
  2. Pod重新创建,由调度节点的kubelet向Contiv Netplugin发起请求IP地址,Contiv Netplugin整合Pod信息发送给Netmaster。
  3. Netmaster会根据Pod所属资源期望副本数与etcd中该资源副本数作比较,确认该副本是重新调度,并把该资源ip-pool中可用IP分配给Pod。
  4. Netplugin接收到IP信息继续创建Pod流程。


删除Pod:
9.png

  1. 删除Pod流程,由kubelet发起释放IP地址请求到Contiv Netplugin,根据Pod信息删除Pod所对应的ovs-port。
  2. Contiv Netplugin整合Pod信息向Netmaster发起删除请求。
  3. Netmaster根据Pod所属资源副本数确认是删除Pod操作,Netmaster会释放pod-ip,同时ip-pool中删除此IP。
  4. 若删除的Pod是该资源中最后一个副本,则Netmaster释放pod-ip,同时删除etcd中对该资源ip-pool的维护。
  5. 以上操作完成后Netplugin返回IP已释放信号,kubelet删除Pod、删除网络命名空间。


苏宁容器云基于Contiv实现双向限速

Pod双向限速实现原理

下行:
  • 使用netlink包,通过unix socket和内核通信
  • 使用tbf限速方式,直接将规则作用在ovs port上


上行:
  • 使用OVS中Ingress方式
  • 设置rate和burst
  • 超过设置速率限制,直接简单丢弃


Pod双向限速流程图

如果想要实现网络限速,在创建Kubernetes资源时是有前置条件的:
  1. 在新建资源时,labels增加io.contiv.net-group: groupb
  2. Group(app Group)中要关联对应的bandwidth policies
  3. 如果关联bandwidth,则在创建port是,增加限速规则。


10.png

下面看一下详细的调度流程:
  1. 请求创建资源,在经过调度之后,请求创建Pod。
  2. Kubelet负责维护和运行Pod。
  3. Kubelet调用Contiv CNI接口,创建port。
  4. 在创建port中判断rate值和burst是否为空,如果为空,代表不设置QoS,如果为空,QoS规则会建立在具体的port上。
  5. 在openvswitch 2.8.0 以后版本,支持了 meter table限速。这也是我们以后改进的一个方向。


苏宁容器云基于Contiv支持etcd v3

之所以改进etcd版本,在测试过程中发现了ectd v2的若干bug,并且涉及到备份问题,如果存在两个格式的数据,无意增加的恢复难度。

当前Contiv对etcd的支持情况:
  • Contiv支持多种分布式存储,Consul、etcd等
  • Contiv默认仅支持etcdv2 client
  • 预留fakestatedriver.go,支持扩展其它client
  • 保持方法名称不变,使用clientv3重写clientv2方法。


改进后代码结构如下:
11.png

苏宁容器云基于Contiv支持SR-IOV

  • SR-IOV技术是基于硬件的虚拟化解决方案
  • SR-IOV标准允许虚拟化高效共享PCIe设备
  • 可以获取与本机媲美的性能


SR-IOV网络

12.png

Contiv支持SR-IOV从代码级别进行改造

  1. 增加sriovd驱动目录
  2. 仿造FakeNetEpDriver设计sriovd驱动
  3. 需要重新修改Contivinit,以便在初始化Netplugin时,对SR-IOV进行初始化。
  4. 一个Netplugin仅支持一种驱动,但是同一集群内可以有多种网络驱动。


改造后的代码架构图如下:
13.png

Q&A

Q:网络限速的对于系统级别是如何实现的?

A:网络限速其实依然利用的操作系统的特性,比如tc,其实不管是OVS Ingress还是Netlink都是通过和内核通信,将限速规则加入到对应的port上。
Q:上面提到的Kubernetes资源,对于实现Pod-IP固定是有限制的吗?

A:是的,当前仅仅支持Deployment、ReplicaSet、StatefulSet,因为随着对不同资源类型的支持,我们发现处理越多的资源,对于实现IP固定的逻辑就越复杂,比如要判断这个资源是真正删除还是重新调度,在代码级别要处理的很细。所以,我们按照自身的业务特点,现在只实现三种。
Q:RSF系统是什么系统?eBPF和XDP是什么?能简单介绍下吗?

A:eBPF和XDF是Calico网络插件的概念,eBPF(extended Berkeley Packet Filter)起源于BPF,它提供了内核的数据包过滤机制。
BPF的基本思想是对用户提供两种SOCKET选项:SO_ATTACH_FILTER和SO_ATTACH_BPF,允许用户在sokcet上添加自定义的filter,只有满足该filter指定条件的数据包才会上发到用户空间。
Q:您现在用的Contiv版本是多少,通过Pod的什么属性实现Pod IP?实现pod-ip固化目前代码改动量有多大,如果按人天算的话?

A:现在用1.2.0版本,Pod的对应pause容器的IP、Mac。改动量需要30人/天,前提是对代码以及数据结构比较了解,也比较清楚Kubernetes的Pod创建逻辑。
Q:你们做了大量定制化开发,是否提交社区了,如何保障与社区同步?

A:没有提交社区,但是我们发现了一些重要的bug提交了,可能是因为很多代码涉及比较广,并且我们改动的有些并不是思科能够接受的,比如pod-ip固定,这个其实不符合Kubernetes开源思想。
以上内容根据2018年6月12日晚微信群分享内容整理。分享人王晓飞,现担任苏宁云容器网络架构师职位,在针对OpenStack、Kubernetes、Swarm网络架构方面有着专业的研究和理解,在该领域拥有4年以上经验,现在负责苏宁云容器网络架构、OpenStack网络架构、容器集群监控,主导容器云监控系统开发、容器网络需求定制开发。对DevOps理念有很深的掌握。DockOne每周都会组织定向的技术分享,欢迎感兴趣的同学加微信:liyingjiesd,进群参与,您有想听的话题或者想分享的话题都可以给我们留言。

0 个评论

要回复文章请先登录注册