HomeArchiveFeedShelf

Internal Developer Platform 简介

我的职场开始很晚,来了日本之后才开始上班,此前一直在自己创业。说来惭愧,业务的规模一直都没做到过很大,人最多的时候也就十来个人,所以也没有管理大规模软件工程团队的经验。这方面的知识一直是欠缺的。这次跳槽到新公司,终于搞清楚了 Internal Developer Platform 是怎么回事,这里做一个记录。以下称 IDP。

在我看来,IDP 的目的是为了在大规模(至少上百人)软件工程师团队协作的前提下持续交付可靠软件。我查了一下 internaldeveloperplatform.org,虽然有一些 out of the box 框架,但总的来说,各个公司在技术选型的时候,根据业务不同,都有自己的考量,因此几乎所有的 IDP 都是公司 infra 团队自建。也因此不去有 IDP 的公司打工的话确实很难搞清楚 IDP 到底是怎么回事,IDP 的好处有哪些,为什么要采用 IDP。

internaldeveloperplatform.org 说 IDP 有五个 Core Components,分别是 Application Configuration Management,Infrastructure Orchestration,Environment Management,Deployment Management,Role-Based Access Control。这样解释太枯燥了,下面我通过具体的例子来说明。为了方便理解,以及信息脱敏,我会做一定简化。

一个常见的 IDP 实现方式,是把应用代码、基础设施配置、部署配置和权限治理尽量收敛到统一的 GitOps 流程里。本文用 monorepo + Bazel + GitHub + Kubernetes + Argo CD 作为例子说明。

Monorepo

IDP 引入眼帘的第一个东西就是一个巨大的 monorepo,所有团队的所有项目的所有源码都放在这个 monorepo 里。由于过于巨大,不得不通过 bazel 来管理构建。这个 monorepo 里不光有软件源代码,还有 terraform 配置(即 Infrastructure as Code),k8s 配置,以及 github 的各种配置。bazel 是 google 开发的构建工具,专为超大规模 monorepo 而生,支持所有语言所有框架所有项目。

软件代码更新

alice 是团队 team0 的程序员,她的项目在 monorepo 下的 projects/foo 里。她完成了一个 feature,推到了 foo/feature-x 分支,提交了一个 pr。此时,为了保证交付代码的质量,infra 团队开发的 github actions 立即启动,自动跑 bazel 脚本,进行 lint,ci,编译检查等工作,如果这些任务中有哪怕一个失败,都无法合并,强迫 alice 好好写代码。

就算所有的 github actions 通过了,alice 自己也不能擅自合并代码。用 IDP 的都是大公司,大公司有自己的流程。在发起 pr 时,github 会自动要求 github organization teams,也就 team0 里的人来 code review。为什么 github 知道 foo 需要 team0 的人来 review?因为 monorepo 根目录下的 CODEOWNERS 配置了。

bob 在收到 github 的邮件通知后,点击了 approve 并留言 lgtm,这时 pr 就可以合并了。team0 里的任何人可以点击合并按钮。

合并到 main 分支之后,infra 团队开发的 github app 立即启动,检查是否需要打包新的 docker/OCI 镜像,如果需要则开始通过 bazel 打包。打包完成后自动推送到内部的 docker registry(比如 gcp 的 artifact registry),自动发起两个合并到 main 的 pr,修改 monorepo 里 infra/k8s/foo/xxx.yaml 中 k8s deployment 的 image tag. 为什么是两个,因为一个修改 dev/staging 环境里的 yaml,一个修改 prod 环境里的 yaml. 每个 pr 里都包含了这次镜像构建基于哪个 commit,方便追溯。

根据 CODEOWNERS 此时 github 会发邮件给 team0. alice 或者 bob 看到邮件后,可以点击 approve,并执行合并。他们可以点击,也可以不点击。可以只合并修改 dev/staging 环境的 pr,也可以合并修改 prod 环境的 pr,甚至可以什么都不合并。这都是他们团队自己的事情,infra 团队不干预。

如果修改 image tag 的 pr 被合并到了 main,argocd 会立刻同步,自动尝试完成部署。

依赖更新

infra 团队得知某个 npm 包被投毒,立即响应。得益于 monorepo 对所有依赖都进行统一管理,他们只需要更新 package.json,推送到 infra/update-x-deps,并合并到 main,过程与上面介绍的流程一样。main 更新后,由于 foo 依赖了这个 npm 包,前面提到的 github app 会自动对 foo 的镜像再次打包,并发送邮件给 team0 的人,alice 和 bob 负责点击合并,触发 argocd 部署。不光 foo,所有依赖了这个 npm 包的其他项目也会自动执行一样的流程。

