Devpod 远程开发实践:如何提升开发者生产力
在大规模软件工程体系中单体仓库、复杂构建流程和本地开发环境维护往往会成为影响开发者生产力的重要因素。某海外大型科技公司通过Devpod 远程开发环境将代码、工具链和构建资源迁移到云端在提升构建速度、降低环境配置成本和增强安全性方面取得了明显成效。早期痛点2017 年的代码库状况2017 年某海外大型科技公司的代码体系高度分散代码分布在数千个仓库中覆盖 10 多种编程语言、4000 多个服务、500 多个 Web 应用同时还使用着 9 种以上构建工具和 6 种以上配置工具。几乎每个微服务和应用都有自己独立的代码仓库。这种分散的代码组织方式给开发者带来了诸多问题包括依赖管理困难、生产环境中的库版本碎片化、构建工具不统一、各类工具和框架难以获得充分支持、团队协作成本高以及代码共享不便等。从多仓库迁移到单体仓库图 1迁移到单体仓库为解决这些问题公司内部成立了一个跨组织工作组负责制定新的仓库与构建策略。该工作组建议将所有代码迁移到一个统一的单体仓库中采用基于主干的开发模式并确保每个第三方库在公司内部只保留一个统一版本。迁移到单体仓库后公司获得了几项重要收益依赖管理更加清晰生产环境中的库版本更加一致形成了统一的集中式构建平台标准化工具和流程更易推广与维护代码可见性、团队协作效率和代码复用能力显著提升。单体仓库带来的开发挑战迁移到单体仓库为公司的长期工程体系奠定了基础但也让开发者在笔记本电脑上完成日常的“编辑—构建—运行”循环变得更加困难构建规模更大耗时更长开发者需要将数 GB 且频繁变化的构建产物下载到本地或直接在本地完成构建当开发者远离办公室高速企业网络时开发体验会明显下降。有时远程克隆一个新项目并从零开始完成环境搭建需要数小时本地开发环境的维护也始终是难题例如工具链更新不具备原子性、执行步骤不透明、不同开发者之间环境差异较大等。图 2Devpod 概览 – Uber 的远程开发环境Devpod面向大规模工程的远程开发方案为了给开发者提供更快、更便捷、更安全的体验团队开始探索远程开发方案。这个思路很有吸引力将构建任务放到云端性能更强的机器上执行让开发环境在几秒钟内启动并把代码库和工具链统一保存在安全、可控的环境中。Devpod 正是在这样的背景下诞生的。Devpod 是该公司内部的远程开发环境目标是让开发者摆脱本地机器性能、网络和环境配置的限制在云端获得稳定、高效且一致的开发体验。什么是 Devpod 远程开发环境Devpod 是一个面向内部工程师设计的远程开发环境。它以容器形式运行在 Kubernetes 集群上内置开发所需的工具链、配置和计算资源并支持与主流 IDE 集成。借助 Devpod开发者可以在大规模单体仓库中顺畅完成代码编辑、构建、调试和运行等工作而无需在本地笔记本电脑上维护复杂的开发环境。Devpod 的核心优势团队认为远程开发环境的核心价值主要体现在三个方面性能提升、接近零配置以及更高的安全性。其中性能和低配置成本是提升开发者生产力的关键。在安全性方面Devpod 也带来了明显改善。由于所有用户都运行在统一且受控的环境中团队可以确保开发环境始终保持在最新稳定版本。存在漏洞的应用和工具可以在非工作时间完成修补和更新。同时远程开发环境更易监控。团队可以更方便地观察环境运行状态、检测异常行为并在非工作时间扫描磁盘以发现潜在的恶意痕迹或异常活动。由于 Devpod 运行在云端 Kubernetes Pod 中不受笔记本电脑电量限制这类安全检查也更容易自动化执行。通过远程开发提升性能和开发效率Devpod 利用云端高性能计算资源为每个开发环境提供最高 48 个核心和 96 GB 内存。同时团队还围绕 Git、构建系统和 IDE 做了一系列优化从而显著改善开发体验。IDE 体验优化安装并配置由中央开发者体验团队支持的最新 IDE 版本预加载缓存后的 IDE 索引预安装常用工具、扩展和内部插件为开发者提供开箱即用的统一配置。Git 性能优化优化 Git 配置利用 Linux 文件系统相较普通笔记本电脑文件系统的性能优势结合单体仓库场景对常见 Git 操作进行专项优化。构建性能优化预加载构建所需的开发工件提供更充足的计算资源就近接入远程构建缓存减少开发者本地下载和重复构建的成本。除了构建和代码操作速度提升之外远程开发环境还带来了其他体验改善笔记本电脑不再频繁卡死或过热笔记本电脑电池续航时间得到改善每位用户可以同时拥有多个远程开发环境远程开发任务不会受到本地机器上其他进程的干扰。接近零配置的云端开发环境Devpod 预置了一整套工具和配置使开发者能够快速进入主要单体仓库并开始工作配置简单通过一条客户端命令或在 Web 管理界面中点击几下即可按需创建新环境IDE 开箱即用预配置主流代码编辑器和商业 IDE并预加载索引几分钟内即可获得一致的开发环境每个单体仓库所需工具都已完成预安装、预配置和测试操作系统、存储层和库与生产环境保持相似代码仓库已提前克隆减少初次启动等待时间。更安全的远程开发环境使用 Devpod 后开发者无需再手动维护本地环境更新。系统会在夜间自动应用最新工具版本和安全补丁。主要安全收益包括受控工具链开发环境基于预构建镜像内置经过加固的工具链配置变更无缝生效支持快速自动更新镜像在提升为稳定版本之前会经过安全扫描。Devpod 也是持久化的远程环境。工程师无需担心个人设置、文件或代码变更丢失也可以在不同设备之间无缝继续工作。在特定场景下多位工程师还可以进入同一个环境进行协作。全球多区域部署降低远程开发延迟对远程开发而言低延迟至关重要。尤其是在 IDE 和终端交互场景中如果输入反馈存在明显延迟开发体验会迅速恶化。为此团队在全球多个区域部署了 Devpod以便让不同地区的工程师都能获得较低延迟的访问体验。目前Devpod 已部署在以下区域美国俄勒冈州美国弗吉尼亚州欧盟荷兰印度孟买巴西圣保罗。Devpod 类型Devpod 的“类型”指的是面向特定工程师群体定制的 Docker 镜像。每种类型都包含对应开发场景所需的工具并预加载默认设置与配置。目前支持的类型包括图 3Devpod 的各种版本——开箱即用的配置Devpod CentralWeb 管理界面为了改善用户首次使用 Devpod 的体验并提升故障排查效率团队为 Devpod 构建了一个简洁的 Web 管理界面 Devpod Central。通过 Devpod Central用户可以更直观地创建、查看和管理自己的远程开发环境。团队后续还计划持续扩展该平台能力提高资源使用和消耗情况的可见性。图 4Devpod 中心 – 管理门户Devpod 架构设计图 5Devpod 架构Devpod 镜像将所有工具和配置打包到 Docker 镜像中是一个自然且合理的选择。Docker 镜像易于分发和部署许多工程师也熟悉其使用方式因此更容易参与贡献和维护。每个 Docker 镜像都需要一个基础镜像。经过讨论团队认为采用与生产环境操作系统一致的基础镜像最为合理。这样一来团队可以复用现有基础设施来构建和分发内部软件包也可以复用生产环境中已经验证过的关键软件配置。图 6Devpod 镜像层级结构使用 Kubernetes 作为底层平台从本地笔记本电脑迁移到云端后团队可以使用拥有 90 多个核心、数百 GB 内存的高性能机器。最终团队选择 Kubernetes 作为底层平台因为它提供了 Devpod 所需的关键基础能力在高性能硬件上托管容器为容器提供网络连接能力通过持久卷在环境重启后保留工程师的工作内容。Devpod Operator当团队开始使用 Kubernetes 运行 Devpod 时采用自定义资源定义也就是 CRD是顺理成章的选择。CRD 是扩展 Kubernetes 的一种方式它可以在控制平面中保存自定义数据结构。这样团队无需再为 Devpod 元数据单独搭建内部数据库。通过自定义控制器团队可以使用kubectl创建和访问 Devpod。Kubernetes 自定义资源定义的一大优势在于它允许开发者编写一段软件来响应自定义资源的变化。这被称为 Operator 模式。借助这一模式团队将自定义资源与小型自定义控制器结合起来把高层级的 Devpod 描述转换为标准 Kubernetes 原语再交由标准 Kubernetes 控制器处理。最初这个自定义控制器非常轻量。团队甚至开玩笑说它几乎可以被改写成 Bash 脚本。幸运的是最终团队没有这么做。后来团队扩展了该自定义控制器使其能够响应VolumeSnapshotContents和PersistentVolumeClaim从而在 Devpod 未使用时降低成本。图 7Devpod 操作员Devpod 部署策略团队希望将 Devpod 运行在生产数据中心之外的 Kubernetes 集群中主要有两个原因。首先将开发者 shell 服务部署在生产数据中心之外可以带来更强的隔离性。其次公司需要服务亚太以及欧洲、中东和非洲等地区不断增长的工程师群体。通过将 Kubernetes 集群部署在靠近开发中心的位置团队可以为开发者提供更流畅的体验。即便远程开发已经在一定程度上降低了对延迟的敏感性例如使用本地文件、避免每次击键都产生网络往返低延迟对于良好的开发体验仍然非常关键。借助 Kubernetes 作为平台团队可以把精力集中在真正具有战略意义的事情上为开发者提供快速、便捷、安全的开发体验。构建过程本质上高度依赖文件系统。因此将高速存储连接到 Kubernetes 集群对于运行 Devpod 至关重要。虽然也可以使用由对象存储支持的临时文件系统但这种方式实现成本较高使用体验也不够理想。团队仍计划在未来继续探索这一方向。远程开发落地过程中的挑战打造理想的工程师开发环境并不容易。Devpod 在落地过程中面临了不少挑战包括如何在性能和成本之间取得平衡如何提供自动升级能力如何确保开发者工作不中断如何为不同用户预配置合适的 IDE 设置如何在统一环境和个性化需求之间找到平衡。IDE 体验工程师每天都要使用 IDE。因此如果 IDE 体验不够好远程开发环境就很难真正成功。在 Devpod 的发展过程中团队先后提供了多种 IDE 连接方式通过远程模式使用主流代码编辑器通过 Web 使用主流代码编辑器通过 Web 使用某主流商业 IDE该方案后来被弃用通过 SSH 访问远程商业 IDE通过终端使用 Vim 和 Emacs。图 8Devpod IDE 选项除了提供多种 IDE 选项团队还重点从以下方面优化使用体验预加载索引预配置设置预安装工具、扩展和自定义插件。凭借强大的云端实例规格Devpod 能够提供接近本地开发的流畅体验。然而IDE 体验从一开始就是团队面临的最大挑战之一。早期流行的 Web IDE 存在较明显的延迟问题后续又暴露出一些稳定性问题这些都影响了 Devpod 的推进速度。主流代码编辑器的远程版和 Web 版在远程工作负载方面表现较好但在语言理解等智能能力上仍有提升空间。语言服务器协议 LSP 是一项重要进步但很多语言服务器实现仍需进一步完善才能满足大型工程场景的需求。例如如果语言服务器能够将索引保存到磁盘并在后续从磁盘重新加载将会非常实用。但目前许多语言服务器还不支持这一能力。幸运的是LSP 是开放协议许多语言服务器也是开源项目因此团队也有机会向社区贡献改进。保持开发环境持续更新工程师的时间非常宝贵因此提供一个无需手动维护的开发环境至关重要。为此团队会在非工作时间自动升级 Devpod 环境使其包含最新工具和安全更新。为了满足不同工程师的需求Devpod 提供了四种发布节奏稳定版默认版本RC 版下一个稳定版本的候选发布版本开发版每晚更新到最新成功构建版本无自动更新完全关闭自动更新。无论工程师希望使用最稳定的环境体验最新功能还是完全不希望自动升级Devpod 都能提供对应选择。后来团队进一步改进了自动更新机制支持新版本逐步发布。这样做是为了在某个问题漏过自动化测试和候选版本测试流程时尽可能缩小影响范围。远程开发环境的成本效益在推进 Devpod 的过程中团队经常需要回答一个问题自建是否比采购现成方案更合理为了证明自建方案的价值团队持续跟踪并优化每个 Devpod 的成本确保 Devpod 的性价比优于现成替代方案。由于 Devpod 并不是用完即销毁的短生命周期环境团队必须确保计算和存储资源得到充分利用。因此团队实施了多项优化措施。关闭不活跃环境为了节省计算资源自动化任务会定期检查每个环境最近是否被使用。一旦检测到环境长期不活跃系统就会删除其容器从而释放计算资源。虚拟机重新平衡多个 Devpod 环境会部署在同一台大型虚拟机上而这些虚拟机都会产生费用。因此充分利用每台虚拟机的资源非常重要。如果两台虚拟机都只使用了一半资源系统会将负载迁移到其中一台虚拟机上并关闭另一台虚拟机。对已关闭环境的磁盘进行快照Devpod 运行时需要容器和磁盘。当容器关闭后磁盘不再处于活跃使用状态。此时系统会将磁盘转换为低成本存储形式直到环境重新启动。通过这些优化团队成功将 Devpod 成本控制在远低于现成方案的水平同时仍实现了显著的性能提升。跟踪 SLO 指标保障开发者体验该公司的开发者平台服务于约 5000 名核心软件工程师帮助他们高效、大规模地构建、部署和管理高质量软件。团队深知为开发者提供稳定体验是一项重要责任。因此Devpod 团队会持续跟踪服务级别指标 SLI以确保达成服务级别目标 SLO。目前关键指标包括以下几类。系统可用性对于大多数工程师日常高度依赖的系统而言可用性至关重要。团队希望在可用性 SLO 中尽可能提供更多“9”。不过实际可用性也会受到云服务提供商可用性上限的限制。开发环境就绪状态团队会密切监控“预期运行的开发环境数量”和“实际可用的开发环境数量”之间的差异。因为每一个不可用环境都对应着一位受影响的工程师。如果某个环境启动时间超过预期团队会收到告警并排查根本原因。连接健康状况为了让 Devpod 尽可能复现本地开发能力团队必须确保基础设施与公司内部服务之间保持稳定连接。因此团队会持续探测多个端点以掌握整体连接状态。在可用性指标方面团队曾遇到一个问题维护窗口期间即使系统不需要处于完全运行状态也会触发关键告警。这给团队带来了额外负担有时甚至会在夜间打断值班人员。因此团队开始跟踪维护窗口并将该时间段从告警逻辑中排除。可观测性仪表盘则帮助团队将维护窗口与正常运行时间指标进行对比。图 9Devpod 关键 SLO – 正常运行时间Devpod 的实际效果数据显示Devpod 有效降低了本地 Git 命令的执行耗时。以公司最大的单体仓库为例该仓库包含超过 7000 万行代码。在该仓库中执行 p95git status命令时Devpod 的耗时表现明显优于本地笔记本电脑。相关数据表明Devpod 上的 p95git status耗时始终低于 4 秒。相比之下随着单体仓库规模扩大笔记本电脑上的git status性能曾一度持续下降。直到团队在笔记本电脑上引入文件系统监视器和稀疏检出后本地性能才有所改善。图 10Git 状态的改进构建任务也呈现出类似趋势。对于耗时最长的完整构建任务Devpod 的表现始终优于笔记本电脑。以 Go 构建任务的 p95 延迟为例Devpod 在高负载构建场景下表现更稳定。图 11Go 构建时间的改进图 12Go 构建时间的改进对于耗时更长、更复杂的构建任务Devpod 的性能平均比笔记本电脑提升 2.5 倍对于一般构建任务也就是 p75 构建任务Devpod 的性能平均比笔记本电脑提升 1.8 倍。随着这些改进持续落地Devpod 在组织内部的采用率自然增长。截至 2022 年 11 月超过 60% 的软件工程师已经采用 Devpod。图 13Devpod 采用情况开发者认可 Devpod根据内部开发者 NPS 反馈Devpod 一直被认为是最能提升工作效率的工具之一。调查显示多数开发者喜欢 Devpod 的主要原因是它显著提升了构建速度。许多开发者表示使用 Devpod 后他们的工作效率和生产力都有明显提高。下一步规划团队认为Devpod 代表了该公司工程体系未来的重要方向。长期目标是让工程师获得完全无缝的远程开发体验。接下来团队计划重点探索以下几个方向。按需 Devpod目前创建一个新的开发环境大约需要 2 到 3 分钟。团队希望通过预先配置每种产品类型的开发环境并在分配给请求用户之前完成最终配置将初始创建时间缩短到 3 秒以内。临时 Devpod生命周期更短的开发环境一旦按需 Devpod 能够实现并将新环境创建时间缩短到 3 秒以内团队希望将 Devpod 与开发者日常使用最频繁的工具进行更深入集成。团队预计短生命周期 Devpod 可以应用于以下场景专用于功能开发的临时环境快速调试 CI 失败问题开箱即用的代码审查环境分析移动端崩溃问题。非中断式自动升级和维护目前系统会在非工作时间设置环境维护窗口。但部分工程师可能需要在非工作时间工作或在环境中运行耗时较长的任务。因此团队计划通过监控活动连接并在必要时延迟维护任务进一步降低自动升级和维护对开发者的影响。通过自动化降低成本并提升性能团队希望制定更加精细的调度和关停策略在不中断用户工作流的前提下进一步降低成本并及时清理闲置 Devpod。这一方向可以理解为 Devpod 的自动化调度能力系统根据环境使用情况、资源消耗和用户活动状态自动做出更合理的资源分配决策。无缝 IDE 体验理想状态下IDE 应该在后台隐藏远程环境的实现细节让工程师在本地笔记本电脑上使用 IDE 时几乎感知不到远程环境的存在。IDE 可以在后台静默连接到远程环境并在网络状态良好时提供强大的云端计算能力。即便远程环境出现问题开发者也不应被迫中断工作而是能够无缝切换并继续在本地完成开发。面向所有环境的集中式构建集群团队计划引入一个统一的构建集群提供远程缓存和远程执行能力为 CI、笔记本电脑和 Devpod 开发环境共同服务。该构建集群将运行计算密集型任务并充分利用空闲计算资源。此外团队还希望部署一个地理分布式远程缓存以最大限度降低延迟并为构建产物提供更快的下载能力。团队专属 Devpod 配置团队正在探索如何尽可能简化新团队首次使用 Devpod 的配置流程。其中一个重要方向是允许团队自定义 Devpod 配置。这样新团队成员只需点击一次就可以获得符合团队需求的一致开发环境而不必手动完成复杂的环境搭建。笔记本电脑与 Devpod 之间的无缝文件传输工程师会使用 Devpod 处理计算密集型任务和长时间运行的构建。在某些情况下开发者需要在笔记本电脑和 Devpod 之间传输文件反向传输也同样常见。团队的目标是将 Devpod 驱动器自动挂载到用户笔记本电脑上从而实现笔记本电脑与远程开发环境之间的无缝文件传输。Devpod 对 Android 模拟器的支持Devpod 能够显著缩短 Android 开发者的构建时间。然而在远程 IDE 中进行测试和调试时当前体验仍不够理想。主要原因是远程环境中缺少 Android 模拟器也缺少可通过 ADB 连接到 Devpod 的虚拟设备。团队的目标是为使用 Devpod 的 Android 开发者提供无缝调试体验包括与 Devpod 支持的 IDE 集成的内置插件。总结Devpod 的实践表明对于拥有大规模单体仓库和复杂构建体系的工程组织而言远程开发环境不仅可以提升构建性能还能降低本地环境维护成本增强安全性并改善整体开发者体验。不过远程开发环境解决的主要是“开发执行效率”问题。对于希望进一步提升端到端研发效能的团队还需要把目标、需求、任务、测试、发布、知识沉淀和数据分析串联起来。比如借助 PingCode 这类智能化研发管理工具团队可以将研发过程中的需求流转、项目开发、测试发布、知识积累和工具集成统一起来让远程开发带来的效率提升进一步沉淀为可管理、可度量、可持续优化的研发体系。通过云端计算资源、Kubernetes 容器平台、预配置 IDE、远程构建缓存和自动化运维能力Devpod 为提升开发者生产力提供了一条可行路径。对于正在应对大型代码库、复杂工具链和多地区协作挑战的研发团队来说这类远程开发模式具有重要参考价值。