以 Kubernetes 为代表的云原生技术底座支撑了字节跳动业务的快速发展。从微服务场景开始,Kubernetes 逐渐演化统一支撑了字节内部的大数据、机器学习以及存储服务等多种形态基础设施。
字节跳动云原生历程
技术体系概览
举个例子,字节跳动目前有超过 10 万个在线服务,在线集群中有超过一千万的 Pod,这些服务每天都有超过 2 万次的变更。平均来看,字节的业务系统每五天就会更新一遍。为了处理数据报表和机器学习训练,每天有超过 1.5 亿的离线任务数量处理数十 EB 的存储资源。
字节的基础设施面临的是一个规模巨大且持续快速变化的业务场景。
字节云原生推进历程
在快速变化和规模挑战下,云原生技术,特别是与云原生相关的资源调度技术在字节是如何发展的呢?
2016 年,字节跳动云引擎 TCE(Toutiao Cloud Engine)启动建设。以 Kubernetes 作为底层容器编排引擎,提供快捷高效的应用部署方案;
2018 年:微服务架构升级。完成核心业务微服务迁移,并在 TCE 之上构建服务框架、Mesh、监控告警等基础设施;
2019 年:“推广搜”云原生。把“推广搜”的物理机服务与在线服务进行全面融合,实现统一容器化调度;
2020 年:在离线调度融合、存储云原生。融合资源管理形态,简化供应链选型;优化运维效率,开启数据库、缓存等存储系统的云原生化改造;
2021 年:联邦化多集群演进。从资源多云到应用多云,实现全场景应用编排和资源管理的标准化和统一化。
目前基础架构的重点建设领域是基于联邦化的多集群资源的统一管理和统一调度。
字节云原生发展动机
研发效率上:云原生技术体系的底层资源模型简化了服务部署等方面的运维管理成本,使得业务团队可以更加聚焦于自身核心业务逻辑开发,从而实现快速的业务迭代;
资源效率上:字节大范围地合并资源池,增加资源交互弹性。在大型资源池下,基础设施团队可以集中通过调度等手段去优化资源效率,帮助业务团队获得更低的资源成本。
我们把和云原生相近的技术体系分成了 DevOps、Cloud Native 以及 Serverless 三代。
DevOps:更多强调管理和运维的自动化。主流的服务开发模式是以虚拟机作为底层的资源抽象模型,以 Jenkins 之类的一些自动化管理平台来部署单体应用,进而实现运维管理自动化;
Cloud Native:以微服务模式为主。在资源方面以容器作为更小、更灵活的资源交付单元,辅以 Kubernetes 等容器编排引擎,来管理服务的部署和运维。开发者的效率得到了更大的释放,极大增加了业务产品自身的迭代效率;
Serverless:开发者以函数或者极度简化的微服务代码来表达自身的业务逻辑,以事件作为数据模型来表达服务上下游之间的请求和响应。把容量管理、请求路由和服务治理等运维层面的需求下沉到底层的基础设施来统一支持,服务开发者只需聚焦在自己的业务逻辑上。开发和生产的效率会进一步提升。
这三代技术总体是沿着两个路径在往前推进,分别是产品前向一体化,以及资源规模化。这两种思路从两个角度分别推动着技术体系的演进。
产品前向一体化:这种思路的核心是如何标准化地把业务的计算逻辑、数据管理模型、资源管理等方面的共性需求抽取出来,沉淀到基础设施当中,使得开发者可以用更少、更简洁的代码高效表达自身的需求;
资源规模化:这种思路更多体现在优化上,关注资源池本身的规模化优势,通过大量的并池、资源的混用以及调度等优化手段,实现资源成本降低的目的。
从技术体系迭代来看,字节跳动技术体系往后迭代方向可以总结为下面的主题:
无需管理的基础设施
自动扩展和伸缩
提升开发效率
提升资源效率
按需付费,节省成本
在大量字节业务完成了云原生改造,实现了资源统一托管之后,从全局来看,如何才能够高效地管理并经营好集团资源,这是我们首先面临的问题。要回答好这个问题,需要先解释理想状态下的资源管理模型。
在资源管理的理想状态下,我们给开发者提供的是一个统一的资源入口,在这个入口下,用户可以从统一的资源池获取资源。
在面向业务和应用方面,我们希望开发者可以极度灵活地获取所需资源,像获取“自来水”一样获取各种形态的资源。虽然他们自身的资源需求复杂,有各种各样形态和要求,但是都可以做到随用随取、随取随有的状态。
在资源管理方面,我们希望给用户呈现的是统一的资源池场 —— 一个充分并池混合的资源池。这个资源池具备全局最优的资源效率,能够统一管理多区域、多计算架构的资源。不同的业务形态和团队之间的资源就可以灵活调配。
但落实到实际资源需求场景,各业务用户对于资源的需求是极度复杂的。
从整体来看,字节内部目前托管的平台租户包含在线服务、机器学习平台、数据平台, FaaS 以及部分的存储业务。这些平台租户的应用模型有很大的差别,包含无状态的应用模型、有状态的模型、批式应用等等。
除了业务场景的复杂需求外,安全、性能以及容灾等方面也会为底层的资源管理带来冲击:
以性能角度为例,不同的业务系统,对于底层的资源算力、计算平台架构都有不同程度的感知力,需要根据不同的业务情况针对性做到最优的性能优化收益;
在容灾和安全隔离方面,需要分割不同的业务线常使业务系统能够在各自的容灾域、安全范围内做到互不影响。在复杂的业务分割诉求下,过度的资源分割不仅会带来资源管理上的复杂度,也会给统一的资源并池以及优化带来障碍。
统一资源管理挑战与收益
这里我们总结了资源统一管理方面的挑战和收益。
挑战:
把不同形态的资源调度应用放在同一个队列、同一个集群中统一管理。比如说常驻服务和批处理任务;
不同应用对底层资源的隔离能力要求不同,如何把强隔离的应用和低资源成本需求的应用放在同一集群、节点中,给单机资源管理以及调度系统带来不小的挑战;
资源统一管理后也给平台性能、安全和价格方面带来了挑战。
收益:
为了解决资源统一管理这个问题,我们提出了三个思路:1)抽象能够提供的资源售卖模型,方便不同的业务线、业务系统准确地表达自身的需求;2)创建一套统一的 Quota 管理平台,这个平台可以让开发者们灵活地管理自身的各类资源;3)资源分层调度系统使得单机集群对字节内部所有计算资源做到快速灵活的交付。
在资源模型方面,我们给应用提供的资源形态以 CPU 维度为例一共分为三级:
分层资源调度
如何有效地把资源诉求准确高效地交付到开发者手上需要一套完整的调度系统来支持。字节内部是通过一套分层的调度系统来实现调度交付的。
目前字节使用的调度器是参照 Kubernetes 框架的分布式调度器。这套调度系统主要的中心式组件有 Dispatcher、并行式的 Scheduler 还有中心式的 Binder。
其中,Dispatcher 主要负责把应用以及集群内部的节点资源分配到具体的 Scheduler 上。Scheduler 在主体结构和 Kubernetes 原生的调度器结构类似,主要处理的就是 predicate 和 priority 的调度计算逻辑。Binder 可以解决不同 Scheduler 视角下调度结果的冲突,并且用 SchedulingUnit 替换了原生的 Pod 语义。这样可以更加方便地处理常驻任务中 per Pod 调度以及批式场景下的 per batch 调度。
当集群整体的资源占用水位很满的状态下,乐观并发调度中很容易出现调度冲突的问题。我们的解决思路是在 Scheduler 的每次响应结果里,针对调度申请给出多个候选节点,然后统一送到 Binder 里去解决冲突,这个设计可以降低 Binder 里解决冲突的失败概率。
过去的混部方案是基于 Kubernetes 和 Yarn 的联合系统管控的方案,并在每一个节点上同时运行 Kubernetes 和 YARN 的管控组件。此外还有一个居中的协调组件负责分配两套系统分别可见的资源量。在联合管控的模式下,单机层面每个节点里 agent 占用资源量级不大,但在整个集群里是一个非常可观的资源量。如果能够实现一套统一的链路, 管理不同形态的资源,对于资源优化的架构以及效果都能得到不错的简化和收益。
在新的统一调度架构下,我们的混合部署架构也做了一系列的调整。保留了平台层 Kubernetes 的 API 以及 Yarn 的 Resource manager 两个入口部署应用的能力。底层的系统上是全部收敛到了基于 Kubernetes 的管控系统上,可以实现大数据系统平稳的底层系统的切换工作。
在新的架构上,不论是在线服务还是离线作业的 Pod 都可以通过一个公共的 Kubernetes API 以及统一调度器去安排资源的调度。这样不仅实现了资源分级模型上管控链路的复用途径,有更大的空间考虑在线、离线业务在同一个集群中运行时资源层应该如何分配及协作。
全局调度
考虑到字节跳动的整体规模,单一的集群能力不足以满足管理字节全球数据中心的需求,并且在应用之间的隔离、多区域的容灾以及算力的标准化问题上字节也有更加细粒度的调度要求。
在应用方向上,我们以应用的优先级作为主维度;在资源池方面,我们以机房作为主维度,这两个方面交叉搭配就形成了一个应用整体粒度上可以全局调度的分配空间。应用和资源的维度是很多的,如果我们选择过多的资源维度,全局的资源会被划分成过多的碎片,不利于管理。所以选取主维度需要考虑对于每一个资源池容量的影响不能低于设定的节点数量。
微服务治理
上图是从生产环境里抓取的子业务线服务的拓扑结构,这个图里每个节点代表一个具体的微服务,而节点之间的边就代表服务之间的依赖关系。
在服务架构治理方面,因为这些服务都是散落在不同的业务团队和系统里,很难通过一个全局的视角去做架构层面的迭代,就会造成一些老的服务没有办法下线。
业务和业务系统之间的依赖关系也是直接在底层服务之间通过远程调用的方式实现。在跨业务线交互的场景里直接暴露细粒度的服务接口会使得服务架构治理的复杂度变得很大,往往需要牵涉多个部门协同工作才能推进服务的架构演进。
所以在微服务的产品层面,只需一套面向应用的解决方案去管理一个子业务线内所有的服务。
在资源开销方面,业务系统通过网络调用的方式实现互联,会有很多的数据资源花费在网络通信加解密上。随着微服务数量越来越多,这方面的资源开销也会变得越来越大。目前字节内部在推广函数类的平台,越来越多的服务会通过更细粒度的函数形式去表达自身的逻辑,微服务侧就会趋向于更加微小的方向。那么在架构治理以及资源开销方面的挑战会变得更加巨大。
资源利用率 vs. 资源有效利用率
同时,作为字节跳动旗下的云服务平台,火山引擎抽象了字节跳动的云原生实践思想,已经对外推出了包含上层解决方案和中层基础产品服务的云原生全系产品。
其中,云原生底座包含核心容器服务和镜像仓库两大产品,它们沉淀了字节跳动数年来建设容器平台的经验,除基本应用托管能力外,还提供高稳定、高性能、自运维等能力。
基于应用生命周期拆解,火山引擎也已推出一些包含持续交付等提升敏捷化和统一交付能力的产品,也有服务网格、应用观测、应用韧性这类可以从流量、监控、演练等方面保障业务平稳运行的产品。
相关阅读
- END -
下载云原生白皮书
基于字节跳动基础架构提供的云原生技术能力和技术实践,火山引擎已经构建了全栈的云原生服务产品矩阵,包括面向算力的云原生服务、面向应用的云原生服务和面向场景的云原生服务三大板块。
欢迎下载 IDC 和火山引擎联合出品的云原生白皮书,获取企业数字化转型新理念!
扫描二维码,下载火山引擎云原生白皮书