将云原生进行到底:腾讯百万级别容器云平台实践揭秘

代码微光
• 阅读 693

将云原生进行到底:腾讯百万级别容器云平台实践揭秘

导读|基于 K8s 的云原生容器化已经在腾讯内部海量业务中大范围落地实践。业务从传统的虚拟机部署形态无缝切换到容器部署形态,运行在 K8s 上的应用从无状态服务扩展到有状态服务,这个过程经历了哪些改造?同时,K8s 如何经受住业务形态复杂多样、模块数量庞大的考验?遇到哪些新的挑战?如何优化?效果怎么样?腾讯云高级工程师林沐将为你解答。

将云原生进行到底:腾讯百万级别容器云平台实践揭秘

在线业务资源容器化部署的问题与优化方案

腾讯平台的业务基本都属于在线业务。这些业务以前在虚拟机部署时,是通过物理机操办的方式生产出很多虚拟机,对于业务来说是不感知的。当业务发现虚拟机负载较低时,可将多个在线业务混部来提高资源利用率。

将云原生进行到底:腾讯百万级别容器云平台实践揭秘

这种资源管理方式到容器化部署时发生了一些变化,主要有四方面的内容。

容器交付。每个 Pod 在交付的同时需要声明规格大小,规格大小要改变时 Pod 必须销毁重建,无法通过混部来新增业务。节点均衡。K8s 每个节点上部署多个 Pod,每个节点上的 Pod 类型、数量也都不相同,要保证节点均衡是一个挑战。K8s 的云原生特性,也就是弹性,是否能够符合在线业务在生产环境中的需求?集群池化。K8s 是按集群维度管理,而平台有上万个业务,这么多业务如何映射到不同的集群实现条带化管理?

针对上述问题,腾讯采取的优化手段是:

第一,资源利用率提升——动态压缩和超卖。我们面临一个痛点是用户配置的容器规模不合理,普遍偏大,这样节点装箱率和负载比较低。所以第一个优化方式就是 Pod 资源动态压缩,Pod 请求双核处理器 4G 内存,在调度时压缩成单核 4G 内存。因为 CPU 属于可压缩资源,内存属于不可压缩资源。这里修改的只是 Request 大小,并不修改 Limit,所以不影响容器实际能使用的上限值。这样能提高节点的装箱率。接下来是 Node 资源动态超卖,根据负载情况超卖更多 CPU 核心。

第二,节点负载均衡——动态调度和重调度。资源压缩超卖能提高节点的装箱率和负载使用率,但 Pod 是共享Node 的,压缩和超卖会加剧它们之间的干扰。于是我们开发了动态调度器,当每一个 Pod 调度时,能够感知存量 Node 当前的实时负载情况,从而对增量 Pod 在 Node 当中均衡处理,掉到一个低负载的节点上。存量 Pod 在节点上也有可能发生高负载,这时我们在节点上部署 Pod-Problem-Detecor、NodeProblem-Detecor,检测出哪个 Pod 会导致节点高负载,哪些 Pod 属于敏感 Pod,通过事件上报告诉API Server,让调度器将异常 Pod、敏感 Pod 重新调度到空闲节点。

第三,K8s 业务弹性伸缩——协同弹性。在线业务最关心业务稳定性。有时业务负载超出预期时,因为最大负载数配置过低,导致业务雪崩。所以我们对 HPA 进行优化,加入 HPAPlus-Controller,除了支持弹性最大副本策略之外,还能够支持业务自定义配置进行伸缩。第二个是 VPAPlus-Controller,可以 Pod 突发高负载进行快速扩容,对有状态的服务也可以进行无感知扩缩容。

第四,集群资源管理——动态配额和资源腾挪。从平台的角度,K8s 集群也是一个重要的维护对象。平台通过动态 Operator 的方式控制业务对集群的可见性以及配额大小,使得各个集群的业务是分布均匀的。集群本身也有规模大小,有节点伸缩,叫做 HNA。HNA 能够根据集群负载情况自动补充资源或释放资源。生产环境中一种情况是,有时候突发活动,在公共资源池里没有特定资源,需要从其他系统里腾挪资源。所以我们开发了弹性资源计划 Operator,它会给每个节点、每个集群下发任务,要求每个集群释放一些Node 出来。这批节点的数量要尽可能符合业务的数量要求,同时要对存量业务的负载质量不产生影响。我们的方式是通过动态规划的方式解决问题,从而在业务做活动,或者紧急情况下,能够使集群之间的资源也能够流转。

将云原生进行到底:腾讯百万级别容器云平台实践揭秘

容器化对动态路由同步的挑战与解决方案

