写点什么

京东如何打造 K8s 全球最大集群支撑万亿电商交易

  • 2020-04-15
  • 本文字数:5827 字

    阅读完需:约 19 分钟

京东如何打造K8s全球最大集群支撑万亿电商交易

在过去一年里,Kubernetes 以其架构简洁性和灵活性,流行度持续快速上升,我们有理由相信在不远的未来,Kubernetes 将成为通用的基础设施标准。而京东早在 2016 年年底上线了京东新一代容器引擎平台 JDOS2.0,成功从 Openstack 切换到 JDOS2.0 的 Kubernetes 技术栈,打造了完整高效的 PaaS 平台。


6 月 28 日京东基础架构部技术总监、集群技术部负责人鲍永成受邀出席了 Rancher Labs 举办的Container Day 2018容器技术大会,并做了题为 《京东如何打造 kubernetes 全球最大集群支撑万亿电商交易》 的主题演讲,本文根据演讲内容整理而成。


鲍永成,2013 年加入京东,负责京东容器平台 JDOS 研发工作,带领团队完成京东容器大规模落地战略,全量承载京东全部在线系统、中间件、数据库以及大数据离线计算任务。目前聚焦在京东 JDOS2.0、阿基米德调度平台(特别抢占式智能数据中心调度系统、京东大幅提升数据中心资源使用率的利器)、“云+端”线下门店生态基础设施以及新一代数据中心研发工作。


在演讲中鲍永成分享了京东在大规模实际生产过程对 Kubernetes 做深入重构的经验,以及京东如何围绕 K8s 启动一些内部新项目,服务 JDOS2.0 大规模生产环境稳定高效运行。


感谢 Rancher 邀请我们来做京东在容器方面的分享。京东的分享可能跟业内的很多做向外输出的公司有点不一样,我们的容器主要是自用。京东的数据中心现在规模已经比较大,实际上我们用 Kubernetes 或者是以前用 Openstack 的思路完全是克隆谷歌数据中心管理的理念。

容器生态建设


其实数据中心就是围绕着几个东西来说:服务器、网络以及一些基础软件,剩下的就是集群的管理。这里要说明一下,我们认为基础软件是数据中心非常重要的一个环节,比如,域名解析、负载均衡、时钟这些东西,虽然 Kubernetes 管理了整个集群,但是这些东西它依然没有。也就是说,要是想把它用得非常好的话,这些软件也要进行一些适当的变革。



京东在使用 Kubernetes 管理大数据中心的时候,也围绕着 Kubernetes 在我们内部的数据中心建了很多生态。首先是适合容器化的 DNS,以及适合容器化的负载均衡,还有适合容器化的文件系统、镜像中心等等。这里面特别要说明一点,就是 DNS 跟 LB,Kubernetes 1.9 合入了高性能的负载均衡。


如果在大规模生产环境中,高性能的负载均衡是必不可少的,但这个负载均衡又涉及到另外一些问题。首先,要跟现有的数据中心适配,京东自主研发了一套负载均衡以及 DNS。虽然社区里有 CoreDNS 等等,但是这些 DNS 存在一个问题,就像昨天某厂的一个故障那样,你把所有的东西这个引导这个,那个引导那个。如果你的 DNS 不在容器内的话,带来的后果是很难料想的。因为京东容器已经发展了很多年,数据中心也比较大,我们单个 Kubernetes 集群能够做到 8000 到 10000 台。因为我们的机器实在太多,如果不做大集群的话,人力管理的投入上会非常大。后面我会解释怎么做到这么大规模的集群。


京东容器化的数据中心建设已经四五年了,已经比较稳定了,虽然我们的 Kubernetes 还比较老,是 1.6 版本,但是我们已经有很多改进,我们现在的重点就是往阿基米德,也就是往数据中心的资源调度这个方向发展。去年双十一的时候阿基米德已经上线了,Kubernetes 使用到后期的时候,你会发现 Kubernetes 并不能解决数据中心资源使用率的问题,它其实仅仅解决了你的发布,或者是管理资源的容器这方面的一些东西。



上图是我们数据中心的基础架构,其实比较传统,我们会把负载均衡、域名,以及我们包的这个 Kubernetes 的 API 统一抽象出来,整个就是一套。然后在每个数据中心部署若干套 Kubernetes 集群,每一个 Kubernetes 集群,会管理三个物理 Pod,大概是一万台的规模。



