月度归档:2021年08月

京东618:容器技法日趋娴熟,60%业务已切换至Kubernetes

容器技术火遍技术界,很多公司包括传统行业企业都已经从观望者转变为采用者。作为最早期采用容器技术的一批先锋者,京东从 2015 年的 9 千多实例扩大到如今容器作为业务上线默认选项,支撑全部业务运行以及中间件、数据库等。此外,在经历了从 OpenStack 到 Kubernetes 的迁移转变之后,京东容器引擎平台已经从 1.0 迭代到 2.0 版本,并且于今年陆续开源数个项目。

罗马不是一天建成的。

积累如此久并且支撑过 618 大促的京东容器技术是怎样的?有哪些革新又有哪些值得业界学习呢?已经开源的项目是怎样的呢?

容器技术整体概况

今年随着京东业务的飞速发展,京东容器数量上也对应迅速增加。不仅在去年完成京东业务全面运行在 JDOS 容器之上,并且在数据库,中间件等系统也全面容器化。同时,在这一年,京东上线了 JDOS 2.0 系统,开始了从 OpenStack 向 Kubernetes 的迁移。截止到 6 月 7 日,已经有 60% 的业务运行在了 JDOS 2.0 平台中。
此外不得不提及发生的主要变化:业务系统全面基于容器镜像全量上线发布;全面使用集群编排;在生产环境尝试和运行抢占式调度,并自研单层单体全局调度器 SchedulerX;让业务系统与硬件解耦与资源完全解耦,海量资源,从容大促。

自研单层单体全局调度器

正如上文所述,京东在生产环境尝试和运行抢占式调度,并自研单层单体全局调度器 SchedulerX。
SchedulerX 属于 JDOS 弹性计算项目,主要目的是从更高的层面来加强计算资源调度,以提供服务更强的弹性计算能力,提升数据中心资源利用率。

JDOS2.0 主要通过以下三个维度对业务进行优先级分类归集,并实施抢占式调度。

  • 从业务负载层面来对业务分类,根据业务是长时间运行的任务 (long time running) 还是离线计算任务 (offline),采用不同的资源占用优先级和调度模式。
  • 从业务高峰时间段会对各个业务进行归类,例如区分是否白天高峰期还是夜间高峰期,将任务进行混合调度,实现资源的错峰利用。
  • 从资源区域层面对业务分类,例如 GPU 资源、CPU 资源、SSD 资源等。根据业务对于资源的实际需求进行调度。

在保证各个业务 80% 的资源的情况下,20% 的资源在不同时间段可以互相抢占借用。(此比例可以根据实际运营进行调配。例如 618、双 11 大促时,则不允许业务相互抢占,保证资源足够)
在当前没有空闲资源的情况下,JDOS 会根据每个机器上运行的业务的分类对机器打分,如果该机器的分数较低,那么抢占就会发生,低优先级的业务首先会被驱逐 (Eviction) 抢占。被抢占的作业重新回到 PENDING 队列里等待重新调度。

SchedulerX 确保关键业务不会由于资源不足而停止运行,也会重新调度其他业务使其获得更好的安置。

OpenStack No, Kubernetes Yes!

应用容器化遇到的瓶颈

JDOS 1.0 解决了应用容器化的问题,但是依然存在很多不足。

首先是编译打包、自动部署等工具脱胎于物理机时代,与容器的开箱即用理念格格不入。容器启动之后仍然需要配套工具系统为其分发配置、部署应用等等。应用启动的速度受到了制约。其次线上线下环境仍然存在不一致的情况,应用运行的操作环境,依赖的软件栈在线下自测时仍然需要进行单独搭建。线上线下环境不一致也造成了一些线上问题难于在线下复现。更无法达到镜像的“一次构建,随处运行”的理想状态。

再次,JDOS 1.0 时代的容器体量太重,应用需要依赖工具系统进行部署,导致业务的迁移仍然需要工具系统人工运维去实现,难以在通用的平台层实现灵活的扩容缩容与高可用。另外,容器的调度方式较为单一,只能简单根据物理机剩余资源是否满足要求来进行筛选调度。在提升应用的性能和平台的使用率方面存在天花板。