每一个 Pod 在销毁重建的时候会动态添加或提取路由。一般来说,生产环节中的路由是第三方系统负责,当 Pod 正常的时候系统给它转发流量,或者做名词解析,当它摘除时就从名词服务里剔除。

将云原生进行到底:腾讯百万级别容器云平台实践揭秘

但我们的平台在生产环节中会遇到一些特殊情况。第一个情况就是容器化之后容器的变更更加频繁。第二个变化在于业务规模非常庞大,单个负载的 Pod 可能成千上万。第三是业务层面的变化,云原生的方式是一个集群对一个路由入口,但在生产环节又是第三方路由系统,允许云上云下混合部署,跨集群多路由服务共享路由。动态路由是容器化的关键路径,是要解决的核心问题。

在微观层面,业务对容器运行阶段有特殊需求,包括容器分级、路由和进程的运行状态一致、大批量探针失败时要实现路由熔断。

生产环节中路由系统是非常多的,每个路由系统会对应一种控制组件。所以我们需要路由同步 Controller的统一框架。这个框架理论上是一个旁路 Controller,因此存在不可靠的问题。例如在 Pod 下线前,销毁的时候不保证已经剔除路由;又比如在滚动更新时,可能上一批还没有添加路由,下一批就开始销毁重建。由于有些业务又比较敏感,必须要求绝对保证线下和滚动的时候路由的正确性,于是我们利用了 K8s 云原生的删除保护、滚动更新机制来实现这一需求。当业务在销毁之前先剔除路由,业务在滚动更新的时候先保

证上一批添加。通过这种方式将路由融入到 Pod 生命周期里,来实现业务的可靠性。

对于运行阶段,例如容器异常自动重启,或者 Pod 其中一个容器通过原地生成的方式启动,这些场景就会绕过前面提到的滚动更新和删除保护。所以还要在运行阶段保证业务之间的快速同步。业务大批量变更又会产生大量事件,导致 Controller 积压问题。

对此我们第一个优化方式是使用 Service 粒度事件合并,将事件数量成数量级减少来提高速度。第二个是双队列模型。K8s 的 Controller 里有定时历史对账机制,会将所有的 Pod 对象全部入队列。我们需要将实时和定时的事件分开,这样既能够解决定时对账,又能解决实时处理需求。

这里面有一个细节问题,两个不同队列可能在同一个时刻会有同一个事件要处理,这就需要相互感知的能力避免这种情况发生。

下一个 Controller 框架的核心点在于支持共享路由。但云原生的 K8s 机制里是一个集群对应一个路由入口,所以我们在 Controller 框架里增加一个路由同步记录,也是按照 Service 的粒度去记录的。如果业务系统产生脏数据,例如触发一个剔除操作,但是路由系统返回成功了,实际上没有剔除,那么下一次它去同步处理这个事件的时候发现它没有被剔除,那么还是会再重新剔除一遍。也就是说路由操作等于期望值去 Diff当前值,而它的期望值就等于 Endpoint 和 Pod 生命周期的交集,当前值就是路由系统里面的情况加上路由记录,二者再取差积就是要做的路由操作。

旁路 Controller 作为一个组件会有异常的时候,虽然 K8s 提供 Leader 机制,但这个机制被 Controller拉起时需要预加载存量 service 数据,如果数据量非常大需要很久时间。我们的解决方式是,每一个Controller 运行的时候属于主备模式,这样当主容器挂掉的时候,备容器获得锁,之间的间隔就是整个Controller 同步中断的最长时间,之后备容器就可以快速接管路由通路服务。中断期间可能发生事件丢失问题,我们通过定时历史对账机制解决这个问题。

我们还有特殊需求,是业务为了兼容虚拟机部署的一种管理方式,主要针对容器的运行阶段以及特殊处理。这里的需求包括容器分级、流量平衡、路由熔断。这些需求对传统的 Endpoint Controller 而言是不感知的,原来只维护 Ready 和 Not Ready 的状态,没有感知更细分的状态去维护容器的角色和状态。如果这是由路由 Controller 来实现,那么对这些特殊场景来说是牵一发而动全身的,每一个组件都得同时开发,修改一遍,维护成本是很高的。所以我们提供了一种解决方案——Endpoint-Plus Controller。它将维护容器角色和状态的能力下沉到 Endpoint 来实现。它与 Endpoint 和路由同步 Controller 之间建立一种交互协议,就是 Endpoint Ready 时添加路由,Not Ready 时禁用路由,不在 Endpoint 里删除路由。这样所有组件都是统一的,而且每次业务的新需求只要修改 Endpoint 就对全部生效,这样实现了动态路由同步的桥梁作用。

将云原生进行到底:腾讯百万级别容器云平台实践揭秘

一种全新的容器销毁失败自愈机制探索

