DockOne微信分享( 九十四):唯品会基于Kubernetes的网络方案演进

简介: 本文讲的是DockOne微信分享( 九十四):唯品会基于Kubernetes的网络方案演进【编者的话】本文主要介绍唯品会云平台PaaS在持续集成和持续部署方面,基于Docker和Kubernetes,对网络方案的选型及应用,以及随着业务需求的增加而经历的网络方案变更,包括:
本文讲的是DockOne微信分享( 九十四):唯品会基于Kubernetes的网络方案演进【编者的话】本文主要介绍唯品会云平台PaaS在持续集成和持续部署方面,基于Docker和Kubernetes,对网络方案的选型及应用,以及随着业务需求的增加而经历的网络方案变更,包括:
  1. Kubernetes + Flannel;
  2. 基于Docker libnetwork的网络定制;
  3. Kubernetes + Contiv + kube-haproxy;
  4. 基于Kubernetes的应用容器IP固定方案。

背景简介

PaaS平台持续部署以镜像方式部署,公司业务域对应平台内的应用。平台应用管理包括应用配置管理以及应用的运行态管理。一个应用的运行态对应kubernetes的一个Replication Controller(后面使用RC简称)和一个Service,应用实例对应kubernetes中的Pod, 我们基于这样的管理方式,需要提供应用之间的相互调用,同时对部分应用要提供基于http/tcp的直接访问。

Kubernetes + Flannel

首先说一下Kubernetes Flannel。 Flannel主要提供了跨主机间的容器通信;在kubernetes的Pod、Service模型里,kube-proxy又借助iptables实现了Pod和Service间通信(外部访问Service通过宿主机端口->Cluster IP:Port->Pod IP:Port)。

基于这种网络访问功能,我们平台提供了以下功能:
  • 基于gorouter提供的平台域名的访问 – watch k8s endpoints event管理router信息;
  • 基于skydns并定制化kube2sky组件和kubelet,提供同一命名空间下应用(Pod)之间基于业务域名的访问 - kube2sky基于Kubernetes Service annotation解析并注册域名信息、kubelet设置容器启动时的domain search及外部DNS;
  • 实现容器tty访问控制台 - 每台Kubernetes node部署平台组件 tty agent(根据Pod所属node信息,建立对应Kubernetes结点的tty连接);

网络访问关系图如下:
flannel.png

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

基于Docker libnetwork的网络定制

