翻译自 7 Core Elements of an Internal Developer Platform 。与本文相比,译者团队用的工具是 Gitea, Backstage 和 Jenkins 。
深入理解构建可以让开发者能够自主工作的 IDP 所需的技术栈和参考架构。
构建内部开发者平台需要什么?有哪些工具和平台可以使其工作?这篇文章将讨论建立一个完全可操作的内部开发者平台所需的架构和工具。要查看设置平台的实际步骤,请观看此视频。
平台工程的首要目标是推动开发者的自主性。如果开发者需要数据库,则应该有一种机制来获取它,无论该人是数据库管理员还是 Node.js 开发者。如果开发者需要在 Kubernetes 中管理应用程序,那么这个人不需要花费数年时间试图了解 Kubernetes 的工作原理。所有这些操作都应该易于完成。
开发者应该能够通过定义简单的清单或使用 Web UI 来完成他们需要的东西。我们希望使所有开发者都能使用有助于他们获得所需内容的服务。专家(平台工程师)将在内部开发者门户中创建这些服务,用户将在其图形用户界面中或通过直接编写清单并将其推送到 git 来使用它们。
一个内部开发者平台需要几个组件才能完全运行。对于每个组件,我们将推荐一个工具,但它们可以用类似的工具替换。核心思想是描绘出构建该平台所需的功能:
- 一个控制平面:平台需要一个控制平面来负责管理所有资源,无论它们是在 Kubernetes 集群还是其他地方运行的应用程序,或者基础设施或服务是否在 Amazon Web Services (AWS)、Azure、Google Cloud 或其他任何地方。我们在这里推荐的工具是 Crossplane 。
- 一个控制平面接口:这将使每个人都能与控制平面交互,并在适当的抽象级别管理资源。我们在这里推荐的工具是 Crossplane Compositions 。
- Git:所需的状态将存储在 git 中,因此我们必须在组合中添加一个 GitOps 工具。它的工作是将我们放入 git 的任何内容与控制平面集群同步。我们在这里推荐的工具是Argo CD。
- 数据库和 schema 管理:鉴于这种状态是不可避免的,我们也需要数据库。这些数据库将由控制平面管理,但为了正常工作,我们还需要一种方法来管理这些数据库内的 schema 。我们在这里推荐的工具是 SchemaHero 。
- Secrets 管理器:对于我们无法存储在 git 中的任何 Secrets 信息,我们需要一种方法来管理 Secrets 管理器中的机密。这些 Secrets 可以位于任何 Secrets 管理器中。我们推荐的从中提取 Secrets 的工具是 External Secrets Operator(ESO)。
- 内部开发者门户/图形用户界面:如果用户不想将清单直接推送到 git,我们应该为他们提供一个用户界面,使他们能够查看正在运行的内容以及执行将创建新资源并将其存储在 git 中的进程。我们在这里推荐的工具是 Port 。
- CI/CD pipelines:最后,我们需要 pipelines 来执行一次性操作,例如基于模板创建新存储库、使用清单的新版本更改生成映像等。我们在这里推荐的工具是 GitHub Actions。
设置将需要一些额外的工具,但上面的列表是必须的。
下图显示了每个元素如何相互交互。在阅读本文时,您可以将其用作参考。
让我们检查设置中每个层的角色:
让我们来谈谈控制平面:我们需要一个单一的 API 作为入口点。这是内部开发者平台的主要交互点。反过来,它将管理各种资源,无论资源在何处。我们可以使用 Crossplane 及其 providers ,这使我们不仅可以管理 Kubernetes ,还可以管理 AWS, Google Cloud, Azure 或其他类型的资源。我们将使用 Kubectl 获取自定义资源定义(CRD),这些定义将在超大规模集群中创建部署、服务并管理数据库等。
然而,仅此还不足以构建一个完整的内部开发者平台。一个应用程序很容易由数十个资源组成。基础设施可能会复杂得多。最重要的是,所有这些底层资源的抽象层次对于不是 Kubernetes 、 AWS 或 Google Cloud 专家的人来说不够友好。我们需要更加用户友好的东西。
控制平面接口可以在 100% GitOps 时充当平台 API。不应将其与充当图形用户界面的内部开发者门户混淆。为此,我们可以使用 Crossplane Compositions 。
我们构建的平台的用户需要什么样的抽象级别?原则是,我们应该隐藏或抽象化用户在使用内部开发者平台时真正不关心的任何内容。例如,他们可能不关心子网或数据库存储。合适的抽象级别取决于平台的实际用途,并且会因组织之间的不同而异。您需要发现如何最好地为您的客户和组织中的其他人提供服务。
Crossplane Compositions 使我们能够创建抽象,从而简化不同类型应用程序的管理。接下来,我们可能不希望任何人直接与集群或控制平面交互。人们不应该直接向控制平面发送请求,而应该将他们想要的状态存储在 git 中。
不应允许通过直接与控制平面通信来更改资源状态,因为没有人会知道谁在何时更改了什么。相反,我们应该将所需的状态推送到 git 中,并选择性地通过 pull request 进行审查。如果我们将 GitOps 工具插入平台,则所需状态将与控制平面同步,进而将其转换为实际状态。
这是一种更安全的方法,因为它不允许直接访问控制平面,并且还会跟踪所需的状态。我建议使用 Argo CD 执行此操作,但 Flux 和其他解决方案也一样好。
数据库需要 Schema 。它们因应用程序而异。为了完成我们的内部开发者平台,我们需要解决如何管理 Schema 的问题,最好将其作为存储在 git 中的应用程序定义的一部分。有许多方法可以管理模式,但只有几种方法可以让我们以适合 git 模型的方式指定模式。复杂的是, GitOps 工具只能与 Kubernetes 资源一起工作,这意味着 Schema 也应定义为 Kubernetes 资源。这要求我们使用 CRD 扩展 Kubernetes API ,从而可以将 Schema 定义为 Kubernetes 资源。我推荐使用 SchemaHero 来实现此目的。
有些信息不应该存储在 git 中。在 git 中拥有 Secret 等机密信息很容易导致违规。相反,我们可能希望将它们存储在像 HashiCorp Vault 这样的 Secret 管理器中,或者由您使用的任何超大规模提供商提供的解决方案中。尽管如此,这些 Secret 仍需要到达控制平面,以便其中的进程可以使用外部 API 或访问服务(例如数据库)进行身份验证。我建议为此使用 External Secrets Operator(ESO)。
内部开发者平台需要一个用户界面来补充我们迄今为止建立的一切。这是内部开发者门户网站。它同时提供人员可以使用的服务目录,并允许人员与平台进行交互以管理资源。
以及开发者执行我们希望他们自主使用的操作的界面。具体来说,我们需要一种方法来初始化一个过程,该过程将为应用程序创建新的存储库、添加示例代码、为数据库和其他依赖项提供清单、创建 CICD 管道等。
对于此设置,我们从 Port 的 Kubernetes 目录模板开始。
然后,我们将添加两个与集群蓝图相关的附加蓝图,即后端应用和环境:
最后,我们需要 Pipelines 。它们是拼图的最后一块。
即使我们使用 GitOps 将实际状态同步到所需状态,我们也需要一次性操作的 Pipelines ,每次提交只应执行一次。这些可能是构建二进制文件、运行测试、构建和推送容器镜像等的步骤。
从用户(开发者)的角度来看,只需单击 Web UI 中的按钮,或者通过定义一个非常简单的清单并将其推送到 git 即可创建新应用程序。之后,可以使用同一接口来观察有关该应用程序和相应依赖项的所有相关信息。
然而,在幕后,流程如下。
- 用户与 Web UI(端口)或直接与 git 交互。在这种情况下,内部开发者门户的工作是触发将创建所有必要资源的操作。
- 创建所有相关资源是由 GitHub Actions 等 pipeline 完成的工作。反过来,它创建一个包含所有相关文件的新仓库,如源代码、管道、应用清单等。
- 通过将变更推送到应用程序仓库(无论是由于前面的操作还是后来对代码进行更改),会触发特定于应用程序的 pipeline(GitHub Actions),该 pipeline 至少会构建容器镜像,将其推送到镜像仓库,并更新管理仓库中的清单,该仓库由 Argo CD 或 Flux 等 GitOps 工具监视。
- GitOps 工具检测对管理存储库的更改,并将其与控制平面集群中的资源同步。
- 控制平面集群中的资源由相应的控制器(Crossplane)获取,后者反过来会创建应用程序资源(在其他 Kubernetes 集群中或作为 AWS Lambda、Azure Container Apps 或 Google Cloud Run 等超大规模服务)以及依赖资源,如数据库(自我管理或作为超大规模服务)。