作者 | Mike
译者 | Sambodhi
策划 | 褚杏娟
云中的开发环境是什么?这个问题看似很简单:不需要在本地计算机上开发软件,而是利用云托管环境中的 CPU、存储和网络。但事实上却远不止如此!
云中的开发环境旨在消除“我在机器上工作”的挫折感。你不需要长期构建和维护你的开发环境,只要配置好就可以;你没有 CONTRIBUTING.md,但你有脚本;你拥有的不是部落知识,而是配置,这样确保每个开发者的环境都是相同的。如果一名开发人员的开发环境中出现问题,那么其它人也会有这个问题。只要解决了这个问题,每个人也就都能按预期工作。
如果你需要在六个月前的确切状态下调试应用程序,那么按照给定的提交启动开发环境、完成,它将百分之百起作用。
我们有工具来创建拉取请求预览,特别是在 Web 应用的背景下。当代码被推送到拉取请求时,对代码进行隔离的、特定于分支的部署,它非常适合收集反馈、协作、演示新特性或 Bug 修复。
将这个概念应用到开发环境中,可以实现多种激动人心的用例:
• 与同事共享用于结对编程的开发环境
• 在向客户演示项目时,可实时处理更改
• 如果你开办一个讲习班,就要在学生自己的环境中帮助他们。这就好比课堂上你在学生们的身后看着,但区别在于你可以身处世界的任何地方。
云中的开发环境改善了我们的工作方式,目前为止,StackBlitz 的 Codeflow 就是最好的例子。
你处理的每个任务都发生在独立的开发环境中,你开始工作、完成工作、提交并推送,而你忘记了那个特定的开发环境。
注:除了 CoDeflow 的工作流演示之外,StackBlitz 仅限于 Node.js 开发,绝不是属于云类别的开发环境的产品。
1 云上开发环境都有哪些问题
任何告诉你没有负面影响的人都是骗子,他们把自己的利益放在了第一位。在云环境中开发并非一个万能的解决方案,需要逐案评估。让我们探讨一些你不会在供应商网站上看到的挑战。
必须有互联网接入
如果你的开发环境是在云中,那么你就要保证一直可以连接到云上,否则你可能没那么走运。
尽管在欧洲和北美互联网全天候接入相当普遍,但是世界其它地方仍有一大批软件工程师没有条件或者负担不起。值得注意的是,这也适用于自托管解决方案。无论你是使用 SaaS 产品还是你自己的数据中心托管服务,一旦失去连接都意味着没有人能够正常工作。根据团队规模,有时候这种代价会很高。
服务必须具有可用性、可靠性
如果你的 CI 出现了故障可以继续编写代码,如果你的 Jira 出现了故障也可以继续编写代码。但是,如果你云中的开发环境出现了故障,那情况就不太妙了。如果服务出现中断,你的工作效率将会受到影响。不只是你,你团队的所有成员和任何其他依赖该特定服务的人都是如此。
为了更好地理解这点,下面有一些关于 Codespaces 和 Gitpod 服务可用性的公开报告,Gitpod 是一种工作流程与 StackBlitz 的 Codeflow 类似的产品,但被托管在两个数据中心。
来源:Codespaces、Gitpod
产品质量依赖第三方
事故只是一方面,另一方面就是产品质量。我并不知道 GitHub Codespace 已经公布了他们的 Bug 报告,但就 Gitpod 而言,其在 2022 年 7 月、8 月、9 月、10 月和 11 月中,每个月都报告了超 100 个 Bug。在同一时期,至少 30% 的报告错误仍然存在。
如果你在本地环境开发,那你关心的产品质量是你笔记本电脑的硬件、操作系统、终端和编辑器。但当你的整个开发环境都在云上时,你就会被一家 SaaS 供应商锁定,并依赖他们的质量保证团队。截至 2022 年 6 月,Gitpod 没有专门负责 QA 的人员,而在 2022 年 12 月,这一职位仍然空缺。
目前为止,编写软件是开发者日常工作中最重要的部分,如果第三方服务不可用或出现中断,你真的想要依靠没有可行解决方案的第三方吗?
天然存在延迟
如果你键入一个字符,而该操作需要 100 多毫秒才能到达开发环境,那么你很可能在放弃之前才键入少于 5 个字符。更糟糕的是,还有 100 多毫秒的时间才能从开发环境中获得响应。
延迟取决于开发环境相对于物理位置的可用性。为了更好对比,我们在下表列出了两个供应商 GitHub Codespaces 和 Gitpod 的地理可用性:
过去两年来,Gitpod 一直未能扩展到其他地理区域,而且这一状况还在持续。截至 2022 年 11 月 17 日,官方更新的说法是,扩展并非易事。
要查看 Gitpod 的欧盟或美国数据中心的延迟,请查看 gcping.com 并查找“europe-west1”或“US-west1”区域。
GitHub Codespaces 的使用范围是 GitHub 的两倍,但与南美洲、非洲任何地方和澳大利亚(最近的地区是东南亚,也就是新加坡)的开发人员距离较远。
要检查你到 CodeSpace 数据中心的延迟,请查看 azurespeed.com,选择以下地区,并查看底部的“Latency Test”(延迟测试)表:West US 2、East US、West Europe、Southeast Asia。
供应商锁定
还记得当初我们多担心被云厂商锁定吗?我们通过开放标准(如 Docker 镜像)来减轻这种影响。不喜欢亚马逊云科技吗?那就获取你的 Docker 镜像,并在 Railway.app 上启动一个容器。这听起来不那么容易,但还是可以做到的。
那么,为什么你不担心被云中提供开发环境的 SaaS 业务锁定呢?你至少应该像担心生产工作负载一样担心!对于评估锁定的程度,我认为有两个方面很重要:配置和自托管。
• 配置。如何配置开发环境的自动化?它是一个专有配置还是有一个开放标准?GitHub Codespaces 凭借他们的 devtainer.json 开放标准(参见 tainers.dev)在这方面处于领先地位。Gitpod 的配置是一个自定义的私有 yaml 文件(参考文档) ,只能与 Gitpod 一起使用。
• 自托管。如果担心服务可用性,你是否可以自托管产品?GitHub Codespaces 不能自托管,而且 Gitpod 也结束对自托管的支持,并将源代码转移到开放源代码 AGPL 许可证。
无论怎样,即使对于目前可用的自托管产品,Gitpod 也没有提供支持生产、高可用性配置的说明。这也可以看出,自己运行 Gitpod 可能有多困难。
支持的工具和框架有限
你可能会认为,声称在云中运行开发环境的 SaaS 业务会支持开发者所需要的任何工具和框架。如果你是一个 Javascript/Node.js/web 开发人员,这当然是正确的。但任何在 Kubernetes 上开发全栈应用程序的人或者想利用 GPU 的数据科学家,都应该慎重。
了解 SaaS 供应商的架构以及由此带来的限制是至关重要的。
对于 GitHub Codespace 用户来说,好消息是厂商提供了一个实际的虚拟机,无论是运行 Kubernetes 还是利用 GPU 进行机器学习工作负载都可以支持。但另一方面,Gitpod 限制了你能在 Docker 容器中运行的任何内容。考虑到 Gitpod 本身已经是一个 Kubernetes 应用程序,作为一个工作区,你得到的只是一个运行在 Kubernetes pod 上的容器。虽然隔离性很好,但你可以与其他开发人员共享该 pod 的资源,甚至共享的人并不是你公司的。
定价难
本地开发购买计算机有一次性的前期费用,而云中的开发环境会根据使用情况定价,工作越多,付出的金钱就越多。
与云厂商一样,提供云上开发环境的公司会在开发环境运行的秒 / 分钟 / 小时内盈利。你只要忘记关闭,那在你想起来之前就要一直付费,直到它可能会在某个时间自动关闭。
我还认为,对于未来 10 亿居住在欧洲和北美以外的开发商来说,有一点值得注意:云上的开发环境将无法降低价格,这使那些没有特权的人负担不起,仅仅是因为运营成本太高。
对于大中型公司来说,由于简化的工作流程和自动化的开发环境设置,很难衡量成本的节约。正如我之前所说的,每个团队都必须分别评估利弊。与任何商业采购一样,都要协商出一个合适的价格,永远不要支付广告上所宣传的价格。
2 必须在云上吗?
对于大多数开发人员来说,编写代码是很孤立的一件事。为了让大家直观地了解,让我们看看一个软件开发生命周期(software development lifecycle,SDLC)的五个阶段:
来源:我在 2020 年 6 月在 InfoQ 发表的文章
正如我在 2020 年的 InfoQ 文章中所写,这五个阶段中有四个已经发生在云中,为什么剩下的一个不也放到云上呢?问题是,真的应该在云上实施吗?
自从那篇文章发表以来,我一直在研究云中提供开发环境的众多现有解决方案,后来得出结论:实施阶段需要一种更加动态、灵活的方法。
3 完全成熟的解决方案是什么样的?
谷歌、Facebook 和其他公司多年来一直在使用云上开发环境。尽管云上开发环境有各种各样的挑战,但它仍然适用于这个行业的每个人。
最重要的好处是允许我们消除上下文切换!你可以在 my-Feature 分支中处理某个特性,同时在 prod-hotfix 分支中查看 PR。两个分支都在完全隔离的环境中签出。当你完成任务后就可以忘记以前的环境继续前进,并为下一个任务开始新的环境。
作为一名开发人员,开发环境无论是在本地还是云中,都必须完全透明。不过重要的是,我们想要引入一些改进:共享开发环境来与团队成员配对编程,可以并行启动多个开发环境(例如开发一项功能并快速审查拉取请求)利用云供应商提供的更多 CPU/GPU/ 存储 / 更快的网络 / 最新的存储库来准备开发环境快照,以进一步加快开发环境准备时间。
架构
GitHub Codespaces 和 Gitpod 都提供了自定义架构,不过这一派的思想已经过时了。我们已经定义了一个广泛采用的解决方案,用于安装依赖项和创建独立的、可重现的环境:Nix(Nix 的一系列操作意在彻底解决软件之间依赖问题)。
步骤 1:云中开发环境的完整解决方案必须基于 Nix。
Nix 有什么好处?在线搜索“Why Nix?”可以看到很多答案,其中一个主要优势是 Nix 可以分离各个依赖版本。比如要处理两个 Python 项目,一个依赖于 Python2.x 和 PostgreSQL12,另一个依赖 Python 3.x 和 PostgreQL14。使用 Nix 的话,你可以安装两个版本,并根据项目使用对应的版本。这个概念适用于所有操作系统依赖项,如果应用于开发环境,那么每个开发环境都会是完全独立!
配置
Nix 是伟大的,但 Nix 语言有一个非常陡峭的学习曲线,以至于大规模采用配置开发环境是行不通的。下面是用 Node.js 18 配置开发环境的 shell.nix 文件(来源) :
{ pkgs ? import (fetchTarball "https://github.com/NixOS/nixpkgs/archive/3590f02e7d5760e52072c1a729ee2250b5560746.tar.gz") {} }:
pkgs.mkShell { buildInputs = [ pkgs.nodejs-18_x ];}
事实上,我们真正想要的东西是这样的:简洁、易于理解,是开发人员熟悉的格式。
{ "packages": ["nodejs-18_x"]}
步骤 2:完全抽象 Nix 包管理器和 Nix 语言。
为了避免供应商锁定,你必须将开发环境配置作为一个开放标准导出,例如作为一个 devconter.json 规范导出,这些规范记录在 conters.dev 文档中。
生命周期管理
安装所需的操作系统级依赖项是一个很好的开始,不过任何应用程序都有额外的先决条件,并且需要启动数据库和应用程序服务器,还需要一种在开发环境终止时运行命令的方法。
假设我们使用 PostgreSQL 数据库开发一个全栈 Web 应用程序,让我们扩展上面的 JSON 配置文件:
{ "packages": [ "nodejs-18_x", "postgresql_14" ], "init_hook": [ "npm install", "sh ./scripts/start-database.sh", "npm run dev" ]}
步骤 3:提供生命周期钩子来自动化开发环境的所有方面。
无论你想要安装依赖项、启动服务器还是终止到共享数据库的连接,都必须能够拦截从开发环境创建到终止的、贯穿生命周期的各种事件。
托管在你附近
为了获得最佳体验,云上开发环境需要尽可能靠近开发者的物理位置。
Codespaces 的四个数据中心可能并不接近,而且 Gitpod 的两个数据中心肯定也不是!解决该问题的方法之一是使其能够在云供应商提供的所有区域中运行。一个轻量级、自包含(self-contained)的架构可在全球所有地区无缝扩展。
不过即便如此,你仍然只能使用云供应商提供的数据中心。为此,我们有了另一个解决办法:边缘网络,在边缘网络上部署一个自包含的开发环境,它可以放置在离你稍微远一点的地方。
步骤 4:在边缘网络上运行开发环境。
当然,边缘网络对于开发人员来说得是无缝的。无论是在南非开普敦还是在阿根廷布宜诺斯艾利斯,我都希望我的开发环境能够以毫秒级的延迟运行。如果到法国巴黎旅行时要启动一个开发环境,我希望我附近的边缘节点可用,连接上就开始研发。
放弃集中式数据库
为了实现上一节中提到的托管延迟,你得放弃集中式数据库,否则即使你的代码和计算都在附近,一旦该边缘节点上的服务需要从 us-east1 数据中心请求数据,毫秒延迟的所有希望都将落空。
步骤 5:使用全局复制的 SQLite。
将开发环境服务供应商所需的数据,例如与认证、服务度量、用户设置等相关数据,放在边缘节点开发环境的旁边。开发人员每次启动云上开发环境时,本地 SQLite 数据库都会提供并收集必要的数据,当实例发生在该数据库时,它们将在全局范围内复制到所有其他实例中。
支持离线工作
只有在能够访问网络或 SaaS 提供程序可用的情况下才能访问的开发环境,100% 是没用的。开发人员应该能够像过去几十年一样,在本地运行开发环境,使用相同的配置、相同的端口和相同的自动化。
如果开发人员选择离线工作,他们将无法与团队成员共享开发环境,无法使用 GPU、自动化环境快照,也不能并行多个环境。然而,无法使用这些功能应该是一种选择,而不是因为做不到。
步骤 6:透明地在本地运行开发环境。
开发人员可以自由配置他们更喜欢的开发环境,云中抑或本地(环境变量、CLI 标志等)。如果云上开发环境连接中断,开发人员可以收到通知并转而继续在本地工作。
要实现这一点,需要在云和本地环境之间同步文件。当连接中断时,自动化脚本在本地运行并启动数据库和应用程序服务,这样对开发人员来说就是完全无缝的。
同样,当云上连接恢复时,开发人员也会得到通知并选择是否切换到云环境中,这种切换是没有任何代价的。
定价
使用开发软件不应该让任何人倾家荡产。任何人都应该免费获得自动化开发环境、简化依赖管理和标准化配置的好处。这部分的实现要归功于上文“离线工作”中概述的内容。这本身已经是对 CONTRIBUTING.md 文档和手动开发环境设置的一个巨大的改进(虽然可能已经过时)。
开发人员希望利用云特性时,供应商可以在开发人员使用期间按需付费。由于本地和云开发之间的无缝过渡(如前一章所述),开发人员从本地切换到云的开销为零,反之亦然。
4 总结
如今的云上开发环境是有缺陷的:它们需要手动设置和维护、过于脆弱,迟早会在不同团队成员的机器上崩溃。此外,它们仅限于云,并且试图利用开发者花费在开发软件或学习开发软件上的时间来赚钱。
我们不能简单地展示并规定我们如何开发软件。为了保证所有开发人员的持续生产力,几十年开发的肌肉记忆需要保留。然而我们需要一种进化,先来解决最关键的挑战:自动化和可再现性,同时开发人员无需付出任何代价。
以下是为云中的开发环境引入额外功能的基础:
• 与团队成员和其他利益相关者分享
• 利用云计算、存储和网络速度
• 并行运行多个环境
• 自动化环境快照可降低依赖项安装等待时间,使其接近于零
总而言之,流程就是:
• 步骤 1:云中开发环境的完整解决方案必须基于 Nix。
• 步骤 2:完全抽象 Nix 包管理器和 Nix 语言。
• 步骤 3:提供生命周期钩子来自动化开发环境的所有方面。
• 步骤 4:在边缘网络上运行开发环境。
• 步骤 5:使用全局复制的 SQLite。
• 步骤 6:透明地在本地运行开发环境。
作者声明:
这篇文章使用 GitHub Codespaces 和 Gitpod 来概述当今在云端实现开发环境所面临的挑战。这是我最熟悉的两种解决方案。保证信息透明起见,请注意我为 Gitpod 做了近两年的工作。无论如何,在这篇博客文章中分享的任何内容都是基于源代码链接的公开信息。
原文链接:
https://www.mikenikles.com/blog/dev-environments-in-the-cloud-are-a-half-baked-solution
本文为 InfoQ 翻译,未经书面许可,严禁转载。
今日好文推荐
“干净”的代码,贼差的性能
一场向应用交付标准的“冲锋”
没有 NGINX 和 OpenResty 的未来:Cloudflare 工程师正花费大量时间用 Rust 重构现有功能
开源意味着不问责,我们准备好应对比 Log4Shell 更大的安全危机了吗?|Log4j 一周年特别报道
活动推荐
近年来,组织数字化转型已经成为大势所趋,而研发管理数字化是组织数字化转型的基础工作和必赢战。
我们观察到各行各业,研发团队的规模都在急剧扩张,成百上千人的研发组织已经成为常态。然而,由于大型研发组织是一个复杂系统,组织规模扩大后,管理复杂性也急剧提升。研发团队效能开始降低,交付周期开始变慢,质量变差,团队协同成本提升开始出现。
如何做好大型研发组织的研发效能管理,提升研发团队交付速度,提升业务团队满意度成为 CTO 们关心的话题。
为此,极客邦科技旗下 InfoQ 极客传媒 、极客时间企业版与 Agilean 联袂推出「数字化研发管理」线下公开课 从组织角色,流程制度,工具体系等多个角度来全方位地思考和讨论,提升研发效能的方法和实际案例。