在Flannel网络稳定使用后,开始研究network plugin以使应用服务实例以public IP 方式供用户直接使用。当时Docker的版本为1.8,本身还不支持网络插件,同时Kubernetes本身提供一套基于CNI的网络插件, 但本身有bug [CNI delete invoked twice with non-infra container id #[20379]( https://github.com/kubernetes/ ... /2037 9) ]。于是尝试从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);

libnetwork_flow.png

整个方案包括以下三个流程:
  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;

Kubernetes + Contiv + kube-haproxy

随着Docker版本的推进,Docker1.9开始支持Contiv Netplugin,我们开始研究Contiv应用,同时也完成了使用HAProxy替换kube-proxy的开发 [ https://github.com/AdoHe/kube2haproxy ],并最后采用Docker 1.10 Contiv上线。

[Contiv的网络模型在之前的分享 http://dockone.io/article/1691  里已经有详细解释]这里根据我们实际网络访问关系再描述下PaaS在Contiv整体部署结构:
contiv.png

Kube-haproxy替代了kube-proxy,主要是提供服务IP的公共调用,同时避免了容器数量增加后带来的iptables规则的大量增长,方便调试。这里要注意的是Haproxy所部署机器IP和Kubernetes Service IP要在同一网段。

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

应用容器IP固定

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

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

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

作为Pod层面的IPAM,我们把这一功能直接集成在了Kubernetes。Pod作为Kubernetes的最小调度单元,原有的Kubernetes 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操作流程图:
pod-registry.png

在原有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地址回收站,也是实现Pod Consistent 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时序图如下:
pod-create.png

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

删除Pod的UML时序图如下:
pod-delete.png

Pod的删除流程触发情形:删除应用/应用缩容/重新部署重建策略。

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

另外为了防止出现问题,我们在kubernetes中加入了额外的REST API:包括对已分配IP的查询,手动分配/释放IP等。

总结

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

Q&A

Q:想问下这个IP外网可以直接访问吗?
A:在Flannel网络下不可以直接访问Pod,在Contiv网络下,Pod所分配的网段是在交换机端打了tag的,默认办公网络是可以直接访问的。
Q:贵司花了相当大的精力去做容器互通并显著提高了复杂度,如果直接用Kubernetes的host network方式是否可以直接绕过这些复杂点?
A:首先是公司业务的需求。公司有1k+的业务域,运行在不同的Docker容器里,每个业务域的配置基本是固定的,比如Tomcat或Nginx使用的端口,如果使用host network的话,端口冲突是面临的首要问题,整个服务化的管理方式也要改变了。
Q:文中提到一个应用的运行态对应Kubernetes的一个RC和Service,RS是否好过RC?
A:我们的Kubernetes版本是1.2,Kubernetes 1.2里面RS这个东西还处于一个非常早期的版本,后面才有的,RS也是推荐的下一代RC。
Q:什么样的应用必须要固定IP,是否有其他办法可以避开?
A:业务域之间相互调用,有些业务域要求提供调用方白名单。还有些业务域会需要线上的数据访问,要加入相应的防火墙权限等。
Q:固定ip的情况下:容器的IP是通过桥接到宿主机的网桥连接到宿主机网络的吗?
A:固定IP的情况下,仍然是基于Contiv 的网络工作方式,只是在Docker运行时由IPAllocator负责分配好IP,Docker启动时使用--ip的方式绑定该IP。当前OVS的工作方式也是通过ovsbridge连接到宿主机的物理网卡的。
Q:固定IP,分配的IP需要和宿主机同网段吗?
A: Kubernetes node主机网段和pod网段是不同的。原则上可以相同也可以不同。
Q:Kubernetes支持Docker启动加参数吗,例如--ip?
A:默认不支持,我们对kubelet做了一些修改: 例如通过参数传入vlan id以及根据PodSpec中所分配IP指定docker run的 --ip。
Q:据我了解Contiv现在更多的是对CNM的支持, 对Kubernetes的话 你们定制开发的多吗?
A:Kubernetes用的CNI,我们用的是CNM。更多是适应当前的Contiv对相关组件做修改,以及后面的固定IP(把IPAM集成到了Kubernetes APIServer)。

以上内容根据2016年11月8日晚微信群分享内容整理。分享人王成昌,唯品会PaaS平台高级开发工程师,主要工作内容包括:平台DevOps方案流程优化,持续部署,平台日志收集,Docker以及Kubernetes研究。 DockOne每周都会组织定向的技术分享,欢迎感兴趣的同学加微信:liyingjiesz,进群参与,您有想听的话题或者想分享的话题都可以给我们留言。

原文发布时间为:2016-11-09

本文作者:王成昌

本文来自云栖社区合作伙伴Dockerone.io,了解相关信息可以关注Dockerone.io。

原文标题:DockOne微信分享( 九十四):唯品会基于Kubernetes的网络方案演进

相关实践学习
深入解析Docker容器化技术
Docker是一个开源的应用容器引擎,让开发者可以打包他们的应用以及依赖包到一个可移植的容器中,然后发布到任何流行的Linux机器上,也可以实现虚拟化,容器是完全使用沙箱机制,相互之间不会有任何接口。Docker是世界领先的软件容器平台。开发人员利用Docker可以消除协作编码时“在我的机器上可正常工作”的问题。运维人员利用Docker可以在隔离容器中并行运行和管理应用,获得更好的计算密度。企业利用Docker可以构建敏捷的软件交付管道,以更快的速度、更高的安全性和可靠的信誉为Linux和Windows Server应用发布新功能。 在本套课程中,我们将全面的讲解Docker技术栈,从环境安装到容器、镜像操作以及生产环境如何部署开发的微服务应用。本课程由黑马程序员提供。     相关的阿里云产品:容器服务 ACK 容器服务 Kubernetes 版(简称 ACK)提供高性能可伸缩的容器应用管理能力,支持企业级容器化应用的全生命周期管理。整合阿里云虚拟化、存储、网络和安全能力,打造云端最佳容器化应用运行环境。 了解产品详情: https://www.aliyun.com/product/kubernetes
相关文章
|
5月前
|
数据采集 存储 算法
MyEMS 开源能源管理系统:基于 4G 无线传感网络的能源数据闭环管理方案
MyEMS 是开源能源管理领域的标杆解决方案,采用 Python、Django 与 React 技术栈,具备模块化架构与跨平台兼容性。系统涵盖能源数据治理、设备管理、工单流转与智能控制四大核心功能,结合高精度 4G 无线计量仪表,实现高效数据采集与边缘计算。方案部署灵活、安全性高,助力企业实现能源数字化与碳减排目标。
156 0
|
3月前
|
存储 网络协议 数据库
脑控网络设计方案
本内容详细描述了一个虚构的“脑控通信网络”系统架构及通信流程,涵盖核心网络组成、用户开户流程、心灵感应终端注册、跨网络通信机制,以及脑控网与互联网、移动网的数据交互方式。内容包含模拟的通信协议设计、数据包标识、网络路由机制等技术细节,整体基于作者原创的设定,用于探讨未来通信的可能性。
202 74
|
数据采集 数据安全/隐私保护
脑控网络设计方案续写
本文补充说明了普通设备通过脑控终端热点接入互联网的数据传输流程,涵盖连接认证、数据包标识、核心网绑定与编号生成、数据转发及断开连接的完整过程,详述了设备间通信、验证、路由与逻辑删除机制,完善了脑控网络与普通互联网交互的技术闭环。
|
11月前
|
Web App开发 监控 网络协议
网络分析与监控:阿里云拨测方案解密
阿里云网络拨测业务提供了全球、多种协议、多种网络态势的用户网络性能和用户体验监控场景的全面可观测方案。该文章从拨测场景下,介绍了用户如何快速的构建一套全球用户视角的服务可用性大盘,为客户的业务保驾护航。
1419 166
|
6月前
|
机器学习/深度学习
解决神经网络输出尺寸过小的实战方案
在CIFAR10分类模型训练中,因网络结构设计缺陷导致“RuntimeError: Given input size: (256x1x1). Calculated output size: (256x0x0)”错误。核心问题是六层卷积后接步长为2的池化层,使特征图尺寸过度缩小至归零。解决方案包括调整池化参数(如将部分步长改为1)和优化网络结构(采用“卷积-卷积-池化”模块化设计)。两种方案均可消除报错,推荐方案二以平衡特征表达与计算效率。
|
8月前
|
人工智能 运维 监控
阿里云携手神州灵云打造云内网络性能监测标杆 斩获中国信通院高质量数字化转型十大案例——金保信“云内网络可观测”方案树立云原生运维新范式
2025年,金保信社保卡有限公司联合阿里云与神州灵云申报的《云内网络性能可观测解决方案》入选高质量数字化转型典型案例。该方案基于阿里云飞天企业版,融合云原生引流技术和流量“染色”专利,解决云内运维难题,实现主动预警和精准观测,将故障排查时间从数小时缩短至15分钟,助力企业降本增效,形成可跨行业复制的数字化转型方法论。
450 6
|
8月前
|
安全 网络安全 定位技术
网络通讯技术:HTTP POST协议用于发送本地压缩数据到服务器的方案。
总的来说,无论你是一名网络开发者,还是普通的IT工作人员,理解并掌握POST方法的运用是非常有价值的。它就像一艘快速,稳定,安全的大船,始终为我们在网络海洋中的冒险提供了可靠的支持。
257 22
|
9月前
|
Kubernetes Shell Windows
【Azure K8S | AKS】在AKS的节点中抓取目标POD的网络包方法分享
在AKS中遇到复杂网络问题时,可通过以下步骤进入特定POD抓取网络包进行分析:1. 使用`kubectl get pods`确认Pod所在Node;2. 通过`kubectl node-shell`登录Node;3. 使用`crictl ps`找到Pod的Container ID;4. 获取PID并使用`nsenter`进入Pod的网络空间;5. 在`/var/tmp`目录下使用`tcpdump`抓包。完成后按Ctrl+C停止抓包。
341 12
|
11月前
|
存储 运维 Kubernetes
正式开源,Doris Operator 支持高效 Kubernetes 容器化部署方案
飞轮科技推出了 Doris 的 Kubernetes Operator 开源项目(简称:Doris Operator),并捐赠给 Apache 基金会。该工具集成了原生 Kubernetes 资源的复杂管理能力,并融合了 Doris 组件间的分布式协同、用户集群形态的按需定制等经验,为用户提供了一个更简洁、高效、易用的容器化部署方案。
516 16
正式开源,Doris Operator 支持高效 Kubernetes 容器化部署方案
|
10月前
|
Kubernetes 持续交付 开发工具
阿里云协同万兴科技落地ACK One GitOps方案,全球多机房应用自动化发布,效率提升50%
阿里云协同万兴科技落地ACK One GitOps方案,全球多机房应用自动化发布,效率提升50%
404 2

推荐镜像

更多