为了配合这个规模,我们做了一些工作。DNS 最早的时候,还没有 CoreDNS 来适配,大家知道每个数据中心最老的 DNS 是 bind9,适配起来是非常痛苦的,它缺 API,缺很多东西。所以我们就自己研发了一套基于 Etcd 的分布式 DNS,当时提供了 RestfulAPI,直接对接的 Kubernetes 的 watch,这样的话我们就能够做一个非常好的适配。但是后来我们发现一个问题,原来你有可能 10 万台物理机,也就假设就是你的 hostname 的解析也就 10 万个,现在不一样了,一台物理机是 100 多个容器,即你增长了 100 倍。这时运维解析的请求量会激增,增长之后会带来一个问题,抖动、延迟都非常大,间接的就影响了你的业务的 TP 响应。因此我们后来又把我们域名解析的服务,改成了 DBTK 的服务,现在的性能是 bind9 的 19 倍,是 CoreOS 的 60 多倍,每秒查询率能冲到 800 万 QBS。

化繁为简 Kubernetes 重构

有人问,京东做一个这么大的 Kubernetes 集群,是不是特别复杂特别容易出错。确实,如果你的集群非常多,假设你有 50 个集群,那么你误操作的概率可能就是这 50 的概率相加。因此京东会把整个 Kubernetes 的集群做减法,并没有做加法,当然这是代表京东的一家之言了,因为我们是自用,并不是往外卖,所以我们主要是做减法,以适合我们使用。



为了适用上万台 Server 的这种规模,最大的问题就是 API 的负载容易崩溃。比如你把 config-map 存到 etcd 里面去,这个设计本身就是有问题的。如果你的规模比较大的话,一定要去改,如果不改,你的集群很快就会崩溃。其实我们的做法其实还比较传统,就是采用一些缓存技术,就比如说 config-map 我们压根是不会放在 etcd 里去的。因为如果你把 config-map 放到 etcd 里去的话,首先假设有一个用户,给你传一百个 20M 的配置文件,你就完蛋了。


其次,京东对 controller 也做了很多重构,虽然社区提供了很多 controller,但我可以保证,这些 controller 绝对没有做严格的关联性测试,也就是说有些 controller 之间互相是有影响的。建议启用任何一个 controller 前都要做严格的分析跟测试。想做大集群的 Kubernetes,必须得去改,而且是做减法式的改。



还有一点,Kubernetes 号称有各式各类功能,我可能要泼一下冷水。京东很多东西的确是基于 Kubernetes 建设起来的,Kubernetes 对我们的帮助非常大,但是它也不是万能的。


Kubernetes 号称的 deployment、金丝雀发布等等一切都非常美好,但是我来自京东基础架构部门,基础部门要服务业务,而业务会给你提很多需求,第一次你听上去可能觉得这需求非常扯,但是你跟他仔细沟通之后,你会发现人家的需求是非常合理的。比如说,他说你金丝雀发布的时候,副本数随机的挑几个,升级了 50%,但有的业务方会要求就要升级某一个特定 IP。他不是对这个 IP 特别有感情,而是因为他配了很多 host,除了有研发还有测试等等,所以你不得不去面临这个问题,像 IP 不变等等这样的一些需求就会蹦出来,我们都要满足他,才能继续往下走。


还有比如说你的节点被物理故障重启等等,这个时候你要充分的考虑是先拉起新调度过来的容器,还是先拉起原来老的容器,这些策略都要针对你自己的业务去改变。


还有,比如有人说京东大促的时候,我们 Kubenetes 整个的弹性速度非常快等等。但是我可以向你保证,如果真正是那种流量高峰瞬间来的时候,这个弹性是绝对跟不上的。因为等你还没弹完,老的已经被打死了,弹几个死几个,所以一般来说,你要用更多的实例,用调度的方式来做,而不是说通过 scale out 这种弹来做,来不及的。



刚才也提到这些策略 IP 不变,还有我们这有一个很有意思的东西,就是支持容器的 rebuild。我们的资源使用率,通过阿基米德调度之后,我们的资源使用率非常紧张,因为少买了很多机器,同时业务又在不断地增长,这个时候我们资源的限额都会被耗尽,在某些情况下甚至调度器也无能为力。


这怎么办?我们采取了一种古老的方法, 跳过调度器,进行本地 rebuild 。因为你的调度有的在排队,有的 depending,但是有一些业务在发布的时候,他会提出一个问题,我原来有 100 个容器,我发布完之后只剩 80 了,另外 20 个容器的资源被别的业务抢走了,这是不能接受的,所以我们也有了这种所谓的优先 rebuild,就是就地 rebuild,这会带来很多好处。


这么做最明显的一个好处,就是拉镜像至少省了一些时间。还有一个明显的好处是,虽然在数据中心依然很复杂,但当业务部署在某一台容器机器上之后,调用的依赖、调用数据库的链路都是经过了大量压测的,已达到相对最优的状态。如果你今天把这容器从 pod1 搬到 pod2,我说物理 pod,从房间 1 搬到房间 2 去了,那可能会带来抖动或者等等情况。当然这并不代表你损失了 Kubernetes 的很多特性。