最后一个话题是关于容器销毁失败自愈的。前面提到了动态调度、弹性伸缩、容灾迁移、流水线发布,这些操作都有一个前提,就是容器销毁重建时老的容器要销毁,新的容器能创建出来。但实际上在生产环境中这并不是 100% 能保证的。因为容器是共享的,多个容器在同一个节点上,卡住的时候会涉及到很多原因:

调用链很长,只要其中任何软件出现 BUG 都会卡住;管理容器对业务容器有侵入,造成卡顿;业务容器之间互相干扰;共享内核、Cgroup、Namespace,并不保证所有资源绝对完全隔离;共享节点资源,当 CPU、磁盘 IO 高负载时会影响整个节点上的所有 Pod。

K8s 发展到现在已经有了一套很完善的自愈机制。对容器异常来说,云原生 K8s 提供一个暴力解决方案就是强删机制。该机制只是删除这个数据对象的数据,并不是销毁这个容器。这样导致一个问题,如果进行强制销毁,可能老容器会残留,新容器又起来了,这时老的容器会影响节点。

所以容器销毁阶段卡住会影响容器销毁重建这个基本需求,而且它的原因是复杂多样的,在大规模系统环境中更容易出现,而已有的自愈机制是没有涵盖这种场景的,所以我们就需要提供一种全新的自愈机制。传统的解决方案是通过脚本扫描到它,对于定位到的问题,没有解决方案的需要临时隔离,已有解决方案的就要明确修复。但这并不是一个闭环方案,因为还有很多未知问题,对未知问题来说业务关心的是尽可能恢复,而对平台来说为了保证稳定性,需要尽可能知道这些根因,去收敛这类问题。

所以我们兼顾这两个需求,要缩小定位范围、缩短定位周期,提高定位效率。对定位到根因的我们要去评估它的影响面,防止增量发生。而已经有解决方案的,我们需要有全网修复能力,出现异常的时候要告警,从而实现闭环解决方案。

我们想到了是智能运维的方法,它依靠大规模训练样本,关注相关性。而故障处理一般是小样本量,强调专业和因果性,所以它并不很适合这种场景。但在智能运维的决策树模型里有些概念可以拿来参考,譬如基尼系数、信息熵、剪枝等。

将云原生进行到底:腾讯百万级别容器云平台实践揭秘

最后简单介绍一下决策树模型的实现。

第一步需要建立模型,是关于信息熵的权衡,要平衡自愈机制和定位效率。我们在选择信息熵的时候是自顶向下的推导路径,从节点异常再到容器调用链异常,再到具体系统日志。

第二步是特征选取,基尼系数越小特征越明确,所以我们选择共同特征作为一个特征值。同时选择一些已知问题或者根因比较明确的作为叶子节点。

最后一步是模型优化,例如剪枝优化,通过后剪枝的方式解决过拟合现象。同时简化模型。通过这种方式,

当容器发生销毁失败时,能够触发自愈路径。同时,对于新增问题,我们可以缩短问题范围,提高定位效率。

通过以上三步,最终我们探索出了这样一种全新的容器销毁失败自愈机制。期望本文思路对你有帮助~

⛳️公众号粉丝专享:点击文末“阅读原文”,参与调研抽BANQ防水U盘

腾讯工程师技术干货直达:

1、手把手教你搭建Hexo博客

2、如何不改一行代码,让Hippy启动速度提升50%?

3、内存泄露?腾讯工程师2个压箱底的方法和工具

4、一文读懂Go函数调用