OpenStack PK Kubernetes

Kubernetes 方案与 OpenStack 方案相比,架构更为简洁。OpenStack 整体运营成本较高,因为牵涉多个项目,每个项目各自有多个不同的组件,组件之间通过 RPC(一般使用 MQ) 进行通讯。为提高可用性和性能,还需要考虑各个组件的扩展和备份等。这些都加剧了整体方案的复杂性。问题的排查和定位难度也相应提升,对于运维人员的要求也相应提高。

与之相比,Kubernetes 的组件较少,功能清晰。其核心理念 (对于资源,任务的理解),灵活的设计 (标签) 和声明式的 API 是对 Google 多年来 borg 系统的最好总结。而其提供的丰富的功能,使得京东可以投入更多精力在平台的整个生态上,比如网络性能的提升、容器的精准调度上,而不是容器管理平台本身。尤其是,副本控制的功能受到了业务线上应用运维工程师的追捧,应用的扩容缩容和高可用实现了秒级完成。

改造之路

有了 1.0 的大规模稳定运营作为基础,业务对于使用容器已经给予了相当的信任和支持。但是平台化的容器和基础设施化的容器对于应用的要求也不尽相同。比如,平台化的应用容器IP 并不是固定的,因为当一个容器失效,平台会自动启动另一个容器来替代。新的容器 IP 可能与原 IP 不同。这就要求服务发现不能再以容器 IP 作为主要标识,而是需要采用域名,负载均衡或者服务自注册等方式。因此,在 JDOS 2.0 推广过程中,京东也推动了业务的微服务化,服务框架的升级改造等。

在近两年随着大数据、人工智能等研发规模的扩大,消耗的计算资源也随之增大。因此, 京东将大数据、深度学习等离线计算服务也迁移进入 JDOS 2.0。目前是主要采用单独划分区域的方式,各自的服务仍然使用相对独立的计算资源,但是已经纳入 JDOS 2.0 平台进行统一管理。未来,京东将在此基础上,通过调度将离线计算服务在集群资源充足 (如夜晚) 时给予计算资源扩充,提高计算的效率。

研发成果,两大开源项目

分布式高性能 DNS 项目

JDOS 是如何支持业务的弹性伸缩的?

对于业务的扩展,直接通过调整副本数,横向扩充容器的实例个数。业务如果是 L4/L7 类型的, 使用一个负载均衡来进行流量的分导。 负载均衡项目 ContainerLB 是京东自研的一套基于 DPDK 实现的高性能 L4 负载均衡服务,主要负责 JDOS2.0 的 service 中 LoadBalancer 的实现。