补充前面的一点,我们的 deployment 做了大量定制,原生的 deployment 其实还是很难满足这样的要求。比如说在线上,因为是面向生产环境,但是生产环境不会那么美好。首先业务,可能上 100 个容器就有两个容器,它的响应很差,这个时候要去排查或者要去进行其他的操作,这个时候用 deployment 做不到,因为一升级就没了。而我们,让它可以指定把这两个停掉,或者是其他操作,反正就是能够指定,就相当于你要改一些东西,改动量不大,只是在它原来基础之上改。

阿基米德调度器


下面说说我们目前的工作重点。京东整个数据中心规模很大,有老有新,整体的资源使用率会有明显的波峰波谷。比如上图黑底图上蓝色的线,1 点到 6 点时中国整个互联网的流量都比较低,但是到 8 点以后流量就开始逐渐攀升。那么 1 点到 6 点是一个非常浪费的阶段,因为我们有大量的计算资源,这时候我们就可以跟大数据产生互补,把在线应用的波谷算力贡献给大数据做离线计算,刚好大数据也是后半夜,相对来说离线任务更多,因为第二天早上要出报表,于是我们做了一个融合的混合部署的项目,就叫阿基米德,就是把大数据的业务给调到在线业务的平台上去。


这里面就涉及到一个问题,就是隔离性。大家都觉得 Docker 的隔离性已经很优秀了,其实并非如此,它的隔离性没有大家想象的那么好,你看到的隔离都是 Namespace 的隔离,真正的性能隔离其实并没有完全做到位。例如内存回收,它其实是操作系统统一进行回收的。比如上面 10 个容器有 5 个容器狂读小文件,这时候突然内存已经到一定阀值了,它就要做一次 slab 回收。一旦 slab 回收,它就都被 block 住了,其他的在线业务都会被卡住,虽然只是毫秒级的,但是会有毛刺,业务就会来问你发生了什么。特别是在线大数据进来之后,这个问题就会被无限放大,因此在这块你要做适当的改动。京东做得比较早,从 2013 年就开始做容器,在过去几年我们在这块已经做了很多工作。


还有另外一个,大家也都感同身受。业务说我需要 100 个容器,每个容器八个核,其实之后发现每个容器只跑了不到 10%的 CPU,这种情况是有可能的。那怎么办?你不能粗暴地只给业务两个核,出问题谁负责?那怎么办?我们就告诉业务我们给了他八个核(其实没有),只要不出事就行了,出了事解释也无用。这会带来一个巨大的收益,就像上图,绿色的部分是我们给的 CPU,红色是实际使用的,那我们至少给他砍一半。这样做了之后你就会发现,即使一年不买机器,机器也是够的。



调度方面的问题,京东整个数据中心都是用 Kubenretes 来管,我们取名为 JDOS,即 JD Datacenter OS,封包了 Kubernetes 然后做了大量的定制。往上层看,JDOS 支持京东的在线业务。在线业务在 2016 年 6·18 之前全部迁完了。然后 2017 年双十一的时候数据库全部都迁完了,到 2018 年初的时候,我们基本上像中间件类的也都大部分迁上来了,也就是说现在我们除了单纯的存储图片,还在用物理机那种存储型的服务器之外,剩下的全在容器上,现在京东已经看不到物理机了。现在正在做的就是把大数据也往上面导。这会带来一个非常好的收益。



但是把大数据及很多其他业务放上 JDOS 之后我们发现,整个调度变得非常复杂,原来的调度器只是考虑哪一台适合放就可以了,用一句话说,它只负责杀,不负责埋。这会带来一个问题,容器运行之后,带来的影响 Kubernetes 是无能为力的,除非崩溃了,它给你再重新拉副本等等。这看上去会很美好,实际上业务会天天投诉你。


为解决这一问题,我们应用上线的时候会要选优先级,如果你的优先级不高的话,有可能会被优先级高的驱逐掉,相当于我们单独对 Kubernetes 重新做一个东西,即我们的驱逐器。驱逐器会对 pod 打上很多标签,比如优先级、容忍度、副本数等等(例如只有一个副本的话,它优先级再低也不能杀)。这很像 OM 的排序,当宿主机的 CPU、内存 load 达到一定上限的时候,我们就会启动这种排序,很快地把它排出来,立马就驱逐,而且驱逐之后,会告诉调度器不要再往这台上调了。因为有可能资源满了,它又给调回来了,你又给驱逐,就形成一个死循环了。其实基本的理念也非常简单,就是 保障优先级的系统 ,大数据是最先优先级,但是在线业务的话,也要往下放,这样就能在有限资源的情况下发挥最大的作用,特别是大促的时候,如果都是靠买机器来支撑的话,这是非常恐怖的一件事情。因为每次大促我们都要按 20 倍来估,这要买多少机器啊。

