饮墨

子安饮墨馀三斗,留与卿儿作赋来

Backstage 搭建内部开发者门户(IDP):从 0 到生产的落地实战

痛点

团队规模到了 50+ 工程师,微服务数量膨胀到上百个,典型混乱场景:

  • 新人入职找不到服务文档,不知道该服务归谁维护
  • 部署流程散落在 Wiki、Confluence、Slack 消息里,每个团队一套做法
  • 想创建一个新服务,需要手动配 CI/CD、K8s manifests、监控面板,耗时 2-3 天
  • 技术债务没人跟踪,安全漏洞修复进度不透明

这就是 Platform Engineering 要解决的问题——而 Backstage 是目前最成熟的开源 IDP(Internal Developer Platform)方案。

方案概述

Backstage 由 Spotify 开源,2022 年成为 CNCF Incubating 项目。核心能力:

功能模块 解决什么问题
Software Catalog 统一管理所有服务、库、API、基础设施的元数据
Software Templates 一键创建标准化新项目(脚手架)
TechDocs 代码即文档,Markdown 自动渲染为文档站
Plugins 生态 集成 Kubernetes、ArgoCD、PagerDuty、GitHub Actions 等 100+ 插件

架构简图:

Developer  Backstage UI  Backstage Backend  [Catalog YAML in Git]
                                               [Template Engine]
                                               [TechDocs Builder]
                                               [Plugin: K8s/ArgoCD/CI...]

实操步骤

第一步:快速部署 Backstage 实例

# 前置要求:Node.js 18+, yarn, PostgreSQL
npx @backstage/create-app@latest

# 进入项目目录
cd my-backstage-app

# 配置 PostgreSQL(app-config.production.yaml)
cat <<'EOF' >> app-config.production.yaml
backend:
  database:
    client: pg
    connection:
      host: ${POSTGRES_HOST}
      port: ${POSTGRES_PORT}
      user: ${POSTGRES_USER}
      password: ${POSTGRES_PASSWORD}
EOF

# 本地开发启动
yarn dev

启动后访问 http://localhost:3000,看到 Backstage 默认界面即成功。

第二步:注册服务到 Software Catalog

在你的服务仓库根目录创建 catalog-info.yaml

apiVersion: backstage.io/v1alpha1
kind: Component
metadata:
  name: payment-service
  description: 支付核心服务
  annotations:
    github.com/project-slug: myorg/payment-service
    backstage.io/techdocs-ref: dir:.
  tags:
    - python
    - grpc
spec:
  type: service
  lifecycle: production
  owner: team-payment
  system: payment-platform
  dependsOn:
    - resource:default/postgres-main
    - component:default/user-service
  providesApis:
    - payment-api

在 Backstage 的 app-config.yaml 中注册 catalog 来源:

catalog:
  locations:
    - type: url
      target: https://github.com/myorg/payment-service/blob/main/catalog-info.yaml
      rules:
        - allow: [Component, API, Resource, System]
  providers:
    github:
      myorg:
        organization: 'myorg'
        schedule:
          frequency: { minutes: 30 }
          timeout: { minutes: 3 }

这样 Backstage 会自动发现并索引所有带 catalog-info.yaml 的仓库。

第三步:创建 Software Template(黄金路径)

templates/ 目录创建一个标准微服务模板:

apiVersion: scaffolder.backstage.io/v1beta3
kind: Template
metadata:
  name: python-grpc-service
  title: Python gRPC 微服务
  description: 标准 Python gRPC 服务,内置 CI/CD + K8s 部署 + 监控
spec:
  owner: platform-team
  type: service
  parameters:
    - title: 基本信息
      required: [name, owner]
      properties:
        name:
          title: 服务名称
          type: string
          pattern: '^[a-z][a-z0-9-]*$'
        owner:
          title: 所属团队
          type: string
          ui:field: OwnerPicker
        description:
          title: 服务描述
          type: string
  steps:
    - id: fetch-template
      name: 拉取模板
      action: fetch:template
      input:
        url: ./skeleton
        values:
          name: ${{ parameters.name }}
          owner: ${{ parameters.owner }}
    - id: publish
      name: 创建 GitHub 仓库
      action: publish:github
      input:
        repoUrl: github.com?owner=myorg&repo=${{ parameters.name }}
        description: ${{ parameters.description }}
        defaultBranch: main
    - id: register
      name: 注册到 Catalog
      action: catalog:register
      input:
        repoContentsUrl: ${{ steps['publish'].output.repoContentsUrl }}
        catalogInfoPath: /catalog-info.yaml