点赞
收藏
评论区
推荐文章
作业帮上万个 CronJob 和在线业务混部,如何解决弱隔离问题并进一步提升资源利用率?
作者吕亚霖,作业帮基础架构架构研发团队负责人。负责技术中台和基础架构工作。在作业帮期间主导了云原生架构演进、推动实施容器化改造、服务治理、GO微服务框架、DevOps的落地实践。别路,作业帮基础架构高级研发工程师,在作业帮期间,负责多云K8s集群建设、K8s组件研发、Linux内核优化调优相关工作。背景作业帮在云原生容器化改造的过程中,随着
TKE用户故事 | 作业帮检索服务基于Fluid的计算存储分离实践
作者吕亚霖,2019年加入作业帮,作业帮基础架构架构研发团队负责人,在作业帮期间主导了云原生架构演进、推动实施容器化改造、服务治理、GO微服务框架、DevOps的落地实践。张浩然,2019年加入作业帮,作业帮基础架构高级架构师,在作业帮期间,推动了作业帮云原生架构演进、负责多云k8s集群建设、k8s组件研发、linux内核优化调优、底层服务容器化相关工作。
good123 good123
4年前
奈学p7云原生架构师
云原生的概念主要是基于容器云,其主要原则是,软件产品从设计、开发到交付,全流程都考虑适配容器云的环境。传统的开发,是本地开发与测试,测试环境再次测试,然后部署上线,如果有上容器的需求,那么再编写Dcokerfile,做容器化改造,最后部署到容器云上云原生的产品,开发,测试和上线都是完全兼容容器云的环境,例如通过EclipseChe镜像开发,提交到git上,从
Wesley13 Wesley13
4年前
2019云原生产业大会召开 蚂蚁金服贡献云原生典型实践
4月24日,国内最权威、最大规模的云原生应用大会——2019云原生产业大会在北京召开。本次大会上,中国信息通信研究院重磅发布了《云原生行业应用实践白皮书》和《无服务架构技术白皮书》两份白皮书。《云原生行业应用实践白皮书》系统阐述了云原生架构的主要技术、云原生技术的行业落地实践、云原生应用发展趋势和标准化建议。在金融行业落地实践中,蚂蚁金服的
Stella981 Stella981
4年前
Kubernetes 时代的安全软件供应链
作者汤志敏 阿里云容器服务高级技术专家汪圣平 阿里云云平台安全高级安全专家导读:从Dockerimage到Helm,从企业内部部署到全球应用分发,作为开发者的我们如何来保障应用的交付安全。本文会从软件供应链的攻击场景开始,介绍云原生时代的应用交付标准演进和阿里云上的最佳实践。“没有集装箱,就不会有全球化”。在软件行业里,
Wesley13 Wesley13
4年前
50+云原生大咖集结完毕,CNBPS 2020日程落定,5天后见!
11月1921日,第3届云原生技术实践峰会(CNBPS2020)将首次线上开启。突破时空界限,带你领略云原生“原力”觉醒的魅力。50技术大咖,40演讲议题已全部落定!从主旨演讲中洞察云原生前沿趋势,从各个维度解读云原生全栈技术,在用户和专家的碰撞中探寻最佳实践落地路径
3A网络 3A网络
3年前
容器化 | 在 Kubernetes 上部署 RadonDB MySQL 集群
容器化|在Kubernetes上部署RadonDBMySQL集群RadonDBMySQL是一款基于MySQL的开源、高可用、云原生集群解决方案。支持一主多从高可用架构,并具备安全、自动备份、监控告警、自动扩容等全套管理功能。目前已经在生产环境中大规模的使用,包含银行、保险、传统大企业等。RadonDBMySQLKubernetes
轻量化安装 TKEStack:让已有 K8s 集群拥有企业级容器云平台的能力
关于我们更多关于云原生的案例和知识,可关注同名【腾讯云原生】公众号福利:①公众号后台回复【手册】,可获得《腾讯云原生路线图手册》&《腾讯云原生最佳实践》②公众号后台回复【系列】,可获得《15个系列100篇超实用云原生原创干货合集》,包含Kubernetes降本增效、K8s性能优化实践、最佳实践等系列。③公众号后台回复【白皮书】,可获得《腾讯云容器安
使用 Elastic GPU 管理 Kubernetes GPU 资源
关于我们更多关于云原生的案例和知识,可关注同名【腾讯云原生】公众号福利:①公众号后台回复【手册】,可获得《腾讯云原生路线图手册》&《腾讯云原生最佳实践》②公众号后台回复【系列】,可获得《15个系列100篇超实用云原生原创干货合集》,包含Kubernetes降本增效、K8s性能优化实践、最佳实践等系列。③公众号后台回复【白皮书】,可获得《腾讯云容器安
K8s 如何提供更高效稳定的编排能力?K8s Watch 实现机制浅析
关于我们更多关于云原生的案例和知识,可关注同名【腾讯云原生】公众号福利:①公众号后台回复【手册】,可获得《腾讯云原生路线图手册》&《腾讯云原生最佳实践》②公众号后台回复【系列】,可获得《15个系列100篇超实用云原生原创干货合集》,包含Kubernetes降本增效、K8s性能优化实践、最佳实践等系列。③公众号后台回复【白皮书】,可获得《腾讯云容器安
Kubernetes 资源拓扑感知调度优化
作者星辰算力团队,星辰算力平台基于深入优化云原生统一接入和多云调度,加固容器运行态隔离,挖掘技术增量价值,平台承载了腾讯内部的CPU和异构算力服务,是腾讯内部大规模离线作业、资源统一调度平台。背景问题源起近年来,随着腾讯内部自研上云项目的不断发展,越来越多的业务开始使用云原生方式托管自己的工作负载,容器平台的规模因此不断增大。以Kubernetes
代码微光
代码微光
Lv1
十年一觉扬州梦,赢得青楼薄幸名。
文章
2
粉丝
0
获赞
0