job和task的概念是什么

80次阅读
没有评论

共计 5165 个字符,预计需要花费 13 分钟才能阅读完成。

这篇文章主要介绍了 job 和 task 的概念是什么的相关知识,内容详细易懂,操作简单快捷,具有一定借鉴价值,相信大家阅读完这篇 job 和 task 的概念是什么文章都会有所收获,下面我们一起来看看吧。

1. 简介

集群管理系统我们内部叫 Borg,它管理、调度、开始、重启和监控谷歌运行的应用程序的生命周期。本文介绍它是怎么做到这些的。

Borg 提供了三个主要的好处:它(1)隐藏资源管理和故障处理细节,使其用户可以专注于应用开发;(2)高可靠性和高可用性的操作,并支持应用程序做到高可靠高可用;(3)让我们在跨数以万计的机器上有效运行。Borg 不是第一个来解决这些问题的系统,但它是在这个规模,这种程度的弹性和完整性下运行的为数不多的几个系统之一。

本文围绕这些主题来编写,包括了我们在生产环境运行十年的一些功力。

2. 用户视角

Borg 的用户是谷歌开发人员和系统管理员(网站可靠性工程师 SRE),他们运行谷歌应用与服务。用户以 job 的方式提交他们的工作给 Borg,job 由一个或多个 task 组成,每个 task 含有同样的二进制程序。一个 job 在一个 Borg 的 Cell 里面跑,一个 Cell 是包括了多台机器的单元。这一节主要讲用户视角下的 Borg 系统。

2.1 工作负载

Borg Cell 主要运行两种异构的工作负载。第一种是长期的服务,应该“永远”运行下去,并处理短时间的敏感请求(几微秒到几百毫秒)。这种服务是面向终端用户的产品如 Gmail、Google Docs、网页搜索,内部基础设施服务(例如,Bigtable)。第二种是批处理任务,需要几秒到几天来完成,对短期性能波动不敏感。在一个 Cell 上混合运行了这两种负载,取决于他们的主要租户(比如说,有些 Cell 就是专门用来跑密集的批处理任务的)。工作负载也随着时间会产生变化:批处理任务做完就好,终端用户服务的负载是以每天为周期的。Borg 需要把这两种情况都处理好。

Borg 有一个 2011 年 5 月的负载数据[80],已经被广泛的分析了[68,26,27,57,1]。

最近几年,很多应用框架是搭建在 Borg 上的,包括我们内部的 MapReduce[23]、flumejava[18]、Millwheel[3]、Pregel[59]。这中间的大部分都是有一个控制器,可以提交 job。前 2 个框架类似于 YARN 的应用管理器 [76]。我们的分布式存储系统,例如 GFS[34] 和他的后继者 CFS、Bigtable[19]、Megastore[8]都是跑在 Borg 上的。

在这篇文章里面,我们把高优先级的 Borg 的 jobs 定义为生产(prod),剩下的是非生产的(non-prod)。大多长期服务是 prod 的,大部分批处理任务是 non-prod 的。在一个典型的 Cell 里面,prod job 分配了 70% 的 CPU 资源然后实际用了 60%;分配了 55% 的内存资源然后实际用了 85%。在 $5.5 会展示分配和实际值的差是很重要的。

2.2 集群和 Cell

一个 Cell 里面的所有机器都属于单个集群,集群是由高性能的数据中心级别的光纤网络连接起来的。一个集群安装在数据中心的一座楼里面,n 座楼合在一起成为一个 site。一个集群通常包括一个大的 Cell 还有一些小的或测试性质的 Cell。我们尽量避免任何单点故障。

在测试的 Cell 之外,我们中等大小的 Cell 大概包括 10000 台机器;一些 Cell 还要大很多。一个 Cell 中的机器在很多方面都是异构的:大小(CPU,RAM,disk,network)、处理器类型、性能以及外部 IP 地址或 flash 存储。Borg 隔离了这些差异,让用户单纯的选择用哪个 Cell 来跑任务,分配资源、安装程序和其它依赖、监控系统的健康并在故障时重启。

(译者:Cell 其实就是逻辑上的集群)

2.3 job 和 task

一个 Borg 的 job 的属性有:名字、拥有者和有多少个 task。job 可以有一些约束,来指定这个 job 跑在什么架构的处理器、操作系统版本、是否有外部 IP。约束可以是硬的或者软的。一个 job 可以指定在另一个 job 跑完后再开始。一个 job 只在一个 Cell 里面跑。

每个 task 包括了一组 linux 进程,跑在一台机器的一个容器内 [62]。大部分 Borg 的工作负载没有跑在虚拟机(VM) 里面,因为我们不想付出虚拟化的代价。而且,Borg 在设计的时候还没硬件虚拟化什么事儿哪。

task 也有一些属性,包括资源用量,在 job 中的排序。大多 task 的属性和 job 的通用 task 属性是一样的,也可以被覆盖 —— 例如,提供 task 专用的命令行参数,包括 CPU 核、内存、磁盘空间、磁盘访问速度、TCP 端口等等,这些都是可以分别设置并按照一个好的粒度提供。我们不提供固定的资源的单元。Borg 程序都是静态编译的,这样在跑的环境下就没有依赖,这些程序都被打成一个包,包括二进制和数据文件,能被 Borg 安装起来。

用户通过 RPC 来操作 Borg 的 job,大多是从命令行工具,或者从我们的监控系统 ($2.6)。大多 job 描述文件是用一种申明式配置文件 BCL — GCL[12] 的一个变种,会产生一个 protobuf 文件[67]。BCL 有一些自己的关键字。GCL 提供了 lambda 表达式来允许计算,这样就能让应用在环境里面调整自己的配置。上万个 BCL 配置文件超过一千行长,系统中累计跑了了千万行 BCL。Borg 的 job 配置很类似于 Aurora 配置文件[6]。

图 2 展现了 job 的和 task 的状态机和生命周期。

用户可以在运行时改变一个 job 中的 task 的属性,通过推送一个新的 job 配置给 Borg。这个新的配置命令 Borg 更新 task 的规格。这就像是跑一个轻量级的,非原子性的事务,而且可以在提交后轻易再改回来。更新是滚动式的,在更新中可以限制 task 重启的数量,如果有太多 task 停掉,操作可以终止。

一些 task 更新,例如更新二进制程序,需要 task 重启;另外一些例如修改资源需求和限制会导致这个机器不适合跑现有的 task,需要停止 task 再重新调度到别的机器上;还有一些例如修改优先级是可以不用重启或者移动 task 的。

task 需要能够接受 Unix 的 SIGTERM 信号,在他们被强制发送 SIGKILL 之前,这样就有时间去做清理、保存状态、结束现有请求执行、拒绝新请求。实际的 notice 的 delay bound。实践中,80% 的 task 能正常处理终止信号。

2.4 Allocs

Borg 的 alloc(allocation 的缩写)是在单台机器上的一组保留的资源配额,用来让一个或更多的 task 跑;这些资源一直分配在那边,无论有没有被用。allocs 可以被分配出来给未来的 task,用来保持资源在停止一个 task 和重启这个 task 之间,用来聚集不同 jobs 的 tasks 到同一台机器上——例如一个 web server 实例和附加的,用于把 serverURL 日志发送到一个分布式文件系统的日志搜集实例。一个 alloc 的资源管理方式和一台机器上的资源管理方式是类似的;多个 tasks 在一个 alloc 上跑并共享资源。如果一个 alloc 必须被重新定位到其他的机器上,那么它的 task 也要跟着重新调度。

一个 alloc set 就像一个 job:它是一组 allocs 保留了多台机器上的资源。一旦 alloc set 被创建,一个或多个 jobs 就可以被提交进去跑。简而言之,我们会用 task 来表示一个 alloc 或者一个 top-level task(一个 alloc 之外的),用 job 来表示一个 job 或者 alloc set。

2.5 优先级、配额和管理控制

当有超量的工作负载在运行的时候会发生什么事情?我们的解决方案是优先级和配额。

所有 job 都有优先级,一个小的正整数。高优先级的 task 可以优先获取资源,即使后面被杀掉。Borg 定义了不重叠的优先级段给不同任务用,包括(优先级降序):监控、生产、批任务、高性能(测试或免费)。在这篇文章里面,prod 的 jobs 是在监控和生产段。

虽然一个降级的 task 总会在 cell 的其他地方找到一席之地。降级瀑布也有可能会发生,就是一个 task 降下来之后,把下面运行的 task 再挤到别的机器上,如此往复。为了避免这种情况,我们禁止了 prod 级 task 互相排挤。合理粒度的优先级在其他场景下也很有用——MapReduce 的 master 跑的优先级比 worker 高一点,来保证他们的可用性。

优先级是 jobs 的相对重要性,决定了 jobs 在一个 cell 里面是跑还是等 (pending)。配额则是用来决定 jobs 是否运行被调度。配额就是一组资源(CPU, RAM, disk) 的数量在一个指定的优先级、一个指定的时间段(月这个量级)。数量决定了这个用户的 job 可以用的最多资源(例子:20TB 内存和 prod 优先级从现在到 7 月在 xx cell 内)。配额检查是管理控制的一部分,不是调度层的:配额不足的任务在提交的时候就会被拒绝。

高优先级的配额总是花费的比低优先级要多。prod 级的配额是被限制为一个 cell 里面实际的资源量,所以用户提交了 prod 级的 job 的配额时,可以期待这个 job 一定会跑,去掉一些碎片外。即使这样,我们鼓励用户多买一点比自己需要多一点的配额,很多用户超买是因为他们的应用程序的用户数量增长后需要的配额就大了。对于超买,我们的应对方案是低优先级资源的超售:所有用户在 0 优先级都可以用无限的配额,虽然在实际运行中这种情况很难跑起来。一个低优先级的 job 在资源不足时会保持等 (pending) 状态。

配额分配在 Borg 系统之外,和我们的物理资源计划有关。这些资源计划在不同的数据中心产生不同的价格和配额。用户 jobs 只在有足够配额和足够优先级之后才能启动。配额的使用让 Dominant Resource Fairness(DRF)[29, 35, 36, 66]不是那么必要了。

Borg 有一个容量系统给一些特殊权限给某些用户,例如,允许管理员删除或修改 cell 里面的 job,或者允许用户区访问特定的内核特性或者让 Borg 对自己的 job 不做资源估算($5.5)。

2.6 命名和监控

光是创建和部署 task 是不够的:一个服务的客户端和其他系统需要能找到它们,即使它换了个地方。为了搞定这一点,Borg 创造了一个稳定的“Borg name Service”(BNS)名字给每个 task,这个名字包括了 cell 名字,job 名字,和 task 编号。Borg 把 task 的主机名和端口写入到一个持久化高可用文件里,以 BNS 名为文件名,放在 Chubby[14]上。这个文件被我们的 RPC 系统使用,用来发现 task 的终端地址。BNS 名称也是 task 的 DNS 名的基础构成部分,所以,cc cell 的 ubar 用户的 jfoo job 的第 50 个 task 的 DNS 名称会是 50.jfoo.ubar.cc.borg.google.com。Borg 同时还会把 job 的大小和 task 的健康信息写入到 Chubby 在任何情况改变时,这样负载均衡就能知道怎么去路由请求了。

几乎所有的 Borg 的 task 都会包含一个内置的 HTTP 服务,用来发布健康信息和几千个性能指标 (例如 RPC 延时)。Borg 监控这些健康检查 URL,把其中响应超时的和 error 的 task 重启。其他数据也被监控工具追踪并在 Dashboards 上展示,当服务级别对象(SLO) 出问题时就会报警。

用户可以使用一个名叫 Sigma 的 web UI,用来检查他们所有的 job 状态,一个特殊的 cell,或者深入到某个 job 的某个 task 的资源用率,详细日志,操作历史,和最终命运。我们的应用产生大量的日志,都会被自动的滚动来避免塞满硬盘,会在一个 task 结束后保留一小段时间用来 debug。如果一个 job 没有被跑起来,Borg 会提供一个为什么挂起的解释,指导用户怎么修改这个 job 的资源需求来符合目前这个 cell 的情况。我们发布资源的使用方针,按照这个方针来做就容易被调度起来。

Borg 记录所有的 job 提交和 task 时间,以及每 task 的资源使用细节在基础存储服务里面。这个存储服务有一个分布式的只读的 SQL-like 的交互式接口,通过 Dremel[61]提供出来。这些数据在实时使用、debug、系统查错和长期容量规划上都很有用。这些数据也是 Google 集群负载追踪的数据来源之一[80].

所有这些特性帮助用户理解和 debug Borg 的行为和管理他们的 job,并且帮助我们的 SRE 每个人管理超过上万台机器。

关于“job 和 task 的概念是什么”这篇文章的内容就介绍到这里,感谢各位的阅读!相信大家对“job 和 task 的概念是什么”知识都有一定的了解,大家如果还想学习更多知识,欢迎关注丸趣 TV 行业资讯频道。

正文完
 
丸趣
版权声明:本站原创文章,由 丸趣 2023-08-04发表,共计5165字。
转载说明:除特殊说明外本站除技术相关以外文章皆由网络搜集发布,转载请注明出处。
评论(没有评论)