写点什么

平台工程: 用 Backstage 构建开发者门户 - 2

作者:俞凡
  • 2024-02-04
    上海
  • 本文字数:5558 字

    阅读完需:约 18 分钟

本文介绍了如何使用开源 Backstage 构建自己的开发者门户,并基于此实践平台工程。本系列共两篇文章,这是第二篇。原文: Platform Engineering: Building Your Developer Portal with Backstage — Part 2



在本教程第一部分中我们了解了 Backstage 这个用于构建开发者门户的开源 CNCF 工具,还创建了一个软件模板,用于在 GitHub 中为引导项目/存储库构建默认安全的软件组件。


本文将继续开发这一开发者门户,并将其带到下一个层次。

1. 使用 PostgreSQL 数据库

1.1. Backstage 数据库

在本教程第一部分中,我们了解到 Backstage 由前端和后端两部分组成。


如果稍微用一下创建的门户,就会发现一旦重新启动 yarn dev 服务器,之前导入的组件将不再存在。


这是因为 Backstage 后端(及其插件)需要数据库来存储其状态。


注: Backstage 主要针对两个数据库进行了测试,分别是 SQLite(主要用作内存中的模拟/测试数据库)和 PostgreSQL(首选的生产数据库)。其他数据库,如 MySQL 之类,据说可以工作,但没有经过完整测试。


因此,接下来我们将配置 Backstage 使用 PostgreSQL 数据库。

1.2. 安装和配置 PostgreSQL

注: 如果已经安装了 PostgreSQL 服务器并创建了 schema 和用户,可以跳过这些说明。例如,你可能已经在 Linux 服务器上通过 apt-get 安装了 PostgreSQL,或者你可能在 Docker 容器甚至云数据库服务中运行 PostgreSQL。


下面的例子是针对 Mac 用户的。如果你不用 Mac 进行开发,PostgresSQL官网有关于如何安装 PostgreSQL 的详细说明。


使用 brew 安装:


brew install postgresql@14
复制代码


启动 PostgreSQL 并在登录时重新启动,运行:


brew services start postgresql@14
复制代码


如果需要停止/重启,可以执行如下命令:


brew services stop postgresql@14brew services restart postgresql@14
复制代码


运行psql postgres命令登录 Postgres shell,应该可以看到欢迎的交互式命令行,如下所示:


tiexin@mbp ~/work/my-portal $ psql postgrespsql (14.8 (Homebrew))Type “help” for help.
postgres=#
复制代码


在本教程中,我们将创建用户"backstage",密码为"backstage",作为超级用户。请注意,这只适用于本地开发,而不适用于生产:


postgres=# create user backstage with encrypted password ‘backstage’;CREATE ROLEpostgres=# alter role backstage with superuser;ALTER ROLE
复制代码
1.3. 配置 Backstage 使用 PostgreSQL

进入开发者门户目录的根目录,使用以下命令启动 PostgreSQL 客户端安装:


yarn add — cwd packages/backend pg
复制代码


然后再次打开配置文件app-config.yaml并更新backend.database部分:


backend:  database:    client: pg    connection:      host: 127.0.0.1      port: 5432      user: backstage      password: backstage
复制代码


注 1: PostgreSQL 的默认端口是 5432 或 5433,如果本地安装,主机名可以是 127.0.0.1。

注 2: 上面的示例使用了前一步中的连接细节。如果使用已存在的 PostgreSQL 数据库,请相应地更新主机/端口/用户/密码信息。

注 3: 一般来说,不建议在配置文件中使用连接详细信息,因为包含用户名和密码等敏感信息。对于生产环境,可以从环境变量中读取信息(使用 Helm chart 部署到 Kubernetes,并使用 Kubernetes secrets 存储这些敏感信息)。例如:


backend:  database:    client: pg    connection:      host: ${POSTGRES_HOST}      port: ${POSTGRES_PORT}      user: ${POSTGRES_USER}      password: ${POSTGRES_PASSWORD}
复制代码


