Skip to content

Platform Engineering 平台工程:IDP 内部开发者门户从 0 到 1 建设实战

2024 年初我们团队开始推行 Platform Engineering,目标只有一个:让开发者不需要找运维就能完成部署。半年后回头看,做对了三件事,踩了五个坑。这篇把过程和教训都摊开讲。

核心理念:平台是产品,不是工具

平台工程最核心的思维转变是:把平台当作产品来建设,把开发者当作用户来服务。

传统模式:开发者提需求 → 运维建环境 → 开发者部署 → 出问题找运维。全程人工、慢、易出错。

平台工程模式:开发者自己通过自助平台完成全部流程,运维只做平台能力的开发和迭代。

开发者视角                          运维视角
─────────────────────────────────────────────
我要部署一个服务                  我要提供部署能力
↓                                  ↓
打开 IDP 选择 golden path         设计并维护 golden path
填写必要参数                      参数校验 + 模板渲染
提交                              自动化构建 + 部署
等通知(5 分钟)                   等待平台反馈
                                (无需人工介入)

关键指标:平台成功的标准不是"建了多少功能",而是"开发者完成一次标准部署需要多少步、多长时间"。我们的目标是从 3 天(提工单 → 等审批 → 手动部署)降到 5 分钟(自助选择 → 自动部署)。

架构设计:三层模型

┌─────────────────────────────────────────────┐
│  Developer Experience Layer                 │
│  IDP (Backstage) + CLI + Web UI             │
├─────────────────────────────────────────────┤
│  Platform Capability Layer                  │
│  CI/CD Pipeline + GitOps + Secret Mgmt      │
├─────────────────────────────────────────────┐
│  Infrastructure Layer                       │
│  Kubernetes + DNS + Certificate + Registry  │
└─────────────────────────────────────────────┘

每一层的职责: - DevEx 层:统一的入口,开发者在这里感知到平台的存在 - 能力层:把基础设施能力封装成可复用的组件(CI/CD 模板、证书自动签发、DNS 自动配置) - 基础设施层:现有的 K8s 集群、CI/CD 系统、镜像仓库等

Golden Path 设计:三步走

Golden Path 是平台给开发者的"最简成功路径"——开发者不需要思考,照做就能部署。

第一步:服务模板

# template/service-template.yaml
apiVersion: backstage.io/v1alpha1
kind: Template
metadata:
  name: create-service
  description: 创建一个标准微服务
spec:
  parameters:
    - id: serviceName
      title: 服务名称
      description: 小写字母+数字,不含连字符
      type: string
      ui:validateField: /^[a-z0-9-]+$/
    - id: port
      title: 端口
      default: 8080
      type: number
    - id: replicas
      title: 副本数
      default: 2
      type: number
    - id: runtime
      title: 运行时
      type: string
      enum: [go, python, java, node]
      default: go
  steps:
    - id: render
      name: 渲染模板
      action: render:tmpl:v1
      input:
        url: ./template/service
        values:
          serviceName: ${{ parameters.serviceName }}
          port: ${{ parameters.port }}
    - id: push
      name: 推送代码
      action: github:create-pull-request:v4
      input:
        repo: myorg/${{ parameters.serviceName }}
        branch: platform/new-service

第二步:基础设施即代码

# infrastructure/k8s-base.yaml
apiVersion: argoproj.io/v1alpha1
kind: Application
metadata:
  name: ${{ parameters.serviceName }}
spec:
  destination:
    namespace: apps
    server: https://kubernetes.default.svc
  source:
    path: deployments/${{ parameters.serviceName }}
    repoURL: [email protected]:myorg/platform-infrastructure.git
    targetRevision: main
  syncPolicy:
    automated:
      prune: true
      selfHeal: true

踩坑:一开始我们用 Helm chart 做模板,结果每个团队都要学 Helm 语法。改成纯 YAML 模板 + 变量渲染后,学习曲线几乎归零。这个决策是团队投票的结果——大部分开发者不愿意学 Helm。

第三步:自动 DNS 和证书

# 部署成功后自动执行
# 1. DNS 自动注册(通过 ExternalDNS)
# 2. TLS 证书自动签发(通过 cert-manager)
# 3. 服务发现自动注入(通过 K8s Service)

# 开发者只需要:curl https://${serviceName}.example.com
# 不需要:申请 DNS、申请证书、配置 Ingress

Backstage 搭建:最小可用版本

# app-config.yaml
app:
  title: Internal Developer Portal
  baseUrl: https://idp.example.com

