基于Kubernetes(k8s)网络方案演进

时间:2022-12-10 21:08:29

VIP PaaS在接近两年时间里,基于kubernetes主要经历四次网络方案的变迁:

1. kubernetes + flannel

2. 基于Docker libnetwork的网络定制

3. kubernetes + contiv + kube-haproxy

4. 应用容器IP固定

先简单说一下背景,PaaS平台的应用管理包括应用配置管理,应用的运行态管理。一个应用的运行态对应kubernetes的一个Replication Controller(后面使用RC简称)和一个Service,应用实例对应kubernetes中的Pod, 我们基于这样的管理方式,需要提供应用之间的相互调用,同时对部分应用要提供基于http/tcp的直接访问。

首先说一下kubernetes + flannel。

flannel主要提供了跨主机间的容器通信;

在kubernetes的Pod、Service模型里,kube-proxy又借助iptables实现了Pod和Service间通信。

基于这种网络访问功能,我们平台提供了以下功能:

基于gorouter提供的平台域名的访问 – watch k8s endpoints event管理router信息;

基于skydns并定制化kube2sky组件和kubelet,提供同一命名空间下应用(Pod)之间基于业务域名的访问 – kube2sky基于k8s Service annotation解析并注册域名信息、kubelet设置容器启动时的domain search及外部dns;

实现容器tty访问控制台 – 每台k8s node部署平台组件 tty agent(根据Pod所属node信息, 建立对应k8s结点的tty连接);

网络访问关系图如下:

基于Kubernetes(k8s)网络方案演进
在k8s + flannel的模型下,容器网络是封闭子网,可以提供平台内部应用之间基于4层和7层的调用,同时对外部提供应用基于域名(工作在七层)的直接访问,但无法满足用户在平台外部需要直接使用IP访问的需求。

在flannel网络稳定使用后,开始研究network plugin以使应用服务实例以public IP 方式供用户直接使用。

