土法炼钢兴趣小组的算法知识备份

【系统架构设计百科】平台工程:构建开发者自服务的内部平台

文章导航

分类入口
architecture
标签入口
#platform-engineering#Backstage#IDP#developer-experience#golden-path

目录

2022 年,Spotify 公开了一个数据:新工程师从入职到第一次将代码部署到生产环境,平均只需要不到一天。在同一年,Humanitec 对 1000 多家企业的调查显示,没有内部平台的公司里,这个过程的中位数是两周到一个月——主要时间花在了”找人问怎么配置 CI 流水线”“等待 Ops 团队开通 Kubernetes 命名空间”“搞清楚监控 dashboard 在哪里”这些事情上。

差距的根源不在于 Spotify 的工程师更优秀,而在于他们背后有一个叫做 Backstage 的内部开发者平台(Internal Developer Platform,IDP)。这个平台把基础设施的复杂性封装成自助服务,开发者不需要提工单、不需要等审批,直接在 Web 界面上点几下就能创建一个符合公司标准的微服务项目,包括代码仓库、CI/CD 流水线、Kubernetes 部署配置、监控告警规则——全部自动生成。

这就是平台工程(Platform Engineering)要解决的核心问题:在不牺牲标准化和安全合规的前提下,把基础设施的自助使用权交还给开发者

本文将从平台工程的定义出发,厘清平台团队与 SRE、DevOps 的职责边界,深入分析 Backstage 的插件架构,讨论 Golden Path 模板设计,拆解平台的核心能力和产品化思维,给出成熟度模型和衡量指标,最后通过工程案例展示平台工程的实际落地效果。

适用范围说明 本文讨论的 Backstage 特性基于 1.x 版本。平台工程的实践参考了 CNCF 平台白皮书(2023)和 Team Topologies 的团队拓扑模型。

上一篇 中我们讨论了多云与混合云架构的设计,平台工程是在多云基础设施之上为开发者提供统一抽象层的关键实践。


一、平台工程的定义与目标

平台工程(Platform Engineering)是一门设计和构建工具链与工作流的学科,目标是为云原生时代的软件工程团队提供自助服务能力。Gartner 在 2023 年将其列为十大战略技术趋势之一,预测到 2026 年 80% 的大型软件工程组织将建立平台工程团队。

1.1 内部开发者平台的定义

内部开发者平台(Internal Developer Platform,IDP)是平台工程的核心产出物。CNCF 平台白皮书给出的定义是:

IDP 是一组集成的工具和服务,为开发者提供自助式的基础设施和开发工作流管理能力,同时确保组织的标准化、安全性和合规性要求得到满足。

拆开来看,IDP 有三个关键词:

1.2 为什么需要平台工程

DevOps 运动的初衷是”你构建,你运维(You Build It, You Run It)“。但十年实践下来,一个现实问题浮出水面:认知负荷(Cognitive Load)过高

Team Topologies 的作者 Matthew Skelton 和 Manuel Pais 指出,开发者被迫掌握的工具链已经膨胀到了不合理的程度:

领域 开发者需要了解的工具
源码管理 Git、GitHub/GitLab、分支策略
构建 Maven/Gradle/npm/Go Modules、Docker
CI/CD Jenkins/GitHub Actions/ArgoCD
容器编排 Kubernetes、Helm/Kustomize
可观测性 Prometheus、Grafana、Jaeger、ELK
安全 Trivy、Snyk、OPA/Kyverno
云服务 AWS/GCP/Azure 各种托管服务

一个后端开发者要做的事情不再只是写业务代码,还要写 Dockerfile、Helm Chart、Terraform 配置、Prometheus 告警规则、GitHub Actions 工作流。Humanitec 2023 年的调查数据显示,开发者平均有 30% 的时间花在了基础设施相关的任务上,而不是业务逻辑。

平台工程的解法是引入一个抽象层:平台团队把基础设施的复杂性封装成标准化的服务接口,开发者只需要关心”我要一个 PostgreSQL 数据库”而不是”我要在 AWS 上创建一个 RDS 实例,配置 VPC 子网、安全组、参数组、备份策略”。

1.3 IDP 的分层架构

一个典型的 IDP 包含五个层次:

graph TB
    subgraph "开发者界面层(Developer Portal)"
        A[Web UI / CLI]
        B[Software Catalog]
        C[Software Templates]
        D[TechDocs]
    end

    subgraph "平台 API 层(Platform API)"
        E[平台编排引擎]
        F[Golden Path 模板引擎]
        G[RBAC 权限控制]
    end

    subgraph "集成与交付层(Integration & Delivery)"
        H[CI/CD 流水线]
        I[GitOps 控制器]
        J[制品仓库]
    end

    subgraph "资源管理层(Resource Management)"
        K[Kubernetes 集群]
        L[数据库即服务]
        M[消息队列]
        N[缓存服务]
    end

    subgraph "基础设施层(Infrastructure Providers)"
        O[AWS]
        P[GCP]
        Q[Azure]
        R[私有数据中心]
    end

    A --> E
    B --> E
    C --> F
    D --> E
    E --> H
    E --> I
    F --> H
    G --> E
    H --> J
    I --> K
    J --> K
    K --> O
    K --> P
    K --> Q
    L --> O
    L --> P
    M --> O
    N --> R