工程师在 Backstage UI 点击 "Create" → 选择模板 → 填表 → 自动创建仓库 + CI/CD + 注册服务,全程 < 5 分钟。

第四步:生产级部署(Docker + Kubernetes)

# packages/backend/Dockerfile
FROM node:18-bookworm-slim

WORKDIR /app
COPY . .
RUN yarn install --frozen-lockfile && yarn tsc && yarn build:backend

CMD ["node", "packages/backend", "--config", "app-config.yaml", "--config", "app-config.production.yaml"]

Kubernetes 部署关键配置:

apiVersion: apps/v1
kind: Deployment
metadata:
  name: backstage
spec:
  replicas: 2
  template:
    spec:
      containers:
        - name: backstage
          image: myregistry/backstage:latest
          ports:
            - containerPort: 7007
          env:
            - name: POSTGRES_HOST
              valueFrom:
                secretKeyRef:
                  name: backstage-db
                  key: host
          resources:
            requests:
              memory: "512Mi"
              cpu: "250m"
            limits:
              memory: "1Gi"
              cpu: "1000m"
          readinessProbe:
            httpGet:
              path: /healthcheck
              port: 7007
            initialDelaySeconds: 30

避坑指南

1. Catalog YAML 维护成本高?用自动发现

不要手动逐个注册。配置 GitHub/GitLab Provider 自动扫描所有仓库的 catalog-info.yaml,加上 CI check 强制新仓库必须包含这个文件。

# .github/workflows/catalog-check.yml
- name: Check catalog-info.yaml exists
  run: |
    if [ ! -f catalog-info.yaml ]; then
      echo "::error::Missing catalog-info.yaml - 请参考 https://wiki/backstage-onboard"
      exit 1
    fi

2. 插件版本冲突导致构建失败

Backstage 采用 monorepo 结构,插件版本必须与 @backstage/core 对齐。使用官方升级工具:

# 批量升级所有 backstage 依赖到兼容版本
yarn backstage-cli versions:bump

建议锁定大版本,每月统一升级一次,不要频繁追最新。

3. TechDocs 构建慢、内存溢出

默认 TechDocs 在 Backstage 后端本地构建 MkDocs,服务多了会 OOM。改用外部构建 + 对象存储:

techdocs:
  builder: 'external'       # CI 中构建
  publisher:
    type: 'awsS3'
    awsS3:
      bucketName: backstage-techdocs
      region: us-east-1

在 CI pipeline 中加一步:

npx @techdocs/cli generate --source-dir . --output-dir ./site
npx @techdocs/cli publish --publisher-type awsS3 \
  --storage-name backstage-techdocs \
  --entity default/Component/payment-service

总结

Backstage 的核心价值不是"又一个管理平台",而是把散落各处的工程信息汇聚到一个入口,同时通过 Template 强制推行标准化。

落地建议:

  • 第一阶段(1-2 周):部署 Backstage + 接入 Software Catalog,先让大家"看见"所有服务
  • 第二阶段(3-4 周):建设 2-3 个核心 Template,覆盖最常见的新服务创建场景
  • 第三阶段(持续):接入 K8s 插件看 Pod 状态、接入 CI/CD 插件看构建结果、接入 PagerDuty 看 On-call

ROI 参考: Spotify 内部数据显示,Backstage 让新服务上线时间从数天缩短到 15 分钟,新人 onboarding 时间减少 55%。对于 50+ 人的工程团队,投入 1-2 个平台工程师维护 Backstage,通常 3 个月内回本。

关键一点:Backstage 是平台,不是产品——它需要你根据团队实际情况定制,不要期望开箱即用解决所有问题。先从 Catalog 开始,逐步迭代。

您还没有登录,请登录后发表评论。