BACK TO ARCHIVE
pipeline framework rez apptainer containers linux devops vfx-reference-platform

平衡稳定性与创新:混合运行时环境

08.01.2025 ADUCG RESEARCH

摘要

我们提出了一种用于管理 Netflix Animation Studios (NAS) 软件运行时环境的混合方法,旨在解决 VFX 与动画行业中一个常见挑战:如何在保持稳定性的同时快速采用创新技术。我们将容器化技术 Apptainer 与动态软件环境管理工具 Rez 相结合,从而能够在单一主机上并发运行多个彼此不同的 VFX Reference Platform 软件栈。该方法显著简化了 Linux 发行版之间的过渡,并加快了新软件的采用速度,使工作室能够在不牺牲稳定性或性能的前提下,高效管理多样化的制作需求。

在 CentOS-7.8 与 Rocky-9.2 容器内运行多个 VFX Reference Platform 运行时环境的单一主机

1 引言

本文探讨了 NAS 如何通过混合容器化运行时环境,更高效地管理其软件环境。从整体层面看,在 NAS,我们始终希望在基于 Linux 的制作流水线中加快新软件的采用,同时确保稳定性,并尽量减少对正在进行中的制作所造成的干扰;而这些制作可能各自需要不同的 VFX Reference Platform 软件栈。我们的 North Star 是:在每年第一季度结束前,将最新的 VFX Reference Platform 栈集成到任意制作流水线中。多年来,我们一直在朝这一目标推进(参见 2021 年展示的可复现构建与运行时环境工作)。本次扩展的范围,是在运行时使用 Hybrid Containerized Environments,以及它如何促进加快新软件采用这一总体目标,特别是在 Linux OS 发行版迁移(即 CentOS-7 到 Rocky-9)中的作用。归根结底,借助这一混合方案,我们能够在基于容器的环境中保持可配置性,并使其适用于多种场景下的虚拟化,包括在新硬件上快速测试新配置。

我们将分享我们的看法:为什么从软件管理角度来看,并行管理多个制作并不是一个容易解决的问题;以及为什么我们提出的方法,是迄今为止我们为更接近 North Star 所找到的最佳方案。我们希望,各工作室,尤其是已经在使用 Rez 的团队,能够从我们分享的挑战与见解中有所收获,并受到启发,在自身设施中实施这一策略,以加快新软件的采用。

2 动机

2.1 稳定性与创新之间的张力

DCC 应用程序运行时需要一个软件运行时环境。这些环境由宿主 OS 以及该特定 OS 版本提供的底层库组成。它们还包括用于配置和定制的内部软件,例如库和额外插件,用于扩展 DCC 应用程序的功能、将其连接到资产管理系统,并与渲染农场集成,以创建最终数字影像所需的资产。

在单个制作中,多个部门使用不同环境并搭配不同版本的 DCC 和内部软件,并不少见。这些环境远非静态;在制作初期,它们几乎每天都会更新,而到制作接近尾声时往往会趋于稳定。锁定 DCC 和主要软件组件的版本,并在后期只接受关键软件包,是一种常见做法。而在同一时间段内启动的新制作,则很可能更倾向于使用现有的最新、最好的 DCC 与内部软件版本。

此外,与此同时,宿主 OS 的底层库也不可避免地需要因外部制作原因而同步更新。这些原因可能包括应用最新的安全更新、满足新版 DCC 与开发工具的前置条件,或为非数字内容创建工具引入新特性。

当一家 VFX 或动画工作室需要并行处理不止少数几个制作项目时,管理大量环境所带来的复杂性与工作量会迅速上升。在这种情况下,可以清楚地看到,工作室面临的一个共同挑战就是稳定性与创新之间的张力。

这里所说的稳定性,是指随着项目推进到后期阶段,制作方希望锁定任何变更,以尽量降低延期风险。比如,OS 升级、VFX 平台更新,甚至仅仅是一次次版本 Python 升级,都可能被视为不可接受,必须等到该制作结束后再进行。为了安全性或更好的 OS 用户体验而需要的底层库补丁,虽然更容易被接受,但同样也会冲击稳定性。

让制作能够快速采用新工具、DCC 应用程序和 OS 版本,可以使 System Engineering、Research and Development 以及 Production Technology 等部门推动创新。这种创新体现为更优的工作流、新的流水线以及更高效的工具,最终让数字艺术家能够以更轻松、更高效的方式开展工作,并在艺术领域实现创新。

2.2 关键因素

应对这一挑战的关键驱动因素,是一家并行管理多个制作的工作室必须维护的运行时环境数量。在 NAS,跨五个并行制作,仅统计四个主要 DCC 应用(Maya/Houdini/RV/Nuke)的环境,在 90 天内就创建了超过 1400 个唯一运行时环境,也就是平均每天产生 15 个新的制作环境。

在运行时将容器技术引入到活跃制作中(涉及 Apptainer/Artifactory/Rez 的改动)是具有挑战性的,因为它此前未经验证,且即时收益并不明确。尽管过去这些年曾有过失败尝试,但考虑到以下两个关键因素,这项举措最终变得势在必行:

采用 VFX Reference Platform 2023 的 DCC。 制作希望使用的新 DCC 版本,即 Maya-2024、Nuke-15、Houdini-20.5,都是基于 CY2023 Reference Platform 构建的,也就是 gcc-11.2.1、glibc-2.28、python-3.10 等。这些 DCC 应用程序在我们当前的 CentOS-7.8 主机上无法运行。

重新编译耗时。 在 NAS,升级 OS 版本意味着要重新编译 200 多个彼此相关的 C++ rez 包,而且往往还需要修改代码。由于这些包相互依赖、且由不同团队分散负责,这类升级通常需要数月时间进行协同推进。就当前这个案例而言,从 CY2021 Reference Platform 升级到 CY2023 Reference Platform 时,也伴随着 Python 升级,共有 900 个 rez 包需要更新;在此更新完成之前,我们必须等待超过 6 个月,艺术家机器才能开始重新镜像为 Rocky-9。

我们还识别出另外两个带来改进机会的重要方面:

CentOS-7 生命周期终止。 随着 CentOS-7 即将 end of life,出于安全方面的担忧,System Engineering 加快了向 Rocky-9 的迁移进程,并主张尽快弃用 CentOS。

硬件资源影响。 在从 CentOS-7 过渡到 Rocky-9 的阶段,开发与测试团队需要一台主机继续支持基于旧 OS CentOS-7.8 的现有制作,同时还需要另一台主机为 Rocky-9.2 环境重新编译并测试所有 rez 包。这实际上意味着,在过渡期内,R&D 与 Production Technology 团队所需的工作站数量会翻倍。

3 设计与实现

3.1 基础设计

我们的混合方法设计由一个稳定的 OS 基础容器镜像和一层动态的 rez 包组成。图 2 展示了构建一个运行时环境所涉及的不同软件组件。

我们选定的容器技术是 Apptainer。若要了解我们的选择原因,可查看其与 Docker 的对比表。

混合设计模型

3.2 Rez 修改

实现这种混合方法需要对 rez 做定制。我们采用了一种透明的实现方式,使 NAS 的所有用户都能无缝采用,而无需学习新命令。

3 展示了 apptainer 模块的一个简化实现。

简而言之,我们会拦截 rez 命令,并调用新 apptainer 模块中的一个函数。该函数会检查 rez 解析出的包中是否存在名为 vfx_cxx 的包。根据其版本不同,它会从 Artifactory 获取不同的容器镜像,然后应用 resolve 上下文,以创建应用程序的构建、测试或执行环境。

  • 如果是 vfx_cxx-2019,则获取一个 CentOS-7.4 容器镜像
  • 如果是 vfx_cxx-2021,则获取一个 CentOS-7.8 容器镜像
  • 如果是 vfx_cxx-2023,则获取一个 Rocky-9.2 容器镜像

Rez apptainer 模块实现

一旦容器镜像已在本地缓存,引导过程只需约 0.3 秒即可启动容器。如果 apptainer 镜像发生更新,则会下载新镜像;在这种情况下,对于一个 700MB 到 1GB 的容器镜像,引导过程需要 3 到 4 秒。

3.3 Launcher 实现

4 展示了 NAS Launcher,这是一个图形用户界面,它将 presets(可启动的运行时环境)组织到 toolsets 中。艺术家通过它来启动 Maya、Houdini、Nuke 等 DCC,以及任意特定制作所需的 rez 包和设置。此外,它还可用作配置这些环境的工具。

在 NAS Launcher 中于 preset 级别设置是否使用容器

对于 Launcher 内部的实现,我们选择了复用前文提到的 rez 实现,并仅增加最少的逻辑,通过单个设置项 LAUNCH_CONTAINER=true 来启用或禁用容器化。launcher presets 具有可组合、分层的特性,这使我们可以在单个 preset 级别、制作级别,或整个 facility 级别添加这一设置。我们还增加了若干额外设置,允许为实验目的覆盖版本或容器镜像位置,同时也便于使用开发者镜像。

4 结果

4.1 初始测试与制作采用

在初始验证阶段,我们使用 Nvidia Cuda 的 nbody 工具,测量裸机运行与在将用于生产的容器内运行之间的差异。在这些合成测试未显示出性能差异后(见附录 A 中的表 1),我们进入真实场景测试,以验证该方法不会影响正在进行中的制作。

Production Technology 使用一种端到端制作测试流程来验证 VFX Platform reference 更新;在这个流程中,各工种组会在各自领域内进行测试,首先确保流水线功能、资产创建、渲染与交付都能正常工作。初始测试聚焦于使用现有资产进行向后兼容性验证,第二轮则通过创建新资产来测试。

初始测试是在 CentOS 7.8 主机中的 CentOS 7.8 容器里运行这些测试。我们使用 launcher 设置覆盖项 LAUNCH_CONTAINER=false 来隔离容器相关问题。测试中发现并解决了许多问题。然而,艺术家在交互式工作流中没有感受到任何性能下降。随后,Rocky-9 主机开始铺开,端到端制作测试也在 Rocky-9 主机上再次执行。期间发现了一些性能问题,但它们与宿主 OS 有关,而不是容器本身。完成端到端测试阶段并修复阻断问题,耗时超过一个月。到 2025 年初,我们已经能够在所有当前制作的全部交互式工作流中启用运行时容器化。随后在第二季度中期,我们在使用 CentOS-7.8 主机的渲染农场中启用了容器化,并将部分工作流发送到 Rocky-9.4 渲染农场主机。截至 2025 年 5 月,渲染农场机器上的 Rocky-9 推广仍在进行中。我们预计将在 2025 年第三季度后期把 CentOS 从流水线中淘汰。

5 展示了生产环境中容器化工作流采用情况的演进,并强调了各阶段达成的关键里程碑。

生产中容器化工作流的采用情况

4.2 Rocky-9 迁移

作为背景说明,从 CentOS 7.4 迁移到 7.8,在双主机模式下耗时超过一年。R&D 和 Production Technology 成员各自拥有一台用于重新编译包的 CentOS 7.8 主机,以及一台用于支持现有制作的 CentOS 7.4 主机。直到所有 rez 包都发布完成后,向 CentOS 7.8 的迁移才真正发生。相比之下,借助这一新方法,我们可以立刻让所有技术部门和艺术家迁移到新发行版 Rocky-9,同时只需在 Launcher 中通过一次覆盖设置 LAUNCH_CONTAINER=true,就能将当前制作锁定在前一代平台下的 CentOS-7.8 容器中。这使我们能够在 Rocky-9 主机上、于 CentOS-7.8 容器内运行 CY2021 reference platform 与旧版 DCC(Maya-2023、Houdini-19.5、Nuke-14 等)。

4.3 更新 VFX Platform reference 2023

R&D 与 ProdTech 开发者得以仅使用一台 Rocky-9 主机,同时支持旧流水线,并开始为 CY2023 reference platform 更新重新编译和更新所需的 900 个 rez 包,从而验证了我们简化跨平台编译这一目标。整个过程持续了超过 6 个月,是迄今为止我们耗时最长的一次 VFX Platform reference 更新。与以往更新相比,唯一的优势在于,用户不必每天在不同主机之间来回切换。

5 挑战与问题

回头来看,实现这些目标是值得的,NAS 现在也正在收获此前投入所带来的回报。不过,项目过程中确实遇到了一些值得分享的挑战与问题。

5.1 说服制作团队

与 VFX 和动画行业中许多新颖且具有颠覆性的项目一样,最大的挑战有时并非技术本身,而是需要一定程度的推动与游说,以获得正在进行中的制作团队支持。自 2021 年末起,容器内运行就已经处于“准备好测试”的状态。从那时到 2024 年中,没有任何制作愿意承担使用这些新技术的风险,因为这是一种重大的范式转变,并引入了新的组件。阻力之所以更明显,还因为其主要收益并不面向当前正在推进的制作,而是面向未来制作。

  • 在一个完全成功的场景中,本项目完成后并不会带来任何性能提升。
  • 活跃中的制作已经承诺使用它们现有的 VFX Reference Platform,因此更快迁移到更新版本的 VFX Reference Platform 对它们而言并不重要。
  • 若要完整测试这一方法,需要制作团队投入时间和精力进行端到端制作测试。

采用速度缓慢的另一个原因,是变更的来源不同。不同于典型 VFX 工作室中由上而下、由制作驱动 R&D 的方式,这项举措是一次自下而上的实施,源于 R&D/facility 层面识别出的需求。

只有在评估整个工作室总体方向时,这一方法的收益才会真正显现,因为它增强了并行管理多个制作的能力,并促进了 VFX Reference Platform 软件栈的更快采用。

5.2 时间限制与测试范围变化

和任何项目一样,时间限制始终存在,但在这个项目中尤其明显,因为能够引入这些新技术组件的窗口期非常短。由于负责近 500 台主机从 CentOS-7 迁移到 Rocky-9 的 System Engineering 团队被重新调配去支持另一个重大项目,端到端测试日期被提前了数月。如果没能抓住这段很小的机会窗口,迁移就会被显著推迟。

最初的测试范围只包括在一个测试制作中评估交互式 Maya 工作流。一旦建立起信心并确认用户体验良好,容器化才会扩展到其他 DCC 应用程序。只有当该测试制作成功在容器中运行全部交互式工作流后,改动才会推广到其他制作。

由于工作流之间相互关联且复杂,再加上制作测试人员的可用性,以及前述狭窄的时间窗口,最终决定是:对所有交互式与无头运行时环境一并启用容器化。这导致了第一次错误启动,出现了若干被认定为阻断性的问题,同时也涌现出大量明确与容器内运行应用有关的问题。这给我们的团队带来了额外负担。

5.3 错误启动:特权提升问题

最初的策略,是先在渲染农场环境中启用容器化,然后再推广到交互式工作流。这种分阶段方法基于这样一种理解:无头工作流由于没有 UI,通常更容易容器化;但由于对某些工作流如何彼此纠缠缺乏充分认识,项目被迫暂停,因为其中一个最重要的工作流——将资产“Check-in”到我们的资产管理系统——失败了。

这一测试阶段中的关键问题是,有些工作流会使用特权提升(sudo)。

虽然在容器工作流中运行 sudo 是可能的,但这既不安全,也不是推荐做法。

在最初几天启用容器化时,这次错误启动在制作团队信任层面代价相当高。尽管一开始遭遇挫折,我们仍决定只专注于交互式测试,而这被证明是一个转折点。通过证明 DCC 应用程序可以在容器内运行且没有性能下降,我们重新建立了对项目的信心。这一成功不仅验证了我们的策略调整,也为未来的容器化工作奠定了坚实基础,最终改善了我们的工作流,并加强了跨团队协作。

5.4 Artifactory 问题

三年多来,Artifactory 一直在稳定提供我们用于构建每一个工具的 apptainer 镜像,因此我们原本相信它能够有效扩展。然而,在端到端制作测试的中途发生了一次重大挫折:一个新容器镜像被部署,其中包含修复若干小问题所需的改动。本地容器镜像缓存因此失效,导致工作室内全部 600 台机器同时从 Artifactory 拉取新的 700MB 镜像。尽管 Artifactory 理应能承受这一负载,但当时的部署无法完成扩展,结果出现了请求被拒绝或容器镜像只下载部分内容的情况。

底层问题有两个:

  • 请求来自我们位于 Sydney, Australia 和 Vancouver, Canada 的工作室,而当时我们只有一个单区域的 Artifactory 实例部署。
  • Artifactory 实例资源不足。

这些问题很快得到了解决:我们在每个地点都增加了具有适当规格的 Artifactory 实例,并修复了一些配置问题。

需要指出的是,在过去,Artifactory 宕机只会影响开发者;但现在,由于在运行时使用容器,我们引入了一个会影响所有活跃制作的单点故障。为应对潜在故障,我们在 Rez 中实现了一个回退机制。它会检测从 Artifactory 获取镜像时的任何失败,并将拉取请求重定向到指定的网络位置。为此,我们还必须在部署时建立一个 CI 流水线,用于同步所有容器镜像版本、flavor 和类型。这增加了复杂性,但最终带来了安心感。

5.5 容器版本管理

新的容器镜像和任何软件一样,都有引入意外行为的风险。容器镜像应当进行版本管理,以追踪因包更新、配置、安全补丁和依赖变化所带来的更改。

NAS Launcher 使用 beta、pre-release 和 production 三个 presets levels 来控制软件发布。beta 持续接收更新,然后这些更新会按周自动推进到 pre-release 和 production。

最初,我们决定只维护三种镜像类型:使用 beta、stable 和 latest 标签进行版本控制。正如预期的那样,production presets 使用 stable 容器,但事实证明这是一种错误做法;因为当 beta 或 latest 容器被提升为 stable 时,三个 Launcher level 都会立即受到影响,我们也因此失去了这些 level 所提供的控制层。

为了解决这个问题,我们在 beta preset level 中引入了 semantic versioning(即 CONTAINER_VERSION=2.1.3)作为 launcher 设置,从而确保 beta preset 中的版本变更不会影响 pre-release 和 production presets。

7 未来工作

继续发展这种方法还可能带来更多收益。例如,将更多变化频率较低的组件从 rez 移入容器,只让变化节奏更快的部分(内部 rez 包)继续由 rez 动态管理。也就是说,为特定版本的 DCC 构建专用镜像,把该版本 DCC 所需的第三方库以及 DCC 本身放入镜像中。这可能带来以下收益:

  • 提升启动与运行时性能,因为更多软件会被本地缓存,而不是从网络上的 rez 中央仓库拉取,同时类似 PATH 的变量长度也会缩短。
  • 减少 rez 包数量,缩短 resolve 时间,并降低冲突,因为动态包数量会更少。

类似于 SPK 现在已原生支持定义并针对 VFX Reference Platforms 进行构建,我们还应研究两种专用容器配置方法,以达成类似结果。

  • OS-base + DCC APP-version + VFX Platform-CYX(例如 2021 版本包含 Qt-5.15、OpenEXR-2.4、boost-1.73、python-3.7)
  • OS-base + DCC APP-Version(带其偏好的库 Qt、OpenEXR、opnessl、Python 等)

要实现这一点,需要先实现 rez-provides feature proposal。

作为后续步骤,我们将寻求把我们在 rez 中的混合实现回馈给社区,因为这将帮助其他工作室。此外,继续推动这一方法的采用并争取社区协作,也有望让 NAS 受益,例如加速开发更多支持我们 road map 的附加特性。

8 结论

如结果所示,我们验证了最初的假设:对运行时工作流进行容器化,将使向新 Linux 发行版的迁移更快且更无缝,同时不会干扰正在进行中的制作。

虽然实现这种混合容器运行时环境给流水线引入了额外复杂性,但长期收益证明这些投入是值得的。除了简化 Linux 发行版之间的过渡外,容器化环境还提供了以下战略优势:

  • 构建环境与运行时环境保持一致,对于问题复现至关重要。
  • 能让不同制作在不同 OS 版本下运行。运行时 OS 环境只需通过一个指向 Artifactory 中 Apptainer 镜像的环境变量即可控制,而无需重新镜像机器。
  • R&D 与 System Engineering 团队之间实现相互独立:
    • R&D 无需与 System Engineering 交互,就可以修改 Apptainer 镜像中的开发与运行时基础库。
    • System Engineering 团队可以更新宿主库,而不会影响开发与运行时环境。这包括面向非生产工作流的安全补丁与基础库更新。

总而言之,可复现性、灵活性与便利性这些收益,有助于实现所期望的制作稳定性,同时不会限制快速迭代以交付创新的能力。

我们希望,本文中遇到的挑战与总结出的经验,能够提供有价值的洞见,并帮助未来采用这一方法的工作室更顺利地完成实施。

Acknowledgments

感谢 Toolchain 团队成员 Viven Iyer 和 Nathan Cheung(Software Engineers)的合作,他们在整个项目中提供了想法、参与了实现,并持续支持这一解决方案。

感谢 Genevieve Dufault(Project Manager)和 Oliver Dunn(ProdTech Pipeline Technical Director Supervisor)创建并协调端到端用户测试流程;如果没有这项工作,本项目绝不可能达到生产状态。同时,也感谢所有在该项目各个测试阶段做出贡献的艺术家。

最后但同样重要的是,感谢 NAS System Engineering 和 Digital Resources 团队,他们为我们的工作提供了基础支撑,并且是本项目成功的关键。

A Synthetic Tests

我们使用 nbody 来测量裸机运行与在不同、将用于生产的容器场景中运行之间的性能差异。

测试 1 - GPU - 500224 bodies

nbody -benchmark -numbodies=500224

测试 2 - GPU - 49152 bodies

nbody –benchmark -fullscreen  -fp64

测试 3 - CPU - 4096 bodies

nbody  -benchmark -numbodies=4096 -cpu

1 展示了每项测试在 10 次迭代后的累计时间。

TestCentOS-7.8 Bare metalCentOS-7.8 Apptainer on CentOS-7.8 hostCentOS-7.8 Apptainer on Rocky-9 host
16862.420 ms6795.698 ms6737.508 ms
22703.245 ms2715.286 ms2639.070 ms
3959.298 ms970.614 ms887.471 ms

合成性能对比

本文采用 Creative Commons BY-NC-ND 4.0 协议进行授权。

BY-NC-ND: 署名-非商业性使用-禁止演绎

End of Article