作者|Tiexin Guo
翻译|平台工程技术社区
链接|https://blog.gitguardian.com/platform-engineering-building-your-developer-portal-with-backstage-part-2/
在教程的第一部分,我们了解了用于构建开发人员门户网站的开源 CNCF 工具 Backstage,还创建了一个软件模板,用于为 GitHub 中的项目/源构建安全的软件组件。今天让我们继续我们的开发者门户,并将其提升到一个新的水平。
在教程的第一部分中,我们了解到 Backstage 由前端和后端两部分组成。如果您简单使用过您创建的门户,您会发现,一旦重新启动 yarn dev 服务器,之前导入的组件将不再存在。这是因为 Backstage 后端(及其插件,我们将在稍后讨论)需要一个逻辑数据库来存储其状态。
为简单起见,我们在教程的第一部分没有讨论数据库,但现在,让我们更改开发人员门户以使用数据库来持久存储其状态。
注意:Backstage 主要针对两个数据库进行测试:SQLite(主要用作内存模拟/测试数据库)和 PostgreSQL(首选生产数据库)。其他数据库(例如 MySQL 变体)可以工作,但尚未经过充分测试。
接下来,让我们配置后台以使用 PostgreSQL 数据库。
如果已经安装了 PostgreSQL 服务器并创建了模式和用户,则可以跳过这些说明。例如,如果运行在 Linux 服务器上,可以通过 apt-get 安装 PostgreSQL;或者,你可能在 Docker 容器甚至云数据库服务中运行 PostgreSQL。
下面的例子是针对 Mac 用户的;如果你不使用 Mac 进行开发,可以参考详细的安装 PostgreSQL [1] 说明,以便帮助你入门。
使用 brew 安装:
brew install postgresql@14
要让 launchd(brew 使用的进程管理器)立即启动 PostgreSQL 并在登录时重启,请运行:
brew services start postgresql@14
如果需要停止/重启,可以运行以下命令:
brew services stop postgresql@14
brew services restart postgresql@14
运行psql postgres
命令登录 Postgres shell,你会看到一个类似下面的欢迎交互式 CLI:
tiexin@mbp ~/work/my-portal $ psql postgres
psql (14.8 (Homebrew))
Type "help" for help.
postgres=#
在本教程中,我们将创建一个用户“backstage”,密码为“backstage”作为超级用户。请注意,这仅适用于本地开发,不适用于生产环境:
postgres=# create user backstage with encrypted password 'backstage';
CREATE ROLE
postgres=# alter role backstage with superuser;
ALTER ROLE
进入开发者门户目录根目录,使用以下命令开始安装 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
当后台完全启动后,现在添加一个新组件将把它保存到数据库中。以供测试:
使用教程第一部分中的模板来引导一个版本库;
重新启动 yarn 服务器;
进入软件目录,检查创建的组件是否还在(保存在数据库中)。
Backstage 是由一系列插件组成的单页面应用程序,通过这些插件可以实现各种功能,使您的开发人员门户更强大,以满足您的特定需求。请参见下面的结构图:
创建门户网站后,我们已经拥有了一些默认的核心功能,例如:
软件目录
软件模板
文档
搜索功能
实际上,这些默认/标准的核心功能都是由插件提供的,当我们启动开发人员门户网站时,Backstage 已经默认启用了这些功能。有了这些核心功能/插件,我们的开发人员门户已经相当强大,能够显示 CI/CD 状态和文档,并充当软件目录概览。有了插件,我们就能让开发人员门户网站更上一层楼。插件可以开源和重复使用,也可以针对企业的具体情况,为自己的特定需求创建定制插件。
目前,有许多插件,其中许多是 CI/CD 工具,如 Circle CI、Buildkite、Argo CD、Go CD 等,因此无论您使用的是哪种 CI/CD 工具链,都可以将它们与您的开发人员门户集成。
由于 Backstage 有前端和后端,因此您可以为前端和后端创建插件。
要创建前端插件,请确保已运行 yarn install 并安装了依赖项,然后在开发者门户根目录下的命令行上运行以下命令:
yarn new --select plugin
例如,我们可以将插件命名为 “my-plugin”。
这将根据提供的 ID 创建一个新的 Backstage 插件。它将自动生成并添加到 Backstage 前端应用程序中。
要开发前端插件,需要掌握一些 TypeScript 和 React 知识。不过,即使你不是 TypeScript/React 开发人员,也不难入门,因为上述命令用一些基本代码和模拟数据引导了一个示例插件。
例如,如果在启动 yarn dev 服务器后将插件命名为 “my-plugin”,则可以访问 http://localhost:3000/my-plugin
并查看结果。
还可以通过编辑packages/app/src/components/Root/Root.tsx
。文件对菜单/导航栏进行自定义。向下滚动到代码的Root部分:
export const Root = ({ children }: PropsWithChildren<{}>) => (
} to="/search">
}>
{/* Global nav, not org-specific */}
{/* End global nav */}
}
to="/settings"
>
{children}
);
在这里可以看到侧边栏页面,在该页面中,我们可以添加侧边栏项目、指定图标以及链接到哪个 URL。但是,如果我们深入研究生成的插件代码,在生成的文件的plugins/my-plugin/src/components/ExampleFetchComponent/ExampleFetchComponent.tsx
中,它返回的是模拟数据,而不是通过某个 API 获取的数据:
export const ExampleFetchComponent = () => {
const { value, loading, error } = useAsync(async (): Promise => {
// Would use fetch in a real world example
return exampleUsers.results;
}, []);
if (loading) {
return ;
} else if (error) {
return ;
}
return ;
};
在现实世界中,这里就是你调用一些 API 从后台获取数据并显示在你的插件中的地方。接下来,让我们快速了解一下后端插件。
在开发人员门户根目录下执行以下命令,即可创建一个新的后端插件包(与前端插件不同,后台插件包是空的,带有示例代码):
yarn new --select backend-plugin
同样,你将被要求为后端插件提供一个名称,就像我们在上一节中为前端插件所做的一样。值得注意的是,出于简单的开发目的,你可以在独立模式下启动后端插件:
cd plugins/plugin-name
yarn start
这将启动一个在 7007 端口监听的开发服务器,并直接附带一个健康检查端点,以便您进行检查:
curl localhost:7007/plugin-name/health
返回值应该是将{"status":"ok"}
。
不过,到目前为止,新创建的后端插件还不能正常使用。你需要编辑将src/service/router.ts
,开始添加路由,并将其连接到你要实现的实际底层功能。
值得注意的是,后端内置了 SQL 数据库访问功能,可以满足你的持久性需求,你还可以检索登录用户的身份,如果你想向不同的用户显示不同的数据,这就派上用场了。
到现在我们已经介绍了平台工程/开发人员门户、核心功能、数据持久性和插件(以及创建插件)的概念。我们已经掌握了所需的所有工具,可以构建自己特定的、定制的开发人员门户,以满足我们的需求。
接下来,我想讨论一下如何在生产环境中部署开发人员门户。
更快的方法是在 Docker 外部构建大部分内容,然后将包放入 Docker 镜像中,因此称为“主机构建”。这样做的好处是快捷,因为构建步骤在主机上执行得更快,并且可以在主机上更有效地缓存依赖项,其中单个更改不会破坏整个缓存。
要在主机上构建它,我们首先用yarn install
安装依赖项,然后用yarn tsc
生成类型定义,再用yarn build:backend
构建后端包。
此外,我们创建开发者门户时已经提供了一个 Dockerfile,位于packages/backend/Dockerfile
。我们可以使用这个 Docker 镜像来使用我们的主机构建包。
有时,你的 CI 运行在 Docker 中,所以主机构建的 docker-in-docker 方法可能不适合你;另外,也许你不想把基础架构当作宠物(而不是牲畜)来维护,所以你可能更喜欢在 Docker 中构建一切,尽管有时可能会比主机构建慢一些。
为此,我们需要使用 Docker 多阶段构建并创建自己的 Dockerfile。以下是每个阶段需要完成的工作:
第 1 步:创建 yarn 安装层。例如,git clone,然后将软件包和插件复制到该层。
第 2 步:安装依赖项并运行 yarn build。依赖包可能包括:libsqlite3-dev、python3、build-essential。这与主机构建部分类似。
第 3 阶段:与上一节中的 Docker 镜像相同,我们使用上一阶段构建的软件包构建实际的后端镜像。
在本教程的两个部分中,我们运行yarn dev时都只依赖 yarn dev 服务器,这条命令会启动两个服务器,一个为前端单页面应用服务,另一个为后端服务。无论是使用主机构建还是多阶段构建,docker 镜像都会将前端和后端构建到同一个 Docker 中。
在生产开发中,有时需要将前端与后端分开,要么使用单独的 Docker 镜像,要么使用带 CDN 的静态文件服务器(从技术上讲,CDN 也可以使用 Docker 容器作为源)。
为此,我们希望将前端与后端分开。例如,静态前端文件可以作为静态文件服务器在 AWS S3 中提供,然后在 S3 容器前使用 CloudFront 作为 CDN;对于后端,我们可以将其部署在 K8s 中的 Pod 中,并使用 Ingress 公开服务。
要分离前端,我们需要删除 packages/backend/src/plugins/app.ts
(并从packages/backend/src/index.ts
中删除相应的导入),并从 packages/backend/packages.json
中删除@backstage/plugin-app-backend
(它将前端从后端捆绑并提供服务,并将前端配置注入应用程序)。
现在,我们可以使用 Helm Chart 将后端镜像部署到 Kubernetes。这里[2]有一个社区 Helm Chart,通过设置值和传递你自己构建的 Docker 镜像,你可以将开发者门户部署到 Kubernetes 集群。
默认情况下,该 Helm Chart 不安装 PostgreSQL,因为在生产环境中,你很可能希望单独管理数据库。例如,如果你在云服务提供商中运行基础设施,你可以使用 Terraform 将数据库作为一项服务来管理,在为开发者门户运行 Helm 安装之前创建 PostgreSQL 数据库。
但是,上面的 Helm Chart 可以使用 PostgreSQL 作为 Helm Chart 依赖项,并在 K8s 中同时部署 DB 和门户,在这种情况下,你需要选择正确的 PersistentVolume 存储类型,比如云卷或网络附加存储,任何比 Kubernetes 节点的短暂存储更持久的存储。你还可以选择一个入口类,以便在内部或外部公开你的服务。
在本平台工程系列中,我们首先介绍了平台工程的概念以及平台工程与 DevOps 之间的区别。然后,我们通过实践教程介绍了构建开发人员门户的工具(Backstage),以及如何使用该工具创建开发人员门户、构建软件目录和创建软件模板。最后,我们学习了如何持久化开发人员门户的数据、如何为其添加更多功能以及如何将其部署到生产环境中。
除了我们提及的,还有很多其他事情可以完成,例如:
添加持续部署插件,例如,直接在开发者门户网站上显示 Argo CD 的部署历史和状态;
将 Kubernetes 集成到门户中,这样在每个组件中,你都能直接看到 K8s 中部署的应用程序,而无需运行一些 kubectl 命令或打开 K8s 面板;
添加更多功能,比如将秘密管理器作为插件集成到开发者门户,这样你就可以查看秘密列表、创建秘密,甚至显示每个组件中使用的秘密;
在门户网站中集成紧急服务计划及告警;
更多:您可以决定门户网站中的需求,构建插件并将其集成,这样门户网站就可以作为一个单一的地方查看所有内容,为开发人员团队增添价值。
希望您喜欢这个系列,也希望本教程对您有所帮助!
参考链接:
[1]https://www.postgresql.org/download/?ref=blog.gitguardian.com
[2]https://github.com/backstage/charts/tree/main/charts/backstage?ref=blog.gitguardian.com