Platform Engineering 实战:用 Backstage 构建内部开发者平台

2026-05-20 23:08 Platform Engineering 实战:用 Backstage 构建内部开发者平台已关闭评论

Platform Engineering 实战:用 Backstage 构建内部开发者平台

去年我花了两周时间在团队里搭了一套 Backstage,前后踩了无数坑,今天把整个过程和关键决策写下来。

先说结论:Backstage 不是开箱即用的产品,而是一个半成品框架。你得到的不是"开发者门户",而是一套可以拼成门户的乐高积木。 能不能搭好,取决于你对自己团队的开发者体验有多少理解。

为什么要搞平台工程

事情要从一次故障说起。

我们有个微服务项目,30 多个服务分布在 5 个 Git 仓库里,每个服务的 CI 流程、部署方式、监控面板都不一样。新同学 onboarding 需要看三天的文档才能搞清楚"上线一个新服务要走哪些流程"。

第 37 次被问"这个服务的 API 文档在哪"之后,我决定不再忍受了。

平台工程的核心命题很简单:把基础设施的复杂性封装起来,给开发者一条"黄金路径"。 Backstage 是 Spotify 开源出来的方案,也是目前社区最活跃的内部开发者门户框架。

选型:为什么是 Backstage

市面上做开发者门户的选择其实不多:

方案 类型 成本 定制性
Backstage 开源框架 部署+维护成本 极高
自研 全自建 极高 最高
商业方案(Portal等) SaaS 按量付费 受限于平台

我选 Backstage 的原因很简单:社区生态够活跃,插件机制够灵活。 当时它的 GitHub 星星已经快 3 万了,有 200+ 官方和社区插件,从 TechDocs 到 Kubernetes 到 CI/CD 都有现成的集成。

环境搭建:第一道坎

官方文档写得很美,实际跑起来是另外一回事。

安装脚手架

npx @backstage/create-app@latest --template backstage

这步看起来人畜无害,实际上它会从模板生成一个 monorepo,里面包含了 Frontend(React)、Backend(Express)、Client(API 请求层)三个包。第一次编译时 node_modules 能到 1.5GB。

编译命令:

cd my-backstage
yarn install
yarn dev

默认跑在 localhost:3000(前端)和 localhost:7007(后端)。

依赖地狱

第一次 yarn install 就挂了。报错信息指向某个 Python 包的编译失败——Backstage 用了 node-gyp,它依赖系统的 Python 和 C++ 编译器。

在 macOS 上我跑了:

xcode-select --install

在 Linux 上需要:

sudo apt-get install python3 g++ make

Windows 朋友……建议你先用 WSL2。

注意: Backstage 3.0+ 开始迁移到 New Frontend System,插件注册方式变了。如果你跟进最新版本,很多教程里的写法(用 createPlugin 注册路由)已经不适用。我建议新项目直接走新系统,老教程参考时要留个心眼。

核心概念:先搞懂这几个关键东西

在动手配置之前,必须先理解 Backstage 的几个核心抽象,不然你会一直感觉在"盲填配置"。

Entity(实体)

Backstage 里的万物皆实体。用一个 catalog-info.yaml 文件描述一个组件、API、资源或系统:

apiVersion: backstage.io/v1alpha1
kind: Component
metadata:
  name: user-service
  description: 用户中心服务
  annotations:
    github.com/project-slug: myorg/user-service
    backstage.io/techdocs-ref: dir:.
spec:
  type: service
  lifecycle: production
  owner: team-platform

这个文件放在每个服务的 Git 仓库根目录。Backstage 通过扫描这些文件来构建你的"目录"。

Catalog(目录)

所有实体的注册中心。可以理解成公司的"服务黄页"。支持从多个来源导入:GitHub、GitLab、LDAP、甚至 CSV 文件。

Scaffolder(脚手架)

这是 Backstage 最值钱的能力——用模板创建新服务