而与 ContainerLB 项目非常密切的还有分布式高性能 DNS 项目 ContainerDNS。(https://github.com/ipdcode/skydns) 为容器提供了内部的 DNS 解析服务。业务如果是微服务类型京东叫 JSF,即需要在 JSF 上进行服务注册与发现的类型,京东则是在容器扩充后,通过服务中间层监听到容器已经启动成功,则对应 Notify JSF。
ContainerDNS,作为京东商城软件定义数据中心的关键基础服务之一,具有以下特点:

  • 高可用
  • 支持自动发现服务域名
  • 支持后端 IP+Port,以及 URL 探活
  • 易于维护和横向动态扩展

ContainerDNS 包括四大组件 DNS server、service to DNS 、user API 、IP status check。这四个组件通过 etcd 数据库集群结合在一起,彼此独立,降低了耦合性,每个模块可以单独部署。DNS server 用于提供 DNS 查询服务的主体,目前支持了大部分常用的查询类型(A、AAAA、SRV、NS、TXT、MX、CNAME 等)。service to DNS 组件是 k8s 集群与 DNS server 的中间环节,会实时监控 k8s 集群的服务的创建,将服务转化为域名信息,存入 etcd 数据库中。

user API 组件提供 restful api,用户可以创建自己的域名信息,数据同样保持到 etcd 数据库中。IP status check 模块用于对系统中域名所对应的 ip 做探活处理,数据状态也会存入到 etcd 数据库中。如果某一个域名对应的某一个 ip 地址不能对外提供服务,DNS server 会在查询这个域名的时候,将这个不能提供服务的 ip 地址自动过滤掉。(关于 ContainerDNS 的更多内容详见本系列的另外一篇文章《京东商城分布式智能容器 DNS 实践》)。

分布式共享存储 ContainerFS 项目

JDOS 是如何支持有状态服务和无状态服务的?

无状态业务的支持相对容易一些,可以直接通过调度自动调整副本数来实现服务的弹性伸缩。对于有状态的业务,原生的 Kubernetes 有 StatefulSet 进行支持,但是 StatefulSet 需要容器一个个启动, 另外社区在这个方面开发进度缓慢。 因此京东选择了自己定制 Kubernetes 进行支持,主要是为本集 (RC/RS/deployment) 提供了 IP 保持不变和存储自动迁移的功能来进行支持。

通过对于每个副本集维护一个小的 IP 池。当副本数调整时,也对应增加或者减少 IP 池中的IP 的数量。副本集中的容器创建时,则使用这个 IP 池中的 IP 进行创建;容器删除时,则将IP 返回到副本集的 IP 池中。

存储也是类似, 对于一个副本集有一个对应的持久化存储 (persistent volume) 的集合。当副本集中的容器创建时,则使用这个 PV 集合中的一个 PV 进行绑定核存储挂载。容器删除时,则对应进行卸载和解除绑定。

针对于容器的存储, 京东没有选用社区已有的 glusterfs 等方案。而是自研一套分布式共享存储 ContainerFS (https://github.com/ipdcode/ContainerFS) 的项目来专门提供容器的存储。
Container File System (简称 ContainerFS)是为 JDOS2.0 系统针对性开发的一个分布式文件系统,同时适用于原生 Kubernetes 集群以及其他应用场景。

ContainerFS 的核心概念是:

a volume = a metadata table + multiple block groups

ContainerFS 的架构图如下:

ContainerFS 的产品特性:

  • 无缝集成 : 支持标准的文件访问协议,支持 fuse 挂载,业务应用无需任何修改即可无缝使用
  • 共享访问:共享访问帮助多个业务应用获得相同的数据来源
  • 弹性伸缩 : 可满足业务增长对文件存储的容量诉求
  • 线性扩展的性能:线性扩展的存储性能,非常适合数据吞吐型的应用

ContainerFS 典型应用:

做为 JDOS2.0 的数据存储引擎,ContainerFS 提供了独享、共享等类型的 volume,并通过 PV 机制挂载给 POD 或者容器使用。

使用效果:

目前 ContainerDNS, ContainerFS 已经开源,ContainerLB 会近期在 GitHub 上开源。

写在最后

为什么要将京东底层技术开源呢?主要两个方面原因:

在底层技术方面,开源是大势所趋。Google 的 borg 系统在过去十余年间一直处于保密状态,但是现在不但公开了,而且利用起核心思想,孵化出了 Kubernetes 项目。而 Kubernetes 项目一经发布,也立即受到了热捧。同时,社区的完善也为 Kubernetes 和 Google 的 borg 提供了更为有益的建议和帮助。当然,不仅仅是 Google,CoreOS、OpenStack、Docker 等等公司和项目的开源大热也说明了这一趋势。

在容器平台实践路上,京东是走的比较早也是比较坚定的。在实践过程中有很多理解和技术视野。比如我们认为容器技术本质是 linux kernel 技术,容器技术需要数据中心底层基础软件全力配合,如分布式域名解析,高性能负载均衡,分布式共享存储,精确授时等等。因此京东在这方面不希望闭门造车,而是能够更多的同业界来分享我们的经验。一方面,为许多底层技术还在摸索中的业内同仁提供一点借鉴和帮助,另一方面,也是希望获取业界的指导,提升京东的基础平台系统和技术思路。

作者介绍

鲍永成,京东商城 基础平台部技术总监。2013 年加入京东,负责京东容器集群平台(JDOS)研发,带领团队完成京东容器大规模落地战略项目,有效承载京东全部业务系统和 80% 数据库,特别在大促期间 scale up 秒级弹性应对高峰流量。目前聚焦在京东容器集群 JDOS 2.0 以及京东敏捷智能数据中心研发。服务过土豆网(TUDOU.COM),思科(CRDC)等,在分布式、虚拟化、容器、数据中心建设有丰富的实践经验。

 

来源:  https://www.kubernetes.org.cn/2177.html

正确的在Kubernetes集群中使用SDN技术方法

SDN是Software-defined networking的缩写。在许多介绍Kubernetes的文档,特别是安装文档中, 当介绍到Kubernetes所需的容器网络时常常会提到这个缩写,告知用户需要使用某种SDN技术用以解决“每个Pod有独立IP, Pod之间可以不经过NAT直接互访”这一Kubernetes集群最基本的技术要求。

大多数非网络工程师背景的技术人员对SDN这个概念会比较陌生,当读到这个段落时,往往会选择把它当作Kubernetes的底层依赖, 照着文档所推荐的流程安装一款SDN工具,比如Flannel,Calico,Weave等。由于不了解这些工具的原理,同时缺乏实际的使用经验, 当出现文档以外的异常情况时,整个安装流程就卡住了。SDN俨然成为了Kubernetes大规模普及的拦路虎。那些按照文档顺利搭建起来的集群当中,还有不少使用了并不适合该集群所处环境的SDN技术,造成了额外的运维负担以及潜在的安全风险。 让我们不得不思考一个问题,怎样才是正确的在Kubernetes集群中使用SDN技术的方法?

今天我们来详细聊聊这个话题。

结论先行

在大多数的Kubernetes集群中,都不需要使用SDN技术,Kubernetes的容器网络要求可以使用更加简单易懂的技术来实现, 只有当企业有特定的安全或者配置要求时,才需要使用SDN技术。SDN应当作为一个附加选项,用以解决特定的技术问题。

理解Kubernetes的容器网络

下图是一张Kubernetes容器网络的示意图

20170204140136

可以看到在图中,每台服务器上的容器有自己独立的IP段,各个服务器之间的容器可以根据目标容器的IP地址进行访问。

为了实现这一目标,重点解决以下这两点:

  • 各台服务器上的容器IP段不能重叠,所以需要有某种IP段分配机制,为各台服务器分配独立的IP段
  • 从某个Pod发出的流量到达其所在服务器时,服务器网络层应当具备根据目标IP地址将流量转发到该IP所属IP段所对应的目标服务器的能力。

总结起来,实现Kubernetes的容器网络重点需要关注两方面,分配和路由。

Flannel的工作方式

这里我们以比较常见的Flannel为例子,看看SDN系统是如何解决分配和路由的问题的。

下图是Flannel的架构示意图

20170204140223

可以看到Flannel依赖etcd实现了统一的配置管理机制。当一台服务器上的Flannel启动时,它会连接所配置的etcd集群, 从中取到当前的网络配置以及其他已有服务器已经分配的IP段,并从未分配的IP段中选取其中之一作为自己的IP段。 当它将自己的分配记录写入etcd之后,其他的服务器会收到这条新记录,并更新本地的IP段映射表。

Flannel的IP段分配发生在各台服务器上,由flannel进程将结果写入到etcd中。路由也由Flannel完成,网络流量先进入Flannel控制的Tunnel中, 由Flannel根据当前的IP段映射表转发到对应的服务器上。

需要指出的是Flannel有多种backend,另外新增的kube-subnet-mgr参数会导致Flannel的工作方式有所不同,在这里就不详细展开了。 有兴趣的朋友可以去查阅Flannel的文档以及源代码了解更多的细节。

更见简化的网络配置方法

Flannel的工作方式有2点是需要注意的。一是所有服务器上运行的Flannel均需要etcd的读写权限,不利于权限的隔离和安全防护。 二是许多教程中所使用的默认backend类型为vxlan,虽然它使用了内核中的vxlan模块,造成的性能损失并不大, 但是在常见的二层网络的环境中,其实并不需要使用Tunnel技术,直接利用路由就可以实现流量的转发, 这时使用hostgw模式就可以达成目标。

大部分的Kubernetes集群服务器数量并不会超过100台,不论是在物理机房当中或是利用IaaS提供的VPC技术,我们会把这些服务器均放在同一个网段, 这时我们可以去掉Flannel这一层,直接使用Kubernetes内置的kubenet功能,配合上我们为Kubernetes定制的hostroutes工具, 即可实现容器网络的要求。

kubenet

kubenet是kubelet内置的网络插件中的一个,它非常的简单,会根据当前服务器对应的Node资源上的PodCIDR字段所设的IP段,配置一个本地的网络接口cbr0, 在新的Pod启动时,从IP段中分配一个空闲的IP,用它创建容器的网络接口,再将控制权交还给kubelet,完成后续的Pod创建流程。

由于kubenet会自己管理容器网络接口,所以使用kubenet时,不需要修改任何的Docker配置,仅需要在启动kubelet时,传入–network-plugin=kubenet 参数即可。

allocate-node-cidrs

allocate-node-cidrs是controller-manager的一个参数,当它和cluster-cidr参数共同使用的时候,controller-manager会为所有的Node资源分配容器IP段, 并将结果写入到PodCIDR字段。

hostroutes

hostroutes是我们为kubenet开发的一个配套小工具,它也非常的简单,它会watch所有的Node资源的变化,用所有Node资源的PodCIDR字段来配置服务器本地路由表。 这时所有Pod发出的流量将通过Linux自带的路由功能进行转发,性能优异。Linux的路由功能也是大部分技术人员已经掌握的技能,理解维护起来没有任何负担。

在这一简化的模式下,controller-manager负责分配容器IP段,kubenet负责本地网络接口的控制,hostroutes负责路由。 我们最大程度使用了Kubernetes已有的功能,并且用hostroutes来解决kubenet只管网络接口不管路由的问题。整个方案中, 需要写入权限的仅有部署在master节点的controller-manager,运行在Node节点上的kubenet和hostroutes均只需要读取权限即可,增强了安全性。 另外此方案将Kubernetes作为唯一的配置来源,去除了对etcd的依赖,简化了配置,降低了运维负担和安全风险。

不同的技术方案虽说实现细节不同,但是只要围绕着分配和路由这两个关键点进行比较,我们就可以更加明确的在不同方案之间进行选择。

容器网络技术方案选型推荐

任何的技术方案都离不开场景,在这里我们根据不同的场景给大家推荐几种技术方案:

  • 单服务器:不需要网络组件,使用Docker自带的网络即可
  • 小规模集群:使用kubenet + hostroutes,简单、易配合管理
  • 云环境中的小规模集群:使用kubenet + master组件上运行的网络控制器,充分利用IaaS所提供的VPC环境中的路由功能,简化网络配置
  • 服务器不在一个网段的集群:使用Flannel提供的vxlan或者其他类似的Tunnel技术
  • 安全要求高的集群:使用Calico或者Open vSwitch等支持Policy的SDN技术

总结

在本篇文章中,我们探讨了Kubernetes的容器网络的工具方式,并以Flannel为案例分析了已有的SDN解决方案,并提出了适合小规模集群的kubenet +hostroutes的解决方案。希望可以帮助读者理清在Kubernetes集群搭建过程中容器网络这一部分的思路,不再因为容器网络影响了Kubernetes的整体使用。

在实际工作中,各个企业对集群的要求都有自己的特点,技术人员需要根据企业的需要,充分比较现有的各种方案的优劣,选择最适合的方案。 直接照抄教程的搭建方式会为将来的运行埋下隐患,应当尽可能的避免。

来源: https://www.kubernetes.org.cn/1342.html