backend:
  auth:
    providers:
      oauth2:
        clientId: ${IDP_OAUTH_CLIENT_ID}
        clientSecret: ${IDP_OAUTH_CLIENT_SECRET}
        authorizationUrl: https://oauth.example.com/authorize
        tokenUrl: https://oauth.example.com/token

catalog:
  locations:
    - type: url
      target: https://github.com/myorg/catalog/blob/main/entities.yaml

integrations:
  github:
    - host: github.com
      token: ${GITHUB_TOKEN}
# entities.yaml
---
apiVersion: backstage.io/v1alpha1
kind: Component
metadata:
  name: user-service
  annotations:
    github.com/project-slug: myorg/user-service
    backstage.io/techdocs-ref: dir:.
spec:
  type: service
  lifecycle: production
  owner: platform-team
---
apiVersion: backstage.io/v1alpha1
kind: System
metadata:
  name: user-platform
spec:
  owner: platform-team

关键决策:Catalog 用 GitHub 托管(不用数据库),Entity 定义用 YAML(不用 JSON Schema)。这降低了维护成本,但牺牲了强类型校验——早期出现过不少 entity 格式错误,靠 GitHub PR review 解决了。

失败复盘:我们曾经搞砸过的地方

失败一:功能做了一堆,开发者不用

2024 年 Q1 我们花了两个月做了"服务迁移助手"——把老系统的服务迁移到新平台。功能齐全,文档完善,结果只有 2 个团队用了,剩下 15 个团队原地不动。

根因:我们站在运维视角想功能,而不是开发者视角。开发者真正需要的是:少改代码、少改配置、少开会。迁移助手解决的"运维的痛点"不是"开发者的痛点"。

修正:砍掉迁移助手,转而做"一键创建服务"——开发者想要的就是"别让我写部署配置"。

失败二:权限系统太复杂

原方案:RBAC + ABAC + 自定义 Policy Engine,三层权限控制。

# 权限策略(过于复杂)
apiVersion: iam.example.com/v1
kind: AccessPolicy
spec:
  subjects:
    - kind: Team
      name: user-service-team
  resources:
    - kind: Deployment
      name: user-service-*
  permissions:
    - get
    - list
    - create
    - update
    - delete
  conditions:
    - key: env
      op: in
      values: [staging, production]
    - key: time
      op: between
      values: ["09:00", "18:00"]

结果:开发者看不懂自己的权限,运维维护政策维护到崩溃。

修正:砍掉条件判断,简化为"按团队 + 环境"两层模型: - team-A → staging 全权限,production 只读 - team-B → staging + production 全权限(因为他们有 SRE oncall)

简单了很多,虽然不够细粒度,但可维护性大幅提升。

失败三:SLO 只监控平台,不监控开发者体验

我们最初定义了平台的 SLO: - API 可用性 99.9% - 部署成功率 99.5%

但开发者抱怨的还是多——因为部署成功率 99.5% 意味着每 200 次部署有 1 次失败,而失败的那次往往是最紧急的生产事故。

修正:加了"首次部署时间"和"部署后首次 P0 事故率"两个指标。这才真正反映了开发者体验。

度量:怎么判断平台做得好不好

指标 目标 采集方式
首次部署时间(从代码提交到线上) <10 分钟 CI/CD pipeline 日志
自助部署占比 >80% IDP audit log
平均等待时间(提工单 → 完成) <1 小时 工单系统统计
开发者满意度(季度调查) >4/5 问卷
平台功能使用率 >60% 平台埋点

我的判断:最重要的指标是"自助部署占比"。如果这个数字低于 50%,说明平台还没有真正解决问题,还需要继续迭代。

FAQ

Q:平台工程适合什么规模的团队?

阈值:团队超过 10 个、服务超过 20 个时,Platform Engineering 开始显现价值。少于这个规模,人工流程足够高效,建平台的 ROI 为负。我们团队 8 个人、5 个服务时试过,花了一个月搭建,结果没人用——直接砍了。

Q:平台团队和开发团队的关系怎么处理?

这是个组织问题,不是技术问题。最佳实践:平台团队是开发者的一部分,不是独立部门。每个平台功能都由"平台工程师 + 1-2 个开发者"组成 feature team 来开发,这样既懂平台又懂业务,做出来的东西才有人用。

Q:自建平台 vs 用 Backstage vs 买 SaaS?

  • 自建:适合有特殊合规要求(金融、政务)或深度定制需求的团队
  • Backstage:适合大多数中型团队,社区活跃、插件丰富
  • SaaS(如 Harness、CloudBees):适合不想维护平台本身的团队,但价格昂贵且锁定风险高

我们的建议:先从 Backstage 起步,遇到问题再决定是自研还是购买。