比如定义一个"标准 Go 微服务"模板,开发者点几个按钮,填个服务名,Backstage 就能在 GitHub 上创建仓库、初始化代码、配置 CI、注册到 Catalog,一气呵成。

TechDocs(技术文档)

把你仓库里的 Markdown 文档渲染成整洁的文档站点,支持代码高亮、Mermaid 图表、搜索。这功能单独拿出来都能当一个产品卖了。

Plugins(插件)

一切功能都是插件。Backstage 本身只是一个"空壳子",所有业务功能通过插件注入。

实战:搭一个最小可用门户

我的目标是:让团队能在 Backstage 上看到所有服务、找到每个服务的文档、用一个模板创建新服务。

第一步:配置 Catalog

Backstage 默认从自身的 examples 目录加载实体,显然这不够。我需要从 GitHub 组织拉取所有仓库的 catalog-info.yaml

编辑 app-config.yaml

catalog:
  import:
    entityFilename: catalog-info.yaml
    pullRequestBranchName: backstage-integration
  rules:
    - allow: [Component, System, API, Resource, Location]
  locations:
    # 扫描整个 GitHub 组织
    - type: github-discovery
      target: https://github.com/myorg/*
      rules:
        - allow: [Component]

第二步:接入 GitHub OAuth

要让用户登录才能看实体信息,我配置了 GitHub OAuth App:

auth:
  providers:
    github:
      development:
        clientId: ${AUTH_GITHUB_CLIENT_ID}
        clientSecret: ${AUTH_GITHUB_CLIENT_SECRET}

在生产环境还要配置 session 加密密钥:

curl https://backend:7007/api/auth/keys/generate
# 把返回的密钥写入环境变量

第三步:部署 TechDocs

TechDocs 需要额外的存储后端。我选的是最简单的方案——本地文件构建 + AWS S3 存储。

首先安装插件:

yarn --cwd packages/backend add @backstage/plugin-techdocs-backend

然后在 packages/backend/src/index.ts 注册:

backend.add(import('@backstage/plugin-techdocs-backend'));

注意: 生产环境中 TechDocs 的构建消耗很大。每个文档仓库会启动一个 Docker 容器来构建,建议至少给构建节点 4GB 内存。别问我怎么知道的——我第一次部署时直接把 2GB 的 ECS 打爆了。

第四步:创建 Scaffolder 模板

这是整个平台最花时间的部分,但也是收益最大的。

catalog/scaffolder-template.yaml 里定义一个模板:

apiVersion: scaffolder.backstage.io/v1beta3
kind: Template
metadata:
  name: go-microservice
  title: Go 微服务
  description: 创建一个标准 Go 微服务项目
spec:
  owner: team-platform
  type: service

  parameters:
    - title: 基础信息
      required:
        - serviceName
      properties:
        serviceName:
          title: 服务名
          type: string
          description: 建议用连字符命名,如 user-service
        servicePort:
          title: 端口
          type: number
          default: 8080

  steps:
    - id: fetch-template
      name: 拉取模板
      action: fetch:template
      input:
        url: ./templates/go-microservice
        values:
          serviceName: ${{ parameters.serviceName }}
          servicePort: ${{ parameters.servicePort }}

    - id: publish
      name: 推送到 GitHub
      action: publish:github
      input:
        allowedHosts: ['github.com']
        repoUrl: github.com?repo=${{ parameters.serviceName }}&owner=myorg
        description: 自动创建的微服务项目

    - id: register
      name: 注册到 Catalog
      action: catalog:register
      input:
        repoContentsUrl: ${{ steps['publish'].output.repoContentsUrl }}
        catalogInfoPath: '/catalog-info.yaml'

模板文件放在 templates/go-microservice/ 目录下,里面是 Go 项目的基础结构,加上必填的 catalog-info.yaml 和 README 模板。

踩坑实录

坑 1:插件版本不兼容