这个分层的核心思想是关注点分离:开发者只和最上面的门户层交互,平台 API 层负责编排和权限控制,底层的基础设施细节被完全屏蔽。


二、平台团队 vs SRE vs DevOps 的职责边界

“平台团队和 SRE 有什么区别?”是被问得最多的问题之一。要回答这个问题,需要先搞清楚三个角色各自的起源和目标。

2.1 三者的定位

DevOps 是一种文化和实践,不是一个团队角色。它强调开发(Dev)和运维(Ops)的协作,核心理念是自动化、持续交付、快速反馈。DevOps 解决的是”开发和运维之间的墙”。

SRE(Site Reliability Engineering) 是 Google 提出的一种运维方法论。SRE 团队的核心职责是保障系统的可靠性,用软件工程的方法解决运维问题。SRE 有明确的量化目标:SLO(服务级别目标)、错误预算(Error Budget)。SRE 解决的是”系统如何保持可靠”。

平台团队(Platform Team) 是一种产品团队。它的”用户”是内部开发者,它的”产品”是 IDP。平台团队解决的是”开发者如何高效地使用基础设施”。

2.2 职责对比

维度 DevOps 工程师 SRE 平台工程师
核心目标 加速交付流程 保障系统可靠性 提升开发者生产力
服务对象 开发团队和运维团队 生产环境中的服务 内部开发者
关键指标 部署频率、变更前置时间 SLO 达成率、错误预算消耗 开发者满意度、平台采纳率
工作方式 嵌入业务团队或设立共享团队 On-call、事故响应、容量规划 产品管理、用户研究、平台开发
产出物 CI/CD 流水线、自动化脚本 SLO 仪表板、自动修复系统 开发者门户、自助服务 API
团队拓扑 赋能团队(Enabling Team) 复杂子系统团队 平台团队(Platform Team)

2.3 协作关系

在 Team Topologies 模型中,这三个角色的协作关系是:

实际组织中,SRE 和平台工程师的职责经常有重叠。小型组织可能由同一个团队同时承担两种角色。关键的区分点是:SRE 关注的是生产环境的可靠性,平台工程关注的是开发者的生产力。当一个团队同时承担两者时,往往是 SRE 的优先级更高(生产环境着火了必须先救),平台工程的需求被不断延后。这也是为什么 CNCF 建议在组织达到一定规模后(通常是 50 人以上的工程团队),将平台工程独立出来成为专职团队。


三、Backstage 深度剖析

Backstage 是 Spotify 在 2020 年开源的开发者门户平台,2022 年成为 CNCF 孵化项目。截至 2024 年,它已经被超过 2000 家公司采用,成为 IDP 领域事实上的标准。

3.1 核心架构

Backstage 采用插件化架构,由三大核心功能模块和一个可扩展的插件系统组成:

graph TB
    subgraph "Backstage 架构"
        subgraph "前端层(React SPA)"
            FP1[Frontend Plugin: Catalog]
            FP2[Frontend Plugin: TechDocs]
            FP3[Frontend Plugin: Scaffolder]
            FP4[Frontend Plugin: Kubernetes]
            FP5[Frontend Plugin: 自定义插件]
        end

        subgraph "后端层(Node.js)"
            BP1[Backend Plugin: Catalog]
            BP2[Backend Plugin: TechDocs]
            BP3[Backend Plugin: Scaffolder]
            BP4[Backend Plugin: Auth]
            BP5[Backend Plugin: Search]
            BP6[Backend Plugin: 自定义插件]
        end

        subgraph "数据层"
            DB[(PostgreSQL)]
            SC[Software Catalog<br/>catalog-info.yaml]
        end

        subgraph "外部集成"
            GH[GitHub / GitLab]
            K8S[Kubernetes API]
            CI[CI/CD 系统]
            MON[监控系统]
        end
    end

    FP1 --> BP1
    FP2 --> BP2
    FP3 --> BP3
    FP4 --> K8S
    BP1 --> DB
    BP1 --> GH
    BP2 --> GH
    BP3 --> GH
    BP3 --> CI
    BP4 --> GH
    BP5 --> DB
    BP1 --> SC

3.2 Software Catalog

Software Catalog 是 Backstage 的核心。它维护了组织内所有软件资产的注册表——服务、API、库、数据管道、基础设施组件。每个组件通过一个 catalog-info.yaml 文件向 Catalog 注册。

# catalog-info.yaml —— 服务注册描述文件
apiVersion: backstage.io/v1alpha1
kind: Component
metadata:
  name: order-service
  description: "订单核心服务,处理订单创建、支付和履约"
  annotations:
    github.com/project-slug: myorg/order-service
    backstage.io/techdocs-ref: dir:.
    prometheus.io/alert: order-service-alerts
    pagerduty.com/service-id: P1234567
  tags:
    - java
    - spring-boot
    - tier-1
  links:
    - url: https://grafana.internal/d/order-service
      title: Grafana Dashboard
      icon: dashboard
spec:
  type: service
  lifecycle: production
  owner: team-order
  system: commerce-platform
  providesApis:
    - order-api
  consumesApis:
    - inventory-api
    - payment-api
  dependsOn:
    - resource:order-database
    - resource:order-redis