总结

最后我想分享一些经验与心得体会。


京东最早是 Openstack,在 2016 年切换到了 Kubernetes,这两种系统我一直做下来的,我的感受就是, Kubernetes 正在往 Openstack 这条路上走,越做越庞大,这是一个非常大的问题。诚然,它有很多 feature 要加,这个也可以理解,可它还是得拆,拆成非常小的模块来做。像现在 CNI、CRI、CSI 这些模块的拆离应该是比较好的一个开始。Kubernetes 在中小规模集群是没有问题的,但是它肯定没有官方号称的那样 5000 台没问题,如果是非常大的规模的话,肯定要去改,否则的话会崩溃。我们在早期的时候,上了一些非重要的系统,经历了非常痛苦的一段时间,它时常崩掉了。


有时候 Etcd 跑着跑着就发现版本差异越来越大,那只能把另外两个干掉,把另外一个副本用来复制另外两份,这会带来巨大的问题。Etcd 的运维现在应该没有特别成熟的一些方案,它不像数据库有很成熟的运维方案,毕竟数据放在里面,如果它崩了,数据就很难找回来,这是非常麻烦的一件事。


还有它的 API,因为它是长链接,一般的负载均衡要特别注意起 API 的时候不能一个一个起,起完了它都来连,搞不好都堆到一台上去了,会导致负载不均衡,所以正常来说要先把 API 起好,再去起 Kubernetes,这样负载均衡才会起到作用。


另外,大家一定要特别注意 Kubernetes 对心跳的判断,因为它发生 not ready 的概率太高了。一旦发生节点 not ready 的话,会产生一系列难以预料的状态,比如网络抖动,某台交换机坏了,有可能它就会这样。所以我们建议心跳检测这一块尽量用另外一套系统来做,把你检测的结果反馈给 Kubernetes,这样可能会更好一些。


2020-04-15 23:04874

评论

发布
暂无评论
发现更多内容

云原生训练营 毕业总结

张大彪

云原生

5Why根因分析法:通过好问题引出一个好答案

石云升

1月月更 分析方法

特聘专家朱嘉明:2022,数字经济迈入历史新阶段

CECBC

zip文件自动打包

你?

设计电商秒杀系统

Mars

架构实战营 「架构实战营」

【架构实战营】模块九作业

liu🍊

低代码实现探索(二十)功能的路径

零道云-混合式低代码平台

Go 语言快速入门指南:Go 指针

宇宙之一粟

指针 Go 语言 1月月更

模块五

Only

架构实战营 「架构实战营」

为什么您的企业需要移动CRM系统

低代码小观

移动 CRM CRM系统 客户关系管理系统 企业管理工具

一条 Git 命令减少了一般存储空间,我的服务器在偷着笑

沉默王二

一文带你快速了解 Java 线上问题快速诊断神器 Arthas

zuozewei

性能测试 Java性能 性能分析 Arthas 1月月更

手把手教程|通过部署 Apache Superset 实现 Amazon S3 的数据可视化

亚马逊云科技 (Amazon Web Services)

analytics

ReactNative进阶(十九):React Native 按钮 Touchable 系列组件使用详解

No Silver Bullet

​React Native 1月月更 Touchable

设计电商秒杀系统

Steven

架构实战营

毕业设计

Geek_cb2b43

低代码实现探索(二十一)微流动作返回值类型

零道云-混合式低代码平台

架构实战营-毕业设计

21°Char

【微博评论】功能的高性能高可用计算架构设计

红莲疾风

「架构实战营」

Hoo虎符研究院 | 投资前沿——过去一周顶级投资机构动向

区块链前沿News

虎符 Hoo 虎符交易所 区块链投资

电商秒杀系统设计

天天向上

架构实战营

当使用Vue2+Babel时,如何实现组件重新渲染

吴脑的键客

Vue babel

架构实战营模块九作业

孙志强

架构实战营

Go 语言快速入门指南: Go 并发互斥锁

宇宙之一粟

并发 Go 语言 互斥锁 1月月更

架构训练营 毕业设计

吴霏

架构训练营 「架构实战营」

Three.js 入门指南

devpoint

WebGL 3D渲染 three.js 1月月更

记中山公园全马--一场无准备的马

wood

跑步 300天创作

hw9-毕业项目设计

WWH

架构实战营

基于Mysql,ssm食材采购系统

叫练

ssm 餐厅采购

架构实战营 第 4 期 模块五作业

架构实战营 模块五 「架构实战营」

架构实战营-毕业设计

瓜子葫芦侠

「架构实战营」

京东如何打造K8s全球最大集群支撑万亿电商交易_文化 & 方法_Rancher_InfoQ精选文章