Backstage 的插件生态虽然丰富,但版本地狱很真实。

有次我升级了 Backstage 版本,结果 @backstage/plugin-catalog-graph 和当前核心库不兼容,Graph 页面直接白屏。排查了 3 小时才在 GitHub Issue 里找到线索——某个内部依赖改了接口签名,但类型声明文件没更新。

教训:每次升级时不要直接 yarn upgrade。走官方提供的升级脚本:

yarn backstage-cli versions:bump

它会帮你处理版本对齐,虽然有时候也会翻车,但至少比手动升级靠谱。

坑 2:TechDocs 构建环境不一致

本地构建文档一切正常,上了 CI 就炸。原因是 TechDocs 的构建容器需要访问公司内部的 npm registry(@scope/packages),但 Docker 容器里没有配置 npm registry。

解决方案是在 app-config.yaml 里配置:

techdocs:
  builder: 'local'
  generators:
    techdocs: 'docker'
  containerImage: 'spotify/techdocs'
  preparers:
    techdocs: 'docker'

然后在 Docker 构建命令里注入环境变量。最后我把构建逻辑单独抽成了一个 GitHub Action,避免每次依赖环境。

坑 3:RBAC 权限配置复杂

Backstage 自带的权限系统很基础,要精细化权限控制得靠插件。

我用了 @backstage/plugin-permission-backend + @backstage/plugin-permission-common 来实现"每个团队只能看到自己的服务"。

配置示例:

import { createPermission } from '@backstage/plugin-permission-common';

export const serviceReadPermission = createPermission({
  name: 'service.read',
  attributes: { action: 'read' },
});

但这部分的文档写得比较松散,我至少看了 5 个 Issue 才搞清楚 permission policy 的正确写法。

上线后的效果

跑了一个月后我统计了几个数字:

  • Onboarding 时间:从 3 天降到 4 小时(新同学来了直接看 TechDocs,不用等人教)
  • 新服务创建时间:从小时级降到 10 分钟(Scaffolder 一键搞定)
  • 团队成员对基础设施的提问:下降了 70%(因为黄金路径把复杂度藏起来了)

当然也有不理想的:不是所有人都买账。 有些老炮开发者觉得"你们搞个 Portal 反而把流程搞复杂了,以前我直接 SSH 上机器改多快"。这类声音要正视但不需要完全迎合——平台工程的价值在于规模化后的效率,而不是让某一个人的操作少点几下鼠标。

延伸思考

  • 不要追求"大而全":我见过最离谱的 Backstage 配置接入了 20 多个插件,最终两个月后没人用了。从"解决一个具体问题"开始,比如先只做服务目录和文档,跑通了再加更多功能。
  • 平台工程是组织问题,不是技术问题:技术上把 Backstage 跑起来只需一天,真正难的是让团队接受"以后创建服务必须走模板"这个流程变革。这是文化和习惯的问题,工具只是载体。
  • 与现有工具的关系:Backstage 不是来替代 Jira、Confluence 或 GitLab 的,而是聚合它们的信息到一个入口。不要想着 All-in-One,那是违反事物发展规律的。

最后一句总结:Backstage 不会自动解决你的问题,但如果你清楚自己的开发者痛点在哪,它是一个非常好的"乐高底板"——剩下的,就是你看清痛点后一块一块往上拼积木的事。

你可能感兴趣的文章

来源:每日教程每日一例,深入学习实用技术教程,关注公众号TeachCourse
转载请注明出处: https://teachcourse.cn/4152.html ,谢谢支持!

资源分享

分类:Android 标签:
Rust 异步编程与 Tokio 运行时深度实战 Rust 异步编程与 Tokio 运行时
Python框架Flask开发接口详细介绍 Python框架Flask开发接口详细介
Android SDK “Error when loading the SDK” Android SDK “Error when
Android面试笔记六:租租车 Android面试笔记六:租租车

评论已关闭!