---
apiVersion: backstage.io/v1alpha1
kind: API
metadata:
  name: order-api
  description: "订单服务 REST API"
spec:
  type: openapi
  lifecycle: production
  owner: team-order
  system: commerce-platform
  definition:
    $text: ./openapi.yaml
---
apiVersion: backstage.io/v1alpha1
kind: Resource
metadata:
  name: order-database
  description: "订单服务 PostgreSQL 数据库"
spec:
  type: database
  owner: team-order
  system: commerce-platform

Catalog 的价值在于它解决了大型组织中最常见的问题之一:没有人知道组织里到底有多少服务、每个服务是谁负责的、服务之间的依赖关系是什么。Spotify 内部有超过 2000 个微服务,没有 Catalog 之前,新员工找一个服务的负责人可能要花半天时间在 Slack 上问人。

3.3 Software Templates(Scaffolder)

Software Templates 是 Backstage 的”项目脚手架”功能。平台团队预定义一组模板,开发者在 Web 界面上填入几个参数,就能自动生成一个符合组织标准的新项目,包括代码仓库、CI/CD 配置、Kubernetes 部署清单、监控告警规则。

# template.yaml —— Backstage Software Template
apiVersion: scaffolder.backstage.io/v1beta3
kind: Template
metadata:
  name: springboot-service
  title: Spring Boot 微服务
  description: "创建一个标准化的 Spring Boot 微服务项目,包含 CI/CD、Kubernetes 部署、可观测性配置"
  tags:
    - java
    - spring-boot
    - recommended
spec:
  owner: platform-team
  type: service

  parameters:
    - title: 服务基本信息
      required:
        - serviceName
        - owner
        - description
      properties:
        serviceName:
          title: 服务名称
          type: string
          pattern: "^[a-z][a-z0-9-]*$"
          description: "小写字母开头,只允许小写字母、数字和连字符"
          ui:autofocus: true
        owner:
          title: 负责团队
          type: string
          ui:field: OwnerPicker
          ui:options:
            catalogFilter:
              kind: Group
        description:
          title: 服务描述
          type: string
          maxLength: 200

    - title: 技术选型
      properties:
        javaVersion:
          title: Java 版本
          type: string
          enum: ["17", "21"]
          default: "21"
        database:
          title: 数据库类型
          type: string
          enum: ["postgresql", "mysql", "none"]
          default: "postgresql"
        messaging:
          title: 消息队列
          type: string
          enum: ["kafka", "rabbitmq", "none"]
          default: "none"

    - title: 部署配置
      properties:
        namespace:
          title: Kubernetes 命名空间
          type: string
          default: "default"
        replicas:
          title: 初始副本数
          type: integer
          default: 2
          minimum: 1
          maximum: 10

  steps:
    - id: fetch-skeleton
      name: 拉取项目骨架
      action: fetch:template
      input:
        url: ./skeleton
        values:
          serviceName: ${{ parameters.serviceName }}
          owner: ${{ parameters.owner }}
          description: ${{ parameters.description }}
          javaVersion: ${{ parameters.javaVersion }}
          database: ${{ parameters.database }}
          messaging: ${{ parameters.messaging }}
          namespace: ${{ parameters.namespace }}
          replicas: ${{ parameters.replicas }}

    - id: create-repo
      name: 创建 GitHub 仓库
      action: publish:github
      input:
        allowedHosts: ["github.com"]
        repoUrl: "github.com?owner=myorg&repo=${{ parameters.serviceName }}"
        defaultBranch: main
        description: ${{ parameters.description }}
        protectDefaultBranch: true
        requireCodeOwnerReviews: true

    - id: create-argocd-app
      name: 注册 ArgoCD 应用
      action: argocd:create-resources
      input:
        appName: ${{ parameters.serviceName }}
        argoInstance: production
        namespace: ${{ parameters.namespace }}
        repoUrl: ${{ steps['create-repo'].output.remoteUrl }}
        path: deploy/k8s

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

  output:
    links:
      - title: 代码仓库
        url: ${{ steps['create-repo'].output.remoteUrl }}
      - title: 在 Catalog 中查看
        icon: catalog
        entityRef: ${{ steps['register-catalog'].output.entityRef }}

3.4 TechDocs

TechDocs 是 Backstage 的文档即代码(Docs-as-Code)功能。它基于 MkDocs,让每个服务的技术文档和代码放在同一个仓库里,通过 CI/CD 自动构建并发布到 Backstage 门户。

核心原则:文档在代码旁边,而不是在某个 Confluence 页面里。这解决了文档和代码脱节的长期痛点。

3.5 Backstage 插件开发

Backstage 的扩展性依赖于插件系统。每个插件分为前端插件(React 组件)和后端插件(Express 路由)。以下是一个简单的前端插件骨架:

// plugins/cost-dashboard/src/plugin.ts
import {
  createPlugin,
  createRoutableExtension,
} from '@backstage/core-plugin-api';

export const costDashboardPlugin = createPlugin({
  id: 'cost-dashboard',
  routes: {
    root: rootRouteRef,
  },
});