当时docker的版本为1.8, 本身还不支持网络插件.同时 kubernetes本身提供一套基于CNI的网络插件, 但本身有bug[CNI delete invoked twice with non-infra container id #20379]。

于是我们尝试从docker network plugin的角度入手,结合libnetwork从docker源码的角度进行定制。

整个架构分为三层:

  1. Client Layer – Docker CLI和kubernetes(Docker client);
  2. Docker Layer – Docker daemon 并在代码层面集成libnetwork(内置OVS driver);
  3. Controller Layer – ovsdb-server及network controller(自开发IPAM);

整体访问结构图:

基于Kubernetes(k8s)网络方案演进

整个方案包括以下三个流程:

1. 启动Docker Daemon:

初始化network controller -> 加载OVS Driver -> OVS Driver调用libovsdb创建docker0-ovs Bridge -> OVS Driver将主机上的一物理网卡attach到docker0-ovs上;

2. 启动容器:

OVS Driver 创建veth pair 用于连接network namespaces -> OVS Driver调用network controller获取容器IP和VLAN Tag -> OVS Driver将veth pair的一端添加到docker0-ovs上,并设置VLAN Tag -> OVS Driver设置容器内interface的IP,Mac Address以及路由 -> 设置各network interface为up;

3. 停止容器:

OVS Driver调用network controller释放容器IP -> 删除network link -> OVS Driver调用libovsdb删除port;

libnetwork工作完成了测试阶段但没有经历上线,随着Docker版本的推进,Docker1.9开始支持 contiv netplugin,我们开始研究contiv应用,在期间我们也完成了使用haproxy替换kube-proxy的开发[https://github.com/AdoHe/kube2haproxy],并最后采用docker1.10+contiv上线。

这里根据我们实际网络访问关系再描述下PaaS在contiv整体部署结构:

基于Kubernetes(k8s)网络方案演进

Kube-haproxy替代了kube-proxy,主要是提供服务ip的公共调用,同时避免了容器数量增加后带来的iptables规则的大量增长,方便调试。

contiv带来的方便是用户可以根据实例IP直接进行访问;我们在使用过程中整体比较稳定,中间出现过一次问题: 机房停电导致了部分IP的分配状态不正确,而且contiv当时还没有提供查看已分配IP的接口。

Docker 1.10版本支持指定IP启动容器,并且由于部分应用对实例IP固定有需求,我们开始着手容器IP固定方案的设计与开发。

前面提到应用运行时,对应k8s内一个ReplicationController以及一个Service。 应用的重新部署目前采用的策略主要是重建策略。 重建的流程包括删除RC及RC下所有Pod,更新并创建新的RC(kubernetes会根据RC配置产生新的POD)。

在默认的k8s+contiv的网络环境下,容器(Pod)的IP网络连接是由contiv network plugin来完成的, contiv master只实现了简单的IP地址分配和回收,每次部署应用时,并不能保证Pod IP不变。所以我们引入了新的Pod层面的IPAM,以保证同一个应用多次发生部署时,Pod IP始终是不变的。

作为Pod层面的IPAM,我们把这一功能直接集成在了kubernetes。Pod作为k8s的最小调度单元,原有的k8s Pod Registry(主要负责处理所有与Pod以及Pod subresource相关的请求:Pod的增删改查,Pod的绑定及状态更新,exec/attach/log等操作) 并不支持在创建Pod时为Pod分配IP,Pod IP是通过获取Pod Infra Container的IP来获取的,而Pod Infra Container的IP即为contiv动态分配得来的。

Pod Registry 访问设计图:

基于Kubernetes(k8s)网络方案演进

在原有kubernetes代码基础上,我们修改了Pod结构(在PodSpec中加入PodIP)并重写了Pod Registry 同时引入了两个新的资源对象:

1. Pod IP Allocator: Pod IP Allocator是一个基于etcd的IP地址分配器,主要实现Pod IP的分配与回收。
Pod IP Allocator通过位图记录IP地址的分配情况,并且将该位图持久化到Etcd;

2. Pod IP Recycler: Pod IP Recycler是一个基于etcd的IP地址回收站,也是实现PodConsistent IP的核心。Pod IP Recycler基于RC全名(namespace + RC name)记录每一个应用曾经使用过的IP地址,并且在下一次部署的时候预先使用处于回收状态的IP。

Pod IP Recycler只会回收通过RC创建的Pod的IP,通过其他controller或者直接创建的Pod的IP并不会记录,所以通过这种方式创建的Pod的IP并不会保持不变; 同时Pod IP Recycle检测每个已回收IP对象的TTL,目前设置的保留时间为一天。

这里对kubelet也进行了改造,主要包括根据Pod Spec中指定IP进行相关的容器创建(docker run加入IP指定)以及Pod删除时释放IP操作。

创建和删除Pod的UML时序图如下:

基于Kubernetes(k8s)网络方案演进

Pod的创建在PaaS里主要有两种情形:

  1. 应用的第一次部署及扩容,这种情况主要是从IP pool中随机分配;
  2. 应用的重新部署:在重新部署时,已经释放的IP已根据RC全名存放于IP Recycle列表中,这里优先从回收列表中获取IP,从而达到IP固定的效果。

基于Kubernetes(k8s)网络方案演进

整体删除过程为:由PaaSNg或kube-controller-manager调用apiserver Pod Delete并设置DeletionTimestamp, kubelet监听到删除时间并获取GracefulDeletiontime,删除应用容器, 通知apiserver释放IP(释放IP时获取Pod所属RC,根据是否有对应RC 名称决定是否存放在IP Recycle列表),删除Pause Pod,通知apiserver 删除Pod对象。

另外为了防止IP固定方案中可能出现的问题,我们在kubernetes中加入了额外的REST api: 包括对已分配IP的查询,手动分配/释放IP..。

对目前方案的总结:

容器IP固定方案已上线,运行基本没问题,但稳定性有待提升。主要表现为偶然性不能在预期时间内停止旧Pod,从而无法释放IP造成无法复用(初步原因是由于Docker偶尔的卡顿造成无法在规定时间内停止容器)。我们短期的work around是使用额外添加的REST apiss手动修复,后期IP固定方案会继续加强稳定性并根据需求进行优化。

基于Kubernetes(k8s)网络方案演进的更多相关文章

  1. 【Kubernetes】K8S网络方案--最近在看的

    K8S网络-最近在看的 Create a Minikube cluster - Kubernetes Kubernetes Documentation - Kubernetes Kubernetes ...

  2. Kubernetes(k8s)网络插件(CNI)的基准测试对比

      Kubernetes是一个伟大的容器"乐队".但它不管理Pod-to-Pod通信的网络.这是容器网络接口(CNI)插件的使命,它是实现容器集群工具(Kubernetes,Mes ...

  3. k8s 各种网络方案 - 每天5分钟玩转 Docker 容器技术(170)

    网络模型有了,如何实现呢? 为了保证网络方案的标准化.扩展性和灵活性,Kubernetes 采用了 Container Networking Interface(CNI)规范. CNI 是由 Core ...

  4. Kubernetes网络方案的三大类别和六个场景

    欢迎访问网易云社区,了解更多网易技术产品运营经验. 本文章根据网易云资深解决方案架构师 王必成在云原生用户大会上的分享整理. 今天我将分享个人对于网络方案的理解,以及网易云在交付 Kubernetes ...

  5. k8s 各种网络方案【转】

    网络模型有了,如何实现呢? 为了保证网络方案的标准化.扩展性和灵活性,Kubernetes 采用了 Container Networking Interface(CNI)规范. CNI 是由 Core ...

  6. ASP.NET Core on K8S深入学习(11)K8S网络知多少

    本篇已加入<.NET Core on K8S学习实践系列文章索引>,可以点击查看更多容器化技术相关系列文章. 一.Kubernetes网络模型 我们都知道Kubernetes作为容器编排引 ...

  7. 【Kubernetes】K8S 网络隔离 方案

    参考资料: K8S-网络隔离参考 OpenContrail is an open source network virtualization platform for the cloud. – Kub ...

  8. 开发环境下的 Kubernetes 容器网络演进之路

    马蜂窝技术原创文章,更多干货请搜索公众号:mfwtech 使用 Docker+Kubernetes 来简化开发人员的工作流,使应用更加快速地迭代,缩短发布周期,在很多研发团队中已经是常见的做法. 如果 ...

  9. 浅谈K8S cni和网络方案

    此文已由作者黄扬授权网易云社区发布. 欢迎访问网易云社区,了解更多网易技术产品运营经验. 在早先的k8s版本中,kubelet代码里提供了networkPlugin,networkPlugin是一组接 ...

随机推荐

  1. 4款最具影响力的自助式BI工具

    数据为王的时代,人人都需要掌握一些数据分析技能.不懂SQL,不懂数据库,Excel不精通,VBA不敢碰,这些都是横亘在面前的一道坎. 然而,企业数据分析日益上涨,数据人才供不应求,为了降低入门门槛,近 ...

  2. 搭建AngualarJS开发环境

    1.选择Web浏览器 Chrome和Firefox浏览器 2.选择代码编辑器 Subline Text和Visual Studio Code 3.安装Web服务器 3.1Apache HTTP Ser ...

  3. &lbrack;转&rsqb;&&num;39&semi;&&num;39&semi;&bsol;&bsol;&equals;DevExpress 中 汉化包 汉化方法

    [DevExpress]DevExpress 中 汉化包 汉化方法 2016-02-17 21:13 1781人阅读 评论(0) 收藏 举报  分类: DevExpress(24)  版权声明:本文为 ...

  4. 3140&colon;&lbrack;HNOI2013&rsqb;消毒 - BZOJ

    题目描述 Description 最近在生物实验室工作的小 T 遇到了大麻烦. 由于实验室最近升级的缘故,他的分格实验皿是一个长方体,其尺寸为 a*b*c,a.b.c均为正整数.为了实验的方便,它被划 ...

  5. Spring笔记之&lpar;一&rpar;初探

    对spring框架的学习我是从模拟它的简单实现开始,这样也易于领悟到它的整个框架结构,以下是简单实现的代码: 配置文件:spring.xml <?xml version="1.0&qu ...

  6. NPOI导入导出Excel

    .net mvc利用NPOI导入导出excel 注意:如何导出的提交方式ajax导出是失效的! 解决方案是:js处理l两个表单的提交  代码:  第一步. 在页面里面加入2个隐藏的iframe, 如下 ...

  7. Android学习总结——Service组件

    从Service的启动方式上,可以将Service分为Started Service和Bound Service.在使用Service时,要想系统能够找到此自定义Service,无论哪种类型,都需要在 ...

  8. Eclipse Workspace Unavailable

    开启Eclipse 提示: Workspace Unavailable: Workspace in use or cannot be created, choose a different one. ...

  9. JavaScript的作用域详解。

    首先讲原理,大家都知道JS是逐行执行,首先进入作用域只有有两种方式:  1.当看到script标签的时候,进入到作用域,也就是内置的<script></script>     ...

  10. python之&commat;property

    在绑定属性时,如果我们直接把属性暴露出去,虽然写起来很简单,但是,没办法检查参数,导致可以把成绩随便改: s = Student() s.score = 9999 这显然不合逻辑.为了限制score的 ...