infra 团队决定升级某个语言/框架的 OCI 镜像的基础依赖,比如 debian 版本,他们只需要更新 bazel 的配置,并再次执行上述流程。合并到 main 后,alice 和 bob 会收到通知,决定是否部署。

这样一来,基础依赖的维护可以完全交给安全运维团队,应用开发团队可以只专注于业务实现。

软件上新

team1 的 carol 需要创建新的项目 bar,并需要用到 pg 数据库。carol 需要:

  • 在 monorepo 的 projects 目录下新建项目目录,维护 bazel 需要用到 BUILD 文件
  • 在 monorepo 的 terraform 相关目录下创建 db 相关的文件
  • 在 monorepo 的 infra/k8s 目录下创建 bar 相关的 deployment,并输入 env。如果 env 是 secret,则需要通过 hashicorp vault 来进行管理
  • 在 monorepo 的 terraform 以及 infra/k8s 相关目录下创建域名相关的配置

准备好了这一切,carol 发起 pr,合并到 main。这些 pr 不一定全是 carol 来处理,infra 的人可能会协助 terraform 的部分。甚至在理想情况下,一个 webui (比如 backstage)可以封装以上 gitops,使得对于公司内部开发者来说,使用公司的 IDP 就像使用 SaaS 软件一样简单。

与上面类似,pr 发起后,github actions 会立刻执行 ci,bazel 脚本,lint 之类的检查工作。由于修改了 terraform,ci 还会检查 tf-plan. 如果以上任何一个 ci 失败,则无法合并。根据 CODEOWNERS,terraform 相关目录的改动需要 infra 团队的人 code review. 确保维护责任划分清晰。

软件访问限制

所有团队的所有软件都部署在一个 (dev/staging/prod) k8s 里,不同项目仅仅是 namespace 不同,因此理论上可以互相访问。但为了安全考虑,这种访问需要被默认禁止。monorepo 里 k8s 的部分可以定义一套 istio 规则,并允许各个团队在自己的 k8s 定义目录里进行覆盖。CODEOWNERS 里可以配置,类似的改动合并到 main 时,需要 infra 团队 code review

接口复用

有的软件是针对公司内部使用的,比如内部 SDK。这些 SDK 的服务器部署到 k8s 之后就有自己的集群内和外网访问地址。上面提到的 backstage 不光可以用于简化应用上新的流程,还能为团队内部人员提供清晰明了的内部文档以及架构简介,有效避免重复开发。

这其中最重要的就是 observability,dev/prod 集群内部往往有各种各样的 collector,转发到诸如 grafana cloud 这样的平台。

另一个重要的可能是内部的 SSO,公司内部可能会部署一个类似 keycloak 的 oidc provider,其他服务不需要再写任何注册登录,统一接入集群内的接口。

再看五个 Core Components

结合以上具体的例子,看看 IDP 是如何通过整合各种业界工具,解决以下问题的

Application Configuration Management

主要通过 k8s 的 env 配置来解决。secret 部分可以通过 hashicorp vault 来管理,但他们家真的挺贵的。我查了一下,还有 dotenvxenvsecrets 等候补方案。绝对不可将任何密钥直接引入项目源代码。

Infrastructure Orchestration

主要通过 terraform 和 k8s 的 resources requests/limits, node affinity 甚至 keda 等等来解决。

Environment Management

通过准备不同的 dev/staging/prod k8s 集群并通过 argocd 绑定到 monorepo 的不同部分来解决。

Deployment Management

通过 argocd 来解决。

Role-Based Access Control

代码变更治理主要通过 GitHub Teams、branch protection、rulesets、CODEOWNERS 和 required status checks 实现。运行时访问控制则通过 Kubernetes RBAC、namespace 隔离、service account、network policy 或 Istio AuthorizationPolicy 等机制实现。

结语

本文只是抛砖引玉,由于目前我不是 infra 团队的,只是 IDP 的一个用户,从外部视角结合自己的经验做了一些推断。为了信息脱敏也做了很多简化和改动,比如其实目前我打工的地方的 IDP 是没有 webui 的,但我认为真的应该有一个,让 coding agent 给 gitops 套个 web 壳应该很快。IDP 是业务强相关的,没有放诸四海皆准的标准。不同公司的不同组织架构,甚至办公室政治都会影响 IDP 最后的样子。

拿我自己的几个创业项目来说,由于我现在是 solopreneur,只需要对自己负责,因此我大大简化了 gitops,不需要任何的 review,我自己 review 自己也没有什么意义,反正我只需要对自己负责。只需要推送,立即触发 github action 自动跑 ci,ci 过了就打包,打包完了就自动更新 image tag,然后 argocd 自动部署。另外我也不需要使用 bazel 这样的大杀器,npm package 足够了,rust 和 python 项目也能套 npm script.

@2026-07-07 16:19