更新配置后,可以启动开发者门户:


yarn dev
复制代码


当 Backstage 完全启动后,添加一个新组件并保存在数据库中,以供测试:


  • 使用教程第一部分中的模板来引导一个版本库;

  • 重新启动 yarn 服务器;

  • 进入软件目录,检查创建的组件是否仍然存在(持久化在 DB 中)。

2. Backstage 插件介绍

Backstage 是由一组插件组成的单页应用,通过插件实现的功能使开发者门户更强大,可以满足特定需求。请参见下面的架构图:



在创建门户之后,默认情况下已经有了一些核心功能,比如:


  • 软件目录

  • 软件模板

  • 文档

  • 搜索功能


实际上,这些默认/标准的核心功能都是由插件提供的,只是当我们启动开发者门户时,Backstage 已经默认启用了。


有了这些核心功能/插件,我们的开发者门户已经相当强大,能够显示 CI/CD 状态和文档,并浏览软件目录。不过,有了插件,就能让开发者门户网站更上一层楼。


插件可以是开源和可重用的,也可以是特定于某个公司的,甚至可以根据特定需求创建自定义插件,访问Backage官方网站可以获得所有现有插件的概述。目前已经有了相当多的插件,其中许多是 CI/CD 工具,如 Circle CI, Buildkite, Argo CD, Go CD 等,所以无论使用哪种 CI/CD 工具链,都可以将其集成到开发者门户中。

3. 创建插件

因为 Backstage 有前端和后端,可以为前端和后端创建插件。

3.1. 前端

要创建前端插件,确保已经运行了 yarn install 并安装了依赖项,然后在开发者门户目录的根目录下运行以下命令:


yarn new — select plugin
复制代码


例如,我们可以在这里将插件命名为"my-plugin"。


根据提供的 ID 创建新的 Backstage 插件,插件将自动生成并添加到 Backstage 前端应用程序中。


要开发前端插件,需要一些 TypeScript 和 React 的知识。然而,即使你不是 TypeScript/React 开发人员,也不难上手,因为上面的命令引导了一个带有基本代码和模拟数据的样例插件。


例如,如果你将插件命名为"my-plugin",在启动 yarn dev 服务器后,可以访问http://localhost:3000/my-plugin并查看结果。


可以对菜单/导航栏进行一些定制,也可以编辑packages/app/src/components/Root/Root.tsx实现定制,向下滚动到代码的Root部分:


export const Root = ({ children }: PropsWithChildren<{}>) => (  <SidebarPage>    <Sidebar>      <SidebarLogo />      <SidebarGroup label="Search" icon={<SearchIcon />} to="/search">        <SidebarSearchModal />      </SidebarGroup>      <SidebarDivider />      <SidebarGroup label="Menu" icon={<MenuIcon />}>        {/* Global nav, not org-specific */}        <SidebarItem icon={HomeIcon} to="catalog" text="Home" />        <SidebarItem icon={ExtensionIcon} to="api-docs" text="APIs" />        <SidebarItem icon={LibraryBooks} to="docs" text="Docs" />        <SidebarItem icon={CreateComponentIcon} to="create" text="Create..." />        {/* End global nav */}        <SidebarDivider />        <SidebarScrollWrapper>          <SidebarItem icon={MapIcon} to="tech-radar" text="Tech Radar" />        </SidebarScrollWrapper>      </SidebarGroup>      <SidebarSpace />      <SidebarDivider />      <SidebarGroup        label="Settings"        icon={<UserSettingsSignInAvatar />}        to="/settings"      >        <SidebarSettings />      </SidebarGroup>    </Sidebar>    {children}  </SidebarPage>);
复制代码


这里可以看到侧边栏页面,我们可以添加一个侧边栏项目,指定图标,以及应该链接到哪个 URI。