export const CostDashboardPage = costDashboardPlugin.provide(
  createRoutableExtension({
    name: 'CostDashboardPage',
    component: () =>
      import('./components/CostDashboardPage').then(
        m => m.CostDashboardPage,
      ),
    mountPoint: rootRouteRef,
  }),
);
// plugins/cost-dashboard/src/components/CostDashboardPage.tsx
import React from 'react';
import {
  Header,
  Page,
  Content,
  ContentHeader,
  SupportButton,
} from '@backstage/core-components';
import { useApi, configApiRef } from '@backstage/core-plugin-api';
import { CostTable } from './CostTable';
import { CostTrendChart } from './CostTrendChart';

export const CostDashboardPage = () => {
  const config = useApi(configApiRef);
  const backendUrl = config.getString('backend.baseUrl');

  return (
    <Page themeId="tool">
      <Header title="云资源成本看板" subtitle="按团队和服务查看云资源消费" />
      <Content>
        <ContentHeader title="月度成本概览">
          <SupportButton>
            成本数据每天从云账单 API 同步一次,延迟约 24 小时。
          </SupportButton>
        </ContentHeader>
        <CostTrendChart backendUrl={backendUrl} />
        <CostTable backendUrl={backendUrl} />
      </Content>
    </Page>
  );
};
// plugins/cost-dashboard-backend/src/router.ts
import { Router } from 'express';
import { Logger } from 'winston';
import { CostDataProvider } from './providers/CostDataProvider';

export interface RouterOptions {
  logger: Logger;
  costProvider: CostDataProvider;
}

export async function createRouter(
  options: RouterOptions,
): Promise<Router> {
  const { logger, costProvider } = options;
  const router = Router();

  router.get('/costs/summary', async (req, res) => {
    const { team, startDate, endDate } = req.query;
    logger.info(`Fetching cost summary for team=${team}`);
    try {
      const summary = await costProvider.getCostSummary({
        team: team as string,
        startDate: startDate as string,
        endDate: endDate as string,
      });
      res.json(summary);
    } catch (error) {
      logger.error('Failed to fetch cost summary', error);
      res.status(500).json({ error: 'Failed to fetch cost data' });
    }
  });

  router.get('/costs/by-service', async (req, res) => {
    const { team } = req.query;
    const breakdown = await costProvider.getCostByService(team as string);
    res.json(breakdown);
  });

  return router;
}

Backstage 的插件生态已经非常丰富,截至 2024 年,官方插件市场上有超过 150 个社区插件,覆盖 Kubernetes、ArgoCD、PagerDuty、SonarQube、Snyk、Datadog 等主流工具。


四、Golden Path 模板设计

Golden Path(黄金路径)是平台工程中最重要的概念之一。Spotify 将其定义为”经过平台团队验证和推荐的、完成某项任务的标准化方式”。

4.1 什么是 Golden Path

Golden Path 不是强制规定,而是推荐路径。它回答的是”如果你不知道怎么做,就按这个方式来”。

举几个例子:

4.2 标准化与灵活性的平衡

Golden Path 设计中最大的挑战是在标准化和灵活性之间取得平衡。过度标准化会让开发者觉得被限制,导致他们绕过平台;过度灵活则失去了平台的意义。

实践中,一种有效的策略是分层灵活性

层级 策略 示例
安全和合规层 强制执行,不可绕过 容器镜像必须通过安全扫描,生产环境必须启用 mTLS
基础设施层 标准化但可选配 默认使用 PostgreSQL,但也支持 MySQL;默认 3 副本,可调整为 1-10
应用框架层 推荐但不强制 推荐 Spring Boot,但也可以用 Go 或 Node.js 自建项目
业务逻辑层 完全自由 开发者自主决定代码结构、设计模式

4.3 模板的版本管理

Golden Path 模板不是一次性的产出物,它需要持续演进。模板本身应该像软件一样管理:

# Golden Path 模板的目录结构
golden-paths/
├── templates/
   ├── springboot-service/
   │   ├── template.yaml          # Backstage 模板定义
   │   ├── skeleton/              # 项目骨架代码
   │   │   ├── src/
   │   │   ├── deploy/
   │   │   │   ├── k8s/
   │   │   │   │   ├── deployment.yaml
   │   │   │   │   ├── service.yaml
   │   │   │   │   └── hpa.yaml
   │   │   ├── .github/
   │   │   │   └── workflows/
   │   │   │       └── ci.yaml
   │   │   ├── catalog-info.yaml
   │   │   └── mkdocs.yml
   │   ├── CHANGELOG.md
   │   └── test/                  # 模板的集成测试
   │       └── template_test.go
   ├── go-service/
   ├── python-data-pipeline/
   └── frontend-spa/
├── shared/                        # 跨模板共享的代码片段
   ├── ci-steps/
   ├── k8s-base/
   └── monitoring/
└── docs/
    └── template-authoring-guide.md

模板更新后,已经基于旧版模板创建的项目怎么办?这是一个常见的痛点。成熟的做法是提供模板升级工具(Template Upgrade Tool)——检测项目当前使用的模板版本,生成差异报告,提供一键升级或手动合并的选项。


五、平台的核心能力

一个成熟的 IDP 应该覆盖开发者日常工作中最高频的基础设施交互场景。

5.1 环境管理

开发者需要各种环境:本地开发环境、集成测试环境、预发布环境、生产环境。平台应该提供:

5.2 CI/CD 自助化

平台应该提供标准化的 CI/CD 流水线模板,开发者只需引用即可:

# .github/workflows/ci.yaml —— 基于平台提供的可复用工作流
name: CI/CD Pipeline

on:
  push:
    branches: [main]
  pull_request:
    branches: [main]

jobs:
  build-test-deploy:
    uses: myorg/platform-workflows/.github/workflows/standard-java-pipeline.yaml@v3
    with:
      java-version: "21"
      deploy-target: "kubernetes"
      namespace: "order-service"
    secrets: inherit

开发者不需要知道流水线的内部细节(如何做安全扫描、如何做镜像签名、如何做金丝雀发布),平台团队在可复用工作流中封装了所有这些步骤。

5.3 可观测性集成

平台应该让可观测性变成”零配置”或”低配置”的:

5.4 安全合规自动化

安全不应该是一个事后检查,而应该嵌入到平台的每个环节:

5.5 API 网关自助配置

开发者需要暴露 API 时,通过平台门户自助配置,而不是提工单给网关团队:

# api-gateway-config.yaml —— 开发者自助提交的网关配置
apiVersion: platform.myorg.io/v1
kind: APIRoute
metadata:
  name: order-api-v2
  namespace: order-service
spec:
  gateway: production-gateway
  host: api.myorg.com
  paths:
    - path: /api/v2/orders
      methods: [GET, POST]
      backend:
        service: order-service
        port: 8080
      rateLimit:
        requestsPerSecond: 100
        burstSize: 200
      authentication:
        type: jwt
        issuer: https://auth.myorg.com
      cors:
        allowedOrigins: ["https://app.myorg.com"]

平台在收到这个配置后,自动完成安全审查(通过预定义的 OPA 策略),然后将配置转换为实际的网关规则(如 Istio VirtualService 或 Kong Route)。


六、平台的产品化思维

平台工程与传统基础设施团队最根本的区别在于:平台团队把自己当成产品团队,把内部开发者当成用户

6.1 把开发者当用户

这意味着平台团队需要做产品团队做的所有事情:

6.2 衡量满意度

最直接的衡量方式是定期做开发者满意度调查。一个有效的框架是 SPACE 框架(由 Nicole Forsgren 等人提出):

维度 说明 示例指标
Satisfaction 满意度和幸福感 开发者对平台的 NPS 评分
Performance 产出质量 通过平台创建的服务的 SLO 达成率
Activity 活动量 每月通过平台创建的项目数、部署次数
Communication 协作效率 开发者提交支持请求到解决的平均时间
Efficiency 流程效率 新服务从创建到首次部署的时间

6.3 避免”强制推广”

平台最忌讳的就是发一封全员邮件说”从今天起所有团队必须使用新平台”。这几乎必然导致抵触情绪。

有效的推广策略是渐进式采纳

  1. 找到一两个痛点最大的团队,和他们深度合作,先解决他们的问题
  2. 用这些团队的成功故事做内部宣传
  3. 通过内部技术博客、Tech Talk 分享平台的使用方法和效果
  4. 提供迁移工具和迁移支持,降低存量项目的迁移成本
  5. 设定激励而非惩罚——比如”使用平台创建的项目享受更短的审批流程”

七、平台成熟度模型

平台工程不是一蹴而就的。CNCF 平台白皮书提出了一个四阶段的成熟度模型:

级别 阶段 特征 典型能力 团队规模参考
L1 临时脚本(Ad Hoc) 运维团队维护一堆自动化脚本,开发者通过提工单请求服务 Shell 脚本、Ansible Playbook、手动执行 10-30 人工程团队
L2 标准化工具链(Standardized) 统一了 CI/CD 工具和部署流程,但仍需运维人员操作 统一 Jenkins/GitHub Actions、标准化 Helm Chart、共享 Terraform 模块 30-80 人工程团队
L3 自助服务(Self-Service) 开发者可以通过 Web 门户或 CLI 自助完成大部分操作 Backstage 门户、Golden Path 模板、自助环境管理、自动化安全扫描 80-300 人工程团队
L4 可编程平台(Programmable) 平台提供完整的 API 层,开发者可以通过代码与平台交互,平台本身可扩展 平台 API、自定义插件、平台内部市场、平台即产品的完整运营体系 300+ 人工程团队

7.1 从 L1 到 L2:标准化阶段

这个阶段的核心任务是选型收敛。把散落在各团队的不同 CI/CD 工具、不同部署方式、不同监控方案收敛到统一的标准栈。

关键动作:

7.2 从 L2 到 L3:自助化阶段

这个阶段的核心任务是消除人工干预。开发者的常见操作不再需要提工单等审批。

关键动作:

7.3 从 L3 到 L4:平台即产品阶段

这个阶段的核心任务是开放扩展。平台不再只是平台团队的产出物,而是一个开放的生态系统。

关键动作:


八、衡量指标

平台工程的投入如何衡量回报?需要从三个维度来看。

8.1 DORA 指标

DORA(DevOps Research and Assessment)四个关键指标是衡量软件交付效能的行业标准:

指标 定义 平台工程的影响
部署频率(Deployment Frequency) 组织成功发布到生产环境的频率 Golden Path 和自助 CI/CD 降低部署门槛,提高频率
变更前置时间(Lead Time for Changes) 从代码提交到成功运行在生产环境的时间 标准化流水线缩短构建-测试-部署周期
变更失败率(Change Failure Rate) 导致生产环境降级或需要修复的变更百分比 Golden Path 内置安全扫描和合规检查,减少问题变更
服务恢复时间(Time to Restore Service) 从生产事故发生到恢复的时间 统一可观测性和自动化 Runbook 加速故障定位和恢复

8.2 开发者生产力指标

指标 计算方式 目标值参考
新服务上线时间(Time to First Deploy) 从决定创建新服务到首次部署的时间 小于 1 天
新员工入职时间(Developer Onboarding Time) 从入职到首次提交代码到生产的时间 小于 1 周
自助操作占比 开发者自助完成的操作占所有基础设施操作的百分比 大于 80%
工单等待时间 开发者提交基础设施相关工单到完成的平均时间 趋近于 0(理想状态是不需要工单)
认知负荷评分 通过调查问卷量化开发者对基础设施工具链的认知负荷 逐季度下降

8.3 平台采纳率指标

指标 说明
模板使用率 新项目中使用 Golden Path 模板创建的比例
Catalog 覆盖率 组织中注册到 Software Catalog 的服务占所有服务的比例
平台 DAU/MAU 开发者门户的日活/月活用户数
插件贡献数 非平台团队贡献的插件数量
开发者 NPS 通过调查问卷收集的净推荐值

九、构建还是购买:平台组件的选型决策

平台团队面临的一个关键决策是:每个组件应该自建还是使用现成的产品?

9.1 Build vs Buy 决策表

组件 自建(Build) 购买/采用(Buy/Adopt) 建议
开发者门户 自研 Portal(React/Vue) Backstage、Port、Cortex 推荐 Backstage:开源免费,插件生态成熟,社区活跃;自研门户初期简单,但长期维护成本极高
CI/CD 流水线 自研编排引擎 GitHub Actions、GitLab CI、Tekton 推荐采用:CI/CD 是已经高度成熟的领域,自研几乎没有差异化价值
基础设施编排 自研控制平面 Crossplane、Terraform、Pulumi 推荐 Crossplane:Kubernetes 原生,声明式 API,适合平台团队封装自助服务;Terraform 适合已有大量 HCL 资产的团队
服务目录 自研 CMDB Backstage Catalog、ServiceNow 推荐 Backstage Catalog:与开发者门户天然集成,catalog-info.yaml 可版本控制
可观测性 自研监控平台 Datadog、Grafana Stack(Prometheus+Loki+Tempo)、New Relic 推荐 Grafana Stack:开源可控,与 Kubernetes 生态深度集成;团队规模大且预算充足可选 Datadog
安全扫描 自研扫描引擎 Snyk、Trivy、Aqua Security 推荐 Trivy:开源免费,覆盖容器镜像和 IaC 扫描;企业需求可叠加 Snyk
密钥管理 自研密钥服务 HashiCorp Vault、AWS Secrets Manager 推荐采用:密钥管理涉及核心安全,自研风险极高
特性开关 自研开关服务 LaunchDarkly、Unleash、Flagsmith 视规模而定:小规模可用 Unleash(开源),大规模可选 LaunchDarkly

9.2 决策原则

  1. 核心差异化能力自建,通用能力外购:如果某个组件是你组织的核心竞争力(比如你是一家 DevOps 工具公司),可以自建;否则优先采用成熟方案。
  2. 评估长期维护成本:自建的初始开发成本可能不高,但长期维护成本(安全补丁、版本升级、文档维护、人员流失后的知识传承)往往是初始成本的 3-5 倍。
  3. 优先选择可替换的方案:采用开源方案优于商业方案,因为不存在厂商锁定风险。用抽象层封装外部依赖,确保可以替换底层实现。

十、工程案例:Mercado Libre 的平台工程实践

Mercado Libre(美客多)是拉丁美洲最大的电商平台,拥有超过 17000 名工程师和 20000 多个微服务。以下案例基于 Mercado Libre 在 PlatformCon 2023 的公开分享。

10.1 背景与挑战

2019 年,Mercado Libre 面临的问题:

10.2 平台建设过程

第一阶段(2019-2020):标准化

第二阶段(2020-2021):自助化

第三阶段(2021-2023):平台即产品

10.3 量化成果

指标 2019 年(平台建设前) 2023 年(平台成熟期) 改善幅度
新服务创建时间 2 周 5 分钟 99.97% 缩减
新员工首次部署时间 4 周 2 天 93% 缩减
部署频率 每周 2-3 次 / 团队 每天 5-10 次 / 团队 10-15 倍提升
配置错误导致的事故占比 35% 8% 77% 下降
开发者自助操作占比 15% 92% 6 倍提升
开发者 NPS +12 +58 +46 点

10.4 关键经验

Mercado Libre 团队总结了几条关键经验:

  1. 先解决痛点最大的问题:他们从”新服务创建太慢”这个痛点切入,而不是试图一次性构建完整平台。第一个版本的门户只有服务创建一个功能,但这个功能立刻赢得了开发者的认可。

  2. 平台团队需要产品经理:最初平台团队只有工程师,做出来的东西功能完备但用户体验差。引入产品经理后,开始系统性地收集需求、设计用户流程、做 A/B 测试。

  3. 数据驱动决策:每个平台功能上线前后都要度量关键指标。“新服务创建时间从 2 周缩短到 5 分钟”这个数据是说服管理层继续投入的最有力证据。

  4. 不要低估文档和培训的重要性:平台功能再好,如果开发者不知道怎么用,就等于不存在。Mercado Libre 为每个平台功能录制了视频教程,并定期举办 Platform Office Hours。


