本文发表于一年多前。旧文章可能包含过时内容。请检查页面中的信息自发布以来是否已变得不正确。
Kubernetes 遇见高性能计算
任何使用过 Docker 的人都深知容器所带来的巨大效率提升。虽然 Kubernetes 在容器编排方面表现出色,但高性能计算 (HPC) 应用在 Kubernetes 上部署可能会很棘手。
在这篇文章中,我将讨论使用 Kubernetes 运行 HPC 工作负载的一些挑战,解释当前组织如何应对这些挑战,并提出一种在共享 Kubernetes 集群上支持混合工作负载的方法。我们还将提供关于客户 IHME 的案例研究信息和链接,展示 Kubernetes 如何无缝扩展以服务其 HPC 工作负载,同时保持 HPC 用户熟悉的扩展性和界面。
HPC 工作负载的独特挑战
在 Kubernetes 中,调度的基本单元是 Pod:一个或多个调度到集群主机的 Docker 容器。Kubernetes 假定工作负载是容器。虽然 Kubernetes 有 Cron Job 和 Job 运行至完成的概念,但部署在 Kubernetes 上的应用程序通常是长时间运行的服务,例如 Web 服务器、负载均衡器或数据存储。虽然它们具有高度动态性,Pod 进出频繁,但它们与 HPC 应用程序模式大相径庭。
传统的 HPC 应用程序通常表现出不同的特征
- 在金融或工程模拟中,一个作业可能包含数万个短时运行任务,需要低延迟和高吞吐量的调度,才能在可接受的时间内完成模拟。
- 计算流体动力学 (CFD) 问题可能在数百甚至数千个节点上并行执行,使用消息传递库来同步状态。这需要专门的调度和作业管理功能来分配和启动此类作业,然后对其进行检查点、暂停/恢复或回填。
- 其他 HPC 工作负载可能需要专用资源,如 GPU,或者需要访问有限的软件许可证。组织可能会强制执行关于谁可以使用何种类型的资源的策略,以确保项目获得足够的资源并按时完成。
HPC 工作负载调度器已经发展到能够精确支持这些类型的工作负载。示例包括 Univa Grid Engine、IBM Spectrum LSF 和 Altair 的 PBS Professional。管理 HPC 工作负载的站点已经开始依赖诸如数组作业、可配置抢占、基于用户、组或项目的配额以及各种其他功能。
容器与 HPC 之间的界限模糊
HPC 用户认为容器的价值与为其他组织带来价值的原因相同。将逻辑打包到容器中,使其具有可移植性,与环境依赖项隔离,并易于与其他容器交换,这显然具有价值。然而,转向容器可能很困难。
HPC 工作负载通常在命令行级别集成。作业不是通过编码,而是通过命令行作为二进制文件或充当包装器的简单 shell 脚本提交到队列。HPC 站点使用的工程、科学和分析应用程序有数百个,它们都采用这种方法,并与流行的工作负载调度器进行了成熟且经过认证的集成。
虽然将工作负载打包到 Docker 容器中,发布到注册表,并提交工作负载的 YAML 描述对 Kubernetes 用户来说是第二天性,但这对于大多数 HPC 用户来说是陌生的。运行 R、MATLAB 或 Stata 模型的分析师只想尽快提交模拟,监控其执行,并尽快获得结果。
现有方法
为了应对迁移到容器的挑战,运行容器和 HPC 工作负载的组织有几个选择
- 维护独立的 инфраструктура
对于在 HPC 上有沉没投资的站点,这可能是一种首选方法。与其扰乱现有环境,不如在单独的集群上部署新的容器化应用程序,让 HPC 环境保持不变。挑战在于,这会带来集群孤立的代价,增加基础设施和管理成本。
- 在现有 HPC 工作负载管理器下运行容器化工作负载
对于运行传统 HPC 工作负载的站点,另一种方法是使用现有的作业提交机制来启动作业,这些作业反过来在一个或多个目标主机上实例化 Docker 容器。采用这种方法的站点可以在对环境的干扰最小的情况下引入容器化工作负载。领先的 HPC 工作负载管理器,如 Univa Grid Engine Container Edition 和 IBM Spectrum LSF 正在增加对 Docker 容器的原生支持。Shifter 和 Singularity 也是支持这种部署的重要开源工具。虽然这对于有简单需求并希望坚持使用其 HPC 调度器的站点来说是一个很好的解决方案,但他们将无法访问原生 Kubernetes 功能,这可能会限制管理 Kubernetes 擅长的长时间运行服务的灵活性。
- 使用 Kubernetes 中的原生作业调度功能
对现有 HPC 应用程序投入较少的站点可以使用 Kubernetes 中现有的调度设施来处理 运行至完成的作业。虽然这是一个选项,但对于许多 HPC 用户来说可能不切实际。HPC 应用程序通常要么针对大规模吞吐量进行优化,要么针对大规模并行性进行优化。在这两种情况下,启动和关闭延迟都会产生显著影响。对于当前的容器化微服务来说可以接受的延迟,将使此类应用程序无法扩展到所需的级别。
所有这些解决方案都涉及权衡。第一个选项不允许共享资源(增加成本),而第二个和第三个选项要求客户选择单个调度器,从而限制了未来的灵活性。
Kubernetes 上的混合工作负载
更好的方法是在同一个共享环境中原生支持 HPC 和容器工作负载。理想情况下,用户应该看到适合其工作负载或工作流类型的环境。
支持混合工作负载的一种方法是允许 Kubernetes 和 HPC 工作负载管理器在同一集群上共存,通过限制资源以避免冲突。虽然简单,但这意味着两个工作负载管理器都无法充分利用集群。
另一种方法是使用与 Kubernetes 调度器协调的对等调度器。Univa 的 Navops Command 就是采用这种第三种方法的解决方案,它增强了 Kubernetes 调度器的功能。Navops Command 提供自己的 Web 界面和 CLI,并允许在 Kubernetes 上启用额外的调度策略,而不会影响 Kubernetes 调度器和现有容器化应用程序的操作。Navops Command 通过 Pod 规范中的“schedulerName”属性作为对等调度器插入 Kubernetes 架构,工作负载可以选择使用它而不是 Kubernetes 原生调度器,如下图所示。
通过这种方法,Kubernetes 充当资源管理器,将资源提供给独立的 HPC 调度器。集群管理员可以使用可视化界面根据策略分配资源,或者通过 Web UI 简单地拖动滑块,将 Kubernetes 环境的不同比例分配给非容器 (HPC) 工作负载以及原生 Kubernetes 应用程序和服务。
从客户端的角度来看,HPC 调度器作为部署在 Kubernetes Pods 中的服务运行,其操作方式与在裸机集群上完全相同。Navops Command 提供额外的调度功能,包括资源预留、运行时配额、工作负载抢占等。这种环境同样适用于本地部署、基于云的部署或混合部署。
在 IHME 部署混合工作负载
在混合工作负载方面取得成功的一个客户是健康计量与评估研究所 (IHME),它是华盛顿大学的一个独立健康研究中心。为支持其全球公认的全球健康数据交换 (GHDx),IHME 运营着一个规模庞大的环境,由 500 个节点和 20,000 个核心组成,在 Kubernetes 上运行混合的分析、HPC 和基于容器的应用程序。此案例研究描述了 IHME 如何使用 Navops Command 在共享 Kubernetes 集群上成功托管现有 HPC 工作负载。
对于部署新集群、希望访问 Kubernetes 丰富功能但又需要灵活性来运行非容器化工作负载的站点,这种方法值得一试。它为站点提供了在 Kubernetes 和 HPC 工作负载之间共享基础设施的机会,而不会扰乱现有应用程序和业务流程。它还允许他们按照自己的节奏将 HPC 工作负载迁移到使用 Docker 容器。