然而,如果我们更深入的研究生成的插件代码,在生成的文件plugins/my-plugin/src/components/ExampleFetchComponent/ExampleFetchComponent.tsx中,它返回模拟数据,而不是通过 API 获取的数据:


export const ExampleFetchComponent = () => {  const { value, loading, error } = useAsync(async (): Promise<User[]> => {    // Would use fetch in a real world example    return exampleUsers.results;  }, []);
if (loading) { return <Progress />; } else if (error) { return <ResponseErrorPanel error={error} />; }
return <DenseTable users={value || []} />;};
复制代码


在真实环境中,这里是调用 API 从后端获取数据以显示在插件中的地方。接下来,让我们快速浏览一下后端插件。

3.2. 后端

新的后端插件包(但是是空的,不像前端插件带有样例代码)可以通过在开发者门户根目录中执行以下命令来创建:


yarn new — select backend-plugin
复制代码


类似的,需要为后端插件提供一个名称,就像我们在前一节为前端插件所做的那样。


值得注意的是,为了简单的开发目的,可以在独立模式下启动后端插件:


cd plugins/plugin-nameyarn start
复制代码


这将启动一个监听 7007 端口的开发服务器,直接带有一个健康检查端点,这样你就可以:


curl localhost:7007/plugin-name/health
复制代码


这应该返回{"status":"ok"}


然而到目前为止,新创建的后端插件还没有做任何事情。你需要编辑src/service/router.ts添加路由,并将其连接到将要实现的实际底层功能。


值得注意的是,后端提供了用于 SQL 数据库访问的内置功能,以满足持久化需求,还可以检索登录用户的身份,如果希望向不同用户显示不同数据,这就能派上用场。

4. 生产部署

我们已经介绍了平台工程/开发者门户、核心特性、数据持久化和插件(以及创建它们)的概念。我们有所有工具,可以建立特定的、定制化的开发者门户,以满足我们的需求。


接下来,我想讨论一下在生产环境中部署开发者门户的问题。

4.1. 面向 Docker 的主机构建

更快的方法是在 Docker 之外构建大部分内容,然后将包放在 Docker 镜像中,因此称为"主机构建"。优点是这几乎总是更快的方法,因为构建步骤在主机上执行得更快,并且可以更有效缓存主机上的依赖项,其中单个更改不会破坏整个缓存。


为了在主机上构建,我们首先使用yarn install安装依赖项,然后用yarn tsc生成类型定义,然后使用yarn build:backend构建后端包。


在我们创建开发者门户时已经提供了 Dockerfile,位于packages/backend/Dockerfile,我们可以用这个 Docker 镜像来使用我们的主机构建包。

4.2. 多阶段构建

有时候,CI 运行在 Docker 中,因此主机构建的 docker-in-docker 方法可能不适合。另外,也许你不想像照顾宠物(而不是家畜)那样维护基础设施,所以实际上你可能更喜欢在 Docker 中构建所有内容,即使有时可能比主机构建慢。


为此,我们需要使用 Docker 多阶段构建并创建自己的 Dockerfile。以下是每个阶段需要做的事情:


  • 阶段 1: 创建 yarn 安装层,例如 git clone,然后将包和插件复制到该层。

  • 阶段 2: 安装依赖项并运行 yarn build。依赖项可能包括: libsqlite3-dev, python3, build-essential,与主机构建部分类似。

  • 阶段 3: 与上一节中的 Docker 镜像相同,使用上一阶段构建的包构建实际的后端镜像。


参考 Backstage 的多阶段 Docker 构建示例:https://backstage.io/docs/deployment/docker#multi-stage-build

4.3. 将前端与后端分离

在本教程中,当我们运行yarn dev时,只依赖于 yarn dev 服务器,并且这个命令启动两个服务器,一个服务于前端单页应用,另一个服务于后端。


无论是使用主机构建还是多阶段构建,docker 镜像都会将前端和后端构建到同一个 Docker 中。


你可能已经猜到我要干嘛了,对于生产开发,有时需要将前端与后端分开提供服务,要么从一个单独的 Docker 镜像,要么例如在带有 CDN 的静态文件服务器(技术上,CDN 也可以与 Docker 容器一起工作)。


为此,我们希望将前端与后端分开。例如,静态前端文件可以在 AWS S3 中作为静态文件服务器,然后在 S3 bucket 前使用 CloudFront 作为 CDN。对于后端,可以将其部署在 k8s Pod 中,并使用 Ingress 公开服务。


为了分离前端,需要删除packages/backend/src/plugins/app.ts(并从packages/backend/src/index.ts中删除相应的导入),并从packages/backend/packages.json中删除@backstage/plugin-app-backend(它为后端捆绑前端,为前端提供服务,并将前端配置注入到应用中)。

4.4. Kubernetes 部署

现在可以使用 Helm chart 将后端镜像部署到 Kubernetes。


Github 上有一个社区Helm charts,通过设置值并传递自己构建的 Docker 镜像,可以将开发者门户部署到 Kubernetes 集群。


默认情况下,这个 Helm charts 不安装 PostgreSQL,因为在生产环境中,很可能希望单独管理数据库。例如,如果在云服务提供商中运行基础设施,可以使用 Terraform 将数据库作为服务来管理,以便在为开发者门户运行 Helm install 之前创建 PostgreSQL 数据库。


但是,如果愿意的话,上面的 Helm charts 也可以使用 PostgreSQL 作为依赖项,并在 k8s 中同时部署数据库和门户,在这种情况下,需要选择正确的 PersistentVolume 存储类型,例如,作为云卷或网络附加存储(任何比 Kubernetes 节点的临时存储更持久的存储)。


你可能还希望选择 Igress 类,以便在内部或外部公开服务。

总结

在这个平台工程迷你系列中,首先介绍了平台工程的概念以及平台工程和 DevOps 之间的区别。然后,我们通过实践教程介绍了构建开发者门户的工具(Backstage),以及如何使用该工具创建开发者门户、构建软件目录和创建软件模板。最后学习了如何持久化保存开发者门户网站的数据、如何为其添加更多功能以及如何将其部署到生产环境中。


这只是一个开始,还可以做很多其他事情,例如:


  • 添加持续部署插件,例如,从 Argo CD 直接在开发者门户中显示部署历史和状态;

  • 将 Kubernetes 集成到门户中,这样在每个组件中,可以直接看到 k8s 中部署的应用,而无需运行 kubectl 命令或打开 k8s 仪表板;

  • 添加更多功能,比如将 secrets 管理器作为插件集成到开发者门户,这样就可以查看 secrets 列表,创建 secrets,甚至显示每个组件中使用的 secrets;

  • 将 7×24 支持的日程安排甚至警报集成到门户中;

  • 更重要的是: 可以决定在门户中需要什么,构建该插件并集成,以便可以作为查看所有内容的单一入口,为开发团队增加价值。




你好,我是俞凡,在 Motorola 做过研发,现在在 Mavenir 做技术工作,对通信、网络、后端架构、云原生、DevOps、CICD、区块链、AI 等技术始终保持着浓厚的兴趣,平时喜欢阅读、思考,相信持续学习、终身成长,欢迎一起交流学习。为了方便大家以后能第一时间看到文章,请朋友们关注公众号"DeepNoMind",并设个星标吧,如果能一键三连(转发、点赞、在看),则能给我带来更多的支持和动力,激励我持续写下去,和大家共同成长进步!

发布于: 刚刚阅读数: 5
用户头像

俞凡

关注

公众号:DeepNoMind 2017-10-18 加入

俞凡,Mavenir Systems研发总监,关注高可用架构、高性能服务、5G、人工智能、区块链、DevOps、Agile等。公众号:DeepNoMind

评论

发布
暂无评论
平台工程: 用Backstage构建开发者门户 - 2_平台工程_俞凡_InfoQ写作社区