十一、平台工程的反模式

平台工程实践中有一些常见的反模式,值得警惕。

11.1 过度平台化(Over-Platforming)

症状:平台团队试图把所有东西都抽象成平台服务,包括一些只有两三个团队使用的长尾需求。

后果:平台变得臃肿复杂,维护成本飙升,开发者在平台门户上面对几十个选项不知道该选哪个。

解法:遵循 80/20 原则。平台应该覆盖 80% 的高频场景,剩下 20% 的长尾需求由业务团队自行解决。如果某个需求只有不到 3 个团队需要,先不要放进平台。

11.2 强制采纳(Forced Adoption)

症状:通过行政命令强制所有团队在某个截止日期前迁移到新平台,不留退路。

后果:开发者被迫在不了解新平台的情况下仓促迁移,产生大量问题和负面情绪。平台团队疲于应对支持请求,无暇改进产品。

解法:采纳应该是吸引而非强制。平台应该好到开发者愿意主动迁移。如果需要设定时间线,应该给予充分的迁移支持和缓冲期。

11.3 忽视用户反馈(Ignoring User Feedback)

症状:平台团队按照自己的技术判断决定做什么,不做用户研究,不收集反馈。

后果:平台做了一堆开发者不需要的功能,真正的痛点反而没有被解决。开发者对平台失去信任,开始绕过平台。

解法:建立系统化的反馈机制——定期用户访谈、每季度满意度调查、公开的 Feature Request 看板。平台团队的路线图应该有至少 50% 来自用户反馈。

11.4 技术镀金(Gold Plating)

症状:平台团队追求技术完美,在一个功能上花大量时间做优化和打磨,迟迟不发布。

后果:开发者等不到平台支持,自己造轮子,等平台终于发布时发现已经没人需要了。

解法:MVP 思维。先发布一个能用的版本(哪怕粗糙),快速收集反馈,迭代改进。平台的第一个版本可以是一个简单的 CLI 脚本,不需要一上来就做 Web 门户。

11.5 平台即瓶颈(Platform as Bottleneck)

症状:平台团队成了组织中的新瓶颈——所有基础设施变更都要经过平台团队审批,平台团队忙不过来,开发者还是在等。

后果:平台没有解决原来的问题,只是把瓶颈从运维团队转移到了平台团队。

解法:平台的目标是自助服务,不是集中管控。平台团队应该构建自助工具和自动化策略检查,而不是成为审批流程中的一个节点。如果某个操作需要人工审批,说明自动化程度还不够。


十二、什么时候该开始建内部平台

这是一个经常被问到的问题。答案不是”越早越好”也不是”等到问题大了再说”,而是取决于几个信号。

12.1 启动信号

当出现以下信号中的三个或以上时,就该认真考虑建内部平台了:

  1. 工单驱动的基础设施:开发者的大部分基础设施操作(创建服务、申请数据库、开通权限)都是通过工单系统完成的,平均等待时间超过 1 天
  2. 重复劳动:多个团队在重复解决相同的问题(配置 CI/CD、编写 Kubernetes 清单、搭建监控),但没有共享机制
  3. 入职时间过长:新员工从入职到首次部署需要超过 2 周
  4. 配置漂移:不同团队的部署方式差异很大,生产环境的配置不一致,排查问题时需要先搞清楚”这个团队是怎么部署的”
  5. 工程团队规模超过 50 人:小团队靠口头约定和文档就能维持一致性,大团队必须靠工具和自动化

12.2 起步建议

如果决定开始建平台,建议的起步路径:

// 伪代码:平台工程起步决策
func startPlatformEngineering(org Organization) PlatformPlan {
    // 第一步:识别最大痛点
    painPoints := survey(org.developers)
    topPain := painPoints.sortByFrequency().first()

    // 第二步:选择最小可行平台
    switch topPain {
    case "新服务创建太慢":
        return Plan{
            phase1: "创建 Backstage + 1 个 Golden Path 模板",
            timeline: "6-8 周",
            team: "2 名全栈工程师",
        }
    case "CI/CD 配置太复杂":
        return Plan{
            phase1: "创建可复用 CI/CD 工作流模板",
            timeline: "4-6 周",
            team: "1-2 名 DevOps 工程师",
        }
    case "不知道谁负责哪个服务":
        return Plan{
            phase1: "部署 Backstage Catalog,推动服务注册",
            timeline: "4 周",
            team: "1 名工程师 + 各团队配合",
        }
    default:
        return Plan{
            phase1: "从开发者调查开始,明确优先级",
            timeline: "2 周",
            team: "1 名工程师 + 1 名产品经理",
        }
    }
}

核心原则:从一个具体的痛点切入,用 6-8 周交付一个最小可行平台,用实际效果赢得信任,然后逐步扩展。不要试图在第一个版本中覆盖所有能力。


十三、平台工程的技术栈参考

以下是一个典型的 IDP 技术栈参考架构,适用于中大型组织:

层次 组件 推荐方案 替代方案
开发者门户 Web Portal Backstage Port、Cortex、自研
服务目录 Software Catalog Backstage Catalog ServiceNow CMDB
项目脚手架 Template Engine Backstage Scaffolder Cookiecutter、Yeoman
技术文档 Docs Platform Backstage TechDocs(MkDocs) Docusaurus、Confluence
源码管理 SCM GitHub GitLab、Bitbucket
CI/CD Pipeline GitHub Actions + ArgoCD GitLab CI + Flux
容器编排 Orchestration Kubernetes Nomad
基础设施编排 IaC Crossplane + Terraform Pulumi
可观测性-指标 Metrics Prometheus + Grafana Datadog
可观测性-日志 Logging Loki + Grafana Elasticsearch + Kibana
可观测性-追踪 Tracing Tempo + Grafana Jaeger
可观测性-采集 Collection OpenTelemetry Collector 各厂商 Agent
安全扫描 Security Trivy + Snyk Aqua、Prisma Cloud
策略引擎 Policy OPA / Kyverno Cedar
密钥管理 Secrets HashiCorp Vault AWS Secrets Manager
API 网关 Gateway Istio / Kong Envoy Gateway、APISIX
特性开关 Feature Flags Unleash LaunchDarkly、Flagsmith
成本管理 FinOps OpenCost + KubeCost CloudHealth、Spot.io

13.1 技术栈选型的关键考量

优先选择 CNCF 生态:CNCF 毕业和孵化项目经过了严格的评审,社区活跃度和长期维护有保障。Kubernetes、Prometheus、ArgoCD、OPA、OpenTelemetry 都是 CNCF 项目。

优先选择可组合的方案:不要选择大而全的一体化平台(All-in-One Platform),而是选择可以自由组合的独立组件。这样可以根据组织的具体需求灵活调整,避免厂商锁定。

评估团队的技术能力:Backstage 需要 TypeScript/React 技能来做定制开发。如果团队完全没有前端能力,可以考虑 Port 这种 SaaS 方案作为过渡。


十四、平台工程的未来趋势

14.1 平台即代码(Platform as Code)

越来越多的平台配置正在被代码化。开发者通过声明式的 YAML 或 CRD(Custom Resource Definition)描述自己需要的平台服务,平台控制面自动编排和交付。Crossplane 是这个方向的代表:

# 开发者声明式申请一个 PostgreSQL 数据库
apiVersion: database.platform.myorg.io/v1alpha1
kind: PostgreSQLInstance
metadata:
  name: order-db
  namespace: order-service
spec:
  parameters:
    storageGB: 50
    version: "15"
    highAvailability: true
    backupRetentionDays: 30
  compositionRef:
    name: aws-rds-postgresql
  writeConnectionSecretToRef:
    name: order-db-credentials

开发者不需要知道底层是 AWS RDS 还是 GCP Cloud SQL,平台通过 Composition 模式自动映射到具体的云服务商资源。

14.2 AI 辅助的平台工程

大语言模型(Large Language Model,LLM)正在改变平台工程的交互方式。未来的 IDP 可能不再需要开发者在 Web 表单上填写参数,而是通过自然语言对话完成操作:“帮我创建一个 Go 微服务,连接到 order 系统的 Kafka 集群,部署到 staging 环境”。

14.3 平台工程的组织演进

随着平台工程实践的成熟,组织结构也在演进。一些大型组织开始设立 Platform Product Manager 和 Platform UX Designer 角色,把平台团队从”几个写脚本的 DevOps 工程师”升级为”一个完整的产品团队”。


参考资料

书籍

报告 / 白皮书

会议演讲

论文 / 文章

文档 / 规范


上一篇:多云与混合云架构 下一篇:单体到微服务的演进

同主题继续阅读

把当前热点继续串成多页阅读,而不是停在单篇消费。

2026-04-13 · architecture

【系统架构设计百科】架构质量属性:不只是"高可用高性能"

需求评审时写下的'高可用、高性能、高并发',到了架构设计阶段几乎无法落地——因为它们不是可执行的需求。本文从 SEI/CMU 的质量属性理论出发,用 stimulus-response 场景模型把模糊需求变成可量化、可验证的架构约束,并拆解属性之间的冲突与联动关系。

2026-04-13 · architecture

【系统架构设计百科】告警策略:如何避免"狼来了"

大多数团队的告警系统都在制造噪声而不是传递信号。阈值告警看似直观,实则产生大量误报和漏报,值班工程师在凌晨三点被叫醒,却发现只是一次无害的毛刺。本文从告警疲劳的工业数据出发,拆解基于 SLO 的多窗口燃烧率告警算法,深入 Alertmanager 的路由、抑制与分组机制,结合 PagerDuty 的告警疲劳研究和真实工程案例,给出一套可落地的告警策略设计方法。

2026-04-13 · architecture

【系统架构设计百科】复杂性管理:架构的核心战场

系统复杂性是架构腐化的根源——本文从 Brooks 的本质复杂性与偶然复杂性划分出发,结合认知负荷理论与 Parnas 的信息隐藏原则,系统阐述复杂性的来源、度量与控制手段,并给出可操作的架构策略


By .