导语
Cloud Studio 团队日常开发实战案例自举分享
本文着重分享Cloud Studio产研团队是如何使用腾讯云「云端开发环境 Cloud Development Environment - 简称CDE」来改进日常开发-调试-构建-运行的关键阶段的开发者体验。
Cloud Studio 产品是基于云端开发环境的开发平台,旨在化繁为简解决本地开发诸多问题。
作者从团队最初决定上云实战所遇到的挑战、迁移上云过程中的痛点、进而讲解架构重构带来的优缺点以及如何重点提升开发环境启动性能、降低成本方面,并分享取得的进展。
最后,作者将给您留下一些关于「云端开发环境」在当下及对于未来的机遇与想法。
01 初始痛点
Cloud Studio 的核心代码库状况
Cloud Studio 的业务场景相比于传统业务项目是极其复杂的,各个模块形态不同,vscode 内核、插件、各类文件系统管理程序、动态的容器进程等多种形态的应用程序、十余种编程语言、数十种后台服务及针对各类程序的配套构建与配置工具。
久而久之,碎片化成为了 Cloud Studio 团队大开发人员最大的痛点。具体来讲,即依赖混乱、各模块版本难以统一、多工具碎片化使用成本高、难以协作及代码共享等。
移动到 Monorepo
为解决这些问题,我们制定了代码库转移策略,逐步将所有的代码库转移到统一的代码仓库中,并建立了基于主干的开发模型。
monorepo 的模式提供了如下的优势:
- 更好的依赖管理
- 一致化的各组件、模块版本管理
- 集中式统一管理的构建平台(由 CODING CI、 Bazel 等构成)
- 更便利的协作、文档共享、统一的目录管理等。
Monorepo 挑战
切换到 monorepo之后,我们发现另一个问题:虽然monorepo对稳定统一的开发流程奠定了坚实的基础,但它使日常笔记本电脑上完成DevOps的完整研发流程(从代码编辑-提交-构建-运行-测试)变得具有挑战性,如图1:
- 构建更大,花费的时间更长
- 需要将几 GB 的经常变化的工件下载到笔记本电脑或在本地构建
- 离开办公环境,快速进行开发是一项挑战。有时,克隆一个新项目并从头开始配置本地开发环境,会花费数小时甚至一天的时间。
除了所有这些之外,维护一套一致的工具,并保持笔记本电脑上的本地开发也是需要我们关注并解决的问题。
图1 workspace剖析图
02 使用 Cloud Studio 进行远程开发及自举
我们问自己,既然我们做的是云端开发平台的事情,说了那么多优点(可扩展性、享受云资源、隔离性、随用随取等特点),可否把自己的大仓库跑在云端开发环境里,用Cloud Studio产品特性来进行日常开发,从而不断反哺产品体验,不好用的体验,自己发现自己尝试去修复问题。于是我们进行了自举道路。
什么是腾讯云-云端开发环境?
当我们寻找解决方案来为我们的开发人员提供更快、更轻松和更安全的开发体验时,我们开始关注远程开发作为替代方案。在腾讯云更快的机器上构建云端开发环境,几秒钟内拉取,并将所有代码库和工具保存在安全、受控的环境中的想法。
这就是Cloud Development Environment 的初衷:基于Cloud Studio开发平台构建CDE云上开发环境。
什么是 Cloud Studio?
Cloud Studio 是基于浏览器的集成式开发环境(IDE),为开发者提供了一个永不间断的云端工作站。用户在使用 Cloud Studio 时无需安装,随时随地打开浏览器就能使用。云端开发体验与本地几乎一样,上手门槛更低;具有极强的开放性,第三方平台通过我们提供的 SDK,则可以方便地集成Cloud Studio云端开发能力。
>>优势
三月我们发布了腾讯云云端开发环境白皮书之后,我们把Cloud Studio产研代码和日常开发搬上腾讯云 CDE 中。在白皮书中,我们定义了DevOps、容器化、代码化定义CDE的零设置门槛、安全性是远程开发环境的主要优势。我们通过在最新的稳定版本内核及隔离环境之上,来运行每个开发者的代码,从而大大提高安全性,譬如,我们定制了自动脚本,使得易受攻击的应用程序代码可以在非工作时间进行修补和更新。监控远程开发环境的许多不同方面是相当简单的,我们可以随时检测和识别恶意行为,譬如挖坑、翻墙等。由于在云端开发环境中(背后是Kubernetes集群)运行的 Kubernetes pod 没有电脑的电池和资源限制,因此在下班时间扫描磁盘以查找恶意工件或活动是微不足道的,但价值是巨大的。
>>性能第一
通过利用强大的腾讯云资源——每个环境弹性提升到 最多 32 个内核和 128 GB RAM 以及许多附加功能,更快的 Git、构建和 IDE 体验,如图2:
云端IDE启动:预热常用的开发镜像,秒极启动云端IDE,并根据云端开发环境(CDE)的代码定义,安装配置开发常用的language server、插件等,让开发者的体验获得最佳。同时我们保持内核常新。
\>>持续调优的 IDE 启动链路,通过测试,平均2-3秒即可打开,如下图所示
图2:分层架构
- 内网下载依赖构建:设置国内中央仓库,找到最近的最快的网络下载位置;针对团队内部开发,我们优化了网络方案,在产品上设置团队依赖库的缓存能力,实现秒级挂载,无需额外重新下载。
通过以下方式改进了 Git 性能:
\>>采用Linux 文件系统,与笔记本电脑文件系统相比,性能更好
\>>Git 网络代理,内网访问加速
\>>优化 Git 配置
通过以下方式改进了云端开发性能:预加载所需的开发环境里的插件、预热了镜像启动,预热了依赖库等;同时还提供了:
\>>提供更多计算资源,在编译过程中弹性提升规格,在不用时降低高规格的占有率。
除此之外,远程开发环境还提供:
\>>每个用户多个云端开发环境
\>>独立于笔记本电脑上运行的其他进程进行隔离。在开发上可以做到真正并行。
>>环境代码化和维护
Cloud Studio 支持 workspace.yaml的可视化定义配置(Cloud Studio 高阶玩家:强大的 YAML 模板),并为该配置保存成「自定义模板」,这些模板为团队成员的monorepos 仓库的云端开发提供了极大的价值:
- 易于配置——可视化UI界面配置,无代码的方式即可配置出自定义的新环境配置
- 支持任意本地的IDE——预配置默认启动的IDE类型
- 在几分钟内访问一致的开发环境
- 每个 monorepo 所需的预安装环境里的工具、依赖配置、插件和测试工具等
- 预克隆存储库,为存储预热,用得多启动更快
>>安全性
无需担心代码文件被窃取,Cloud Studio 提供的持久化工作空间,会进行特殊加密(详细文章见:Cloud Studio 云端开发保障企业源代码安全):
\>>受控的开发环境-仅安装安全可靠的工具插件,禁止手动安装非认证插件等
\>>安全的数字水印- 不干扰写代码,但是当准备复制到开发环境之外,我们会针对内容进行加密,防止代码被带走。
\>>禁用复制粘贴和下载能力,但对当前工作空间依然有效。
- 安全性,可通过开关根据所需开启或关闭。
环境保持最新状态——开启自动更新能力,我们会在夜间自动更新最新的插件,进行安全升级,扫描环境里的安全问题:
\>>更安全的工具链——预先定义好的的安全环境,受管控的安全的安全工具链
\>>更安全的软件供应链
\>>无缝配置更改---- 支持底层基础镜像切换、版本切换等,一键热启动即可享受新环境,且当前开发状态不丢失。
\>>团队级别插件市场,可使用最新插件自动更新
\>>可以在将映像发布之前对映像执行安全扫描
Cloud Studio 提供的工作空间是持久的,因此工程师无需担心丢失他们的个人设置、文件和代码更改。这允许工程师在不同的设备上继续他们的工作,并支持多个工程师在单一环境中进行协作。
Cloud Studio 本土化云端开发平台
>>提供主流开发语言环境
我们为中国开发者打造更适应国人开发习惯的开发平台,同时内置了数十款的基础开发环境的模板库,包括所有必需的基础镜像,并预加载了默认设置、预置常用插件和开发配置。我们目前支持以下开发环境的语言,如图3:
- C/C++
- Html
- C#
- Java及Spring框架
- js及Nodejs周边框架
- Go
- Python 及 Flet 框架
- Flutter 及 Andriod 开发
- Vue React Angular 及其他前端框架
图3:开箱即用的配置
>>基于 Web 的开发空间控制台
Cloud Studio 为登录用户提供了专属的控制台,为用户管理自己的工作空间状态,消耗资源情况,制作个性化的专属模板、徽标,团队管理及团队资源情况,满足简单个人开发到复杂的企业级开发的诉求,如图4所示。
图 4:Cloud Studio 控制台
03 Cloud Studio 开发环境架构
图 5:Cloud Studio 控制台
如图5所示,在 Cloud Studio 中,所有的个人环境全部被放置在容器环境中,这使得开发者可以使用官方提供的各类版本,还可以轻松地通过 Dockerfile 定制自己的环境,并且即使脱离 Cloud Studio 也能够被应用在任何地方。在容器之上,Cloud Studio 会为用户提供额外的开箱即用的软件包,这包括了用户的编辑器界面、Docker、kubectl 等常用开发工具。
如图6,我们统一提供了 Ubuntu 作为开发操作系统,Ubuntu 作为全世界最流行的 Linux 发行版,最符合开发者用户的使用习惯。其建立在 Debian 之上又天然可使用大部分 Debian 生态下的工具链,从而可重用大部分现有生产环境基础设施。
图6 Cloud Studio 镜像层次结构
从本地电脑迁移到云,使得能极大地优化享受云上更丰富的计算资源,海量的计算内核和高性能的大容量 GB RAM 的机器。最重要的是,我们决定使用 kubernetes,基于腾讯云 TKE、EKS 及高速稳定的集群能力,给我们提供了我们所需要的 IaaS 能力:
- 在强大的硬件上托管容器的能力
- 连接容器并支持并行运行
- 用于在重启之间存储开发过程中的文件,并持久化到NFS的持久卷中
面向Kubernetes的标准化底层容器
我们使用Custom Resources | Kubernetes CRD来完整的描述一个工作空间资源,这使得即使脱离 Cloud Studio 平台,用户也可以直接通过 kubectl 自行创建、调度、访问 Cloud Studio 的工作空间 pod。
在 CRD 中,我们扩展了 PersistentVolumeClaim 特性,以支持任意的外部持久化数据,而不仅仅局限于 Cloud Studio 自身所使用的全局 NFS 持久化。在后续,我们计划支持响应 VolumeSnapshotContents 变化,从而降低不使用时的存储成本。
图7:Cloud Studio CRD
04 挑战
为工程师创造完美的环境并非易事——我们在此过程中遇到了一些挑战。在性能和成本效率之间取得平衡、提供自动升级、确保不间断工作以及预配置适用于每个人的 IDE 设置是我们必须克服的一些障碍。
IDE 内核选型
工程师每天都在使用 IDE,因此没有良好 IDE 体验的远程环境是无法成功的。在 云端开发环境里,我们提供了多种不同的 IDE 内核选项:
- Cloud Studio Web IDE 内核
- VS Code Remote SSH
- JetBrtain Remote SSH JetBrains Gateway - Remote Development for JetBrains IDEs
>>Remote SSH 连接方式
如图8所示,任意Pod所启动的云端开发环境,都可以用喜爱的本地IDE进行连接,保留喜欢的主题、熟悉的快捷键。充分利用云端开发环境的优势。
图 8:通过SSH的工具访问云端开发环境
通过 SSH 连接云端 IDE 工作空间 | Cloud Studio
除了提供多种 IDE 选项外,我们还专注于通过以下方式微调动手体验:
- 预加载索引
- 预配置设置
- 预安装工具、扩展和自定义附加组件
Cloud Studio 基于弹性算力和持久化存储,为用户提供快速开发的云端开发体验,但是 摆脱本地主流IDE 转到云端开发,从早期开始就是我们最大的挑战之一。特别是,早期流行的基于 Web的 IDE 的延迟问题以及随后的一些稳定性问题给我们带来了很多困扰。
后面我们发现,Web 的IDE和本地的IDE应该是共存,我们应该致力于建设并推行云端开发环境的理念,并与之企业研发的降本增效诉求、DevOps研发一致性,进行助力
使环境保持最新
由于工程师珍惜他们的时间,提供一个不需要手动维护的环境很重要,因此,我们在非工作时间使用最新的工具和安全更新自动升级环境。
为了满足每个人的需求,我们允许工程师从四种发布节奏渠道中选择一种:
- stable——默认一个
- rc——下一个稳定版的候选版本
- dev – 每晚更新到最新的成功构建
- none ——没有自动更新
无论工程师想要最稳定的环境和最先进的功能,还是根本不需要任何升级,我们都能满足。
后来我们改进了自动更新以支持逐步推出新版本。添加此功能是为了减少爆炸半径,以防错误通过我们的自动化测试和候选发布、内部测试过程。
成本效益
从很多客户侧发现,有构建与购买资源的情况并不少见。和企业合作、腾讯云Serverless、基于Cloud Studio产品自我开发的过程中,我们不断跟踪监控,并改进Cloud Studio 的成本,并确保 Cloud Studio 的性价比优于其现成的替代品。
为提高资源利用率,实现更好的成本控制,我们将自建 K8s 集群迁移到腾讯云 Serverless 容器服务(原弹性容器服务EKS)中,我们的目的是将资源上云,充分利用云天然资源利用率和运维成本的优势。
为了实现上云,我们做了大量的架构重新设计,首先将工作空间所依赖的特化特性全部重新设计:
- 去 OCI Hook 特性依赖:在之前工作空间资源持久化我们是利用了 CRI 标准中的 OCI Hook 特性实现的用户持久层的 save 与 load,具体来讲是在容器启动过程中,替换镜像的 upper layer 为我们为用户准备的 ext4 虚拟磁盘持久化数据。而在云上,显然我们不能利用这类特性,因为我们无法充分预估底层 runtime 是否一定兼容 OCI Hook,为此我们重新设计了用户容器,采用两层架构,在外层,我们用标准容器提供一个标准环境,接着在此环境中运行一个 podman 容器,然后通过内层 image inspect 拿到层信息并将用户持久化层组装成最终的 rootfs 提供给 podman 运行。
- 去 DaemonSet 特性依赖:Cloud Studio 团队十分看重容器启动性能,而 Ops 视角出身的 k8s 天然又不特别关注容器镜像下载速度的问题,因此为了提升用户所需容器加载速度,在之前,我们使用了 DaemonSet 为每个节点预热所有用户所需要的基础镜像,从而保证了用户镜像的加载速度,但 DaemonSet 的特性天然与云冲突,因为云的理念是用户不关心节点资源,为了处理这个问题,我们完全重新设计的用户容器镜像预热逻辑,我们除了按需向 k8s 提供资源需求之外,又引入了一层缓存,也就是说会提前向 k8s 申请一起 pod,与之前不同的是如果我们申请的是节点,那么节点的资源是固定的,而申请一批 pod 不同,我们结合业务需求,完全可容忍一定的资源超卖,因此我们申请的资源的 request 都极少,同时又使用 limit 去限制了容器的最大资源保证尽量平衡资源要求,最后结合 k8s 调度又设计了重新调度的策略,对每个缓存 pod 进行评分为每个用户选择表现最好的 pod 供用户使用。
除了这些较大的逻辑变动外,我们还有很多其他的例如流量导入策略、实时计费信息采集等多个优化点,最终形成了一个真正贴合云原生设计又能满足极大资源利用率的工作空间设计,下面是变更示意图:
图9: 资源利用率 - 每个Pod 五脏俱全
我们提供了全持久化能力,相比友商更具有使用价值。由于引入了NFS,我们必须确保我们有效地使用计算和存储资源,因此我们实施了几项改进:
- 关闭非活动环境:为了节省计算资源,自动化作业会定期检查最近是否使用过环境,并在检测到非活动环境时删除其容器。
- 重新平衡 VM:由于多个环境被放置在一个大型虚拟机中,并且我们为 VM 付费,因此只有充分利用一个虚拟机才有意义。因此,如果有两个 VM 仅使用了其容量的一半,我们将负载转移到一台机器上并关闭另一台。
- 关闭环境的快照磁盘:Cloud Studio 需要一个容器和一个磁盘才能运行。当我们关闭容器时,磁盘不再被使用,所以我们将其转换为低成本存储选项,直到环境再次启动。
到目前为止,我们尽量控制我们的成本下,极力去优化提高性能和使用率,与老的开发环境相比,提升效果非常显著。
产品监控指标
Cloud Studio 跑在了TKE集群之上,标准的K8S之上,如图10,并定义了全链路的性能指标。我们通过各种缓存方案,实现并突破了性能极限。
图10: 基于K8S(TKE)基础之上的云端开发环境的性能指标定义
我们优化前, Cloud Studio 冷启动耗时大约 19S。我们分析了各类典型场景,最终绘制出了主要阻塞点的耗时情况:
图11: 阻塞点
同时针对 inspect 这一严重阻塞项我们分析了其与节点中容器数量的关系:
图12: 分析
经过持续优化后:
图13: 优化后
冷启动时长降低到了 5-7 S。二次启动时长降低到了 5S 以内。
我们的进展
- 启动性能持续优化,当前通过预热优化,我们已在内部实现了冷启动与二次启动 稳定 4S 左右的耗时,后续逐步上线线上环境。
- 通过常驻热点工作空间,使得高活跃度的工作空间二次启动时间缩短到 2S 以内。
- 我们后续计划针对各类常用模板进一步预热,使得大部分场景下,用户冷启动工作空间也能达到 2S 左右的时间。
- 计划优化工作空间启动的错误反馈,使得用户能够更容易去发现并解决问题。
- IDE 启动优化,实现毫秒级 IDE 界面加载。
05 云原生开发调试+云端开发环境
云原生调试是我们在云端集成开发环境中关于测试左移又一思考,从 IDE 本身出发,将云原生服务开发调试也作为 IDE 中的一环,使得任何开发者能够在 IDE 编辑器中一键部署起全套的云原生应用,并轻松使用当前代码针对当前关心的一个或多个服务劫持服务流量,打开断点调试器进行调试或与其他团队成员进行实时联调。
2021年底CODING团队贡献了Nocalhost框架到CNCF,在接下来的时间里,Cloud Studio团队一直致力于将Nocalhost与Cloud IDE进行结合,来实现开发集群下的开发联调、测试左移。通过集群下的专属namespace,以及Cloud Studio团队能力正交,尝试让团队可以简化云原生开发阶段,并能更左移的发现问题。如图14,John和Peter在一个开发集群的一个namespace进行前后端联调,通过服务Pod的替换切入替换成Cloud IDE,进而调试发现问题。特此录制了一个视频来简单介绍一下。
图14:资源服务化
<iframe class="video_iframe rich_pages wx_video_iframe" data-vidtype="2" data-mpvid="wxv_3106757778859409412" data-cover="http%3A%2F%2Fmmbiz.qpic.cn%2Fmmbiz_jpg%2Fiaa3nGiaOKKww12SbylJetW3YsV5mRepTt3LDRDiaNia2jG0Dj9vGXzyohda8jujzbsP7EQdbMBPZ5ykKz457o6ItA%2F0%3Fwx_fmt%3Djpeg" allowfullscreen="" frameborder="0" data-ratio="1.637037037037037" data-w="1768" width="578" height="325" src="https://mp.weixin.qq.com/cgi-bin/readtemplate?t=tmpl/video_tmpl&vid=wxv_3106757778859409412" style="margin: 0px; padding: 0px; border: 0px; width: 524px; max-width: 100%; overflow-wrap: break-word !important; box-sizing: border-box !important; background-color: rgb(0, 0, 0); position: static; border-radius: 4px;"></iframe>
06 云端开发,更多契机场景
未来已来,云端开发,是一种抽象但具有价值性落地的基础建设。在有AI可见的年限中,有着更多无限可能。比如,AI+云端开发=Code Interpreter 或者是 AI的Cloud Development Environment,或者更多更高的场景。
我们将 Cloud Studio IDE 视为 云端开发环境的一种产品实现。我们的目标是使企业级工程师的远程开发完全无缝。我们正在致力提升:
>>秒级的弹性分配容器
我们希望通过监控判断较慢的地方,比如消除异步状态,提升预热命中率等一系列手段,致力于将分配并启动开发空间减少到 3 秒以内。
>>短暂的开发容器
当解决并提升到启动的极致之后,我们希望从开发人员可以讲Cloud Studio 作为构建集成。我们预见了短暂的 Devpod 的以下用例:
- Devpod 特定于功能开发
- 简单快速的失败 CI 调试
- 随时可用的代码审查环境
- 分析移动崩溃
>>更省资源的云原生调试
云原生Mesh方案带来的流量劫持和染色,可以使得云原生基础架构下的开发调试和云端开发环境一起,爆发出企业级的新产品。
>>无中断自动升级和维护工作负载
目前,在非工作时间为环境设置了维护窗口,但是,一些工程师可能希望在非工作时间工作或在其环境中运行更长时间的工作负载。因此,可以通过监视活动连接和推迟维护工作负载来进行改进。
>>提升无缝的 IDE 体验
当工程师在笔记本电脑上本地使用 IDE 时,它应该在后台隐藏远程环境实现。IDE 会在后台静默连接到远程环境,并在有足够好的可用网络的情况下提供强大计算能力的所有好处——如果远程环境出现任何问题,它们不会被阻止,并且可以在本地无缝地继续工作。
>>特定团队的配置
我们正在寻找方法来最大程度地减少使用团队的首次设置的门槛。我们希望改进的领域之一是允许团队(代码化)自定义他们的配置,以便新的团队成员只需单击一下即可获得根据他们的需求量身定制的一致开发环境。
>>本地电脑和云端开发环境之间的无缝文件传输
我们尝试探索计算型开发的场景探索,譬如用于计算密集型任务和长时间运行的编译构建。在某些情况下,开发人员需要在他们的笔记本电脑和 Cloud Studio 云端开发环境 之间移动文件(反之亦然)。我们的目标是将 Cloud Studio CLI成为本地驱动器,自动安装到用户电脑上,从而可以无缝移动文件。
>>vGPU
我们正在尝试构建基于腾讯云 gpu-manager 的 vGPU 方案,这将可能帮助到以下开发需求:
- AI 模型训练
- GUI 跨平台客户端开发
- 游戏客户端开发
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。