Spotify Backstageによる内部開発者ポータルの構築:Software Catalog、TechDocs、プラットフォーム自動化

DevOps tutorial - IT technology blog
DevOps tutorial - IT technology blog

成長するエンジニアリング組織が直面するスプロール(肥大化)の課題

エンジニアリング組織が50人規模を超えると、マイクロサービスアーキテクチャは急速に複雑化しがちです。私たちの現場でも、マイクロサービスが80個を突破したあたりから深刻な運用摩擦が生じ始めました。

開発者は毎スプリント、単純な疑問の答えを探すために何時間も浪費していました。「auth-billing サービスのオーナーは誰か?」「決済 Webhook を担当している Slack チャンネルはどこか?」「gRPC のインターフェース定義(契約)はどこにあるのか?」新入社員のオンボーディングには丸2週間かかり、その大半はローカル環境のセットアップや IAM 権限の申請、あちこちに散らばったリポジトリのクローン作業に費やされていました。

この toil(雑務)のしわ寄せを最も受けたのが DevOps エンジニアでした。プラットフォームチームは、インフラの信頼性向上に注力する代わりに、スプリントの約30%をヘルプデスクのような対応に費やしていました。GitHub リポジトリの手動作成、Terraform のボイラープレートの整備、ステージングや本番クラスタへの Kubernetes デプロイマニフェストのコピペ作業に追われていたのです。その一方で、ドキュメントは放置された Confluence スペース、陳腐化した README、個人の Notion ワークスペースという3箇所に分散し、内容が矛盾していました。

こうした認知負荷を軽減するためには、すべての情報を一元化する「single pane of glass(統合ダッシュボード)」が必要でした。そこで大きな価値を発揮したのが Spotify Backstage です。2016年に Spotify が開発し、2020年に CNCF に寄贈された Backstage は、内部開発者ポータル(Internal Developer Portal: IDP)を構築するためのオープンソースフレームワークです。サービスのオーナーシップ管理、Docs-as-Code、プロジェクトのスキャフォールディング(雛形生成)を一元化されたハブに集約します。

Spotify Backstage の基本コンセプト

Backstage は、React フロントエンドと Express 上で動作する Node.js バックエンドで構成されています。既存のインフラツールを置き換えるのではなく、モジュール式プラグインを介して GitHub、GitLab、Kubernetes、SonarQube、ArgoCD などのツールとシームレスに連携します。システムの中核を成すのは以下の3つの柱です。

  • Software Catalog: サービス、ライブラリ、データベース、パイプラインを一元的に追跡する台帳。軽量な YAML ファイルを用い、ソースコード内でオーナーシップ、システムの境界、API の依存関係を直接宣言します。
  • TechDocs: Spotify が提唱する Docs-as-Code ソリューション。エンジニアはソースコードと同じリポジトリの /docs ディレクトリ配下に Markdown でドキュメントを記述します。Backstage は MkDocs を利用してポータル UI 内に検索可能な HTML ページをビルド・描画します。
  • Software Templates(Scaffolder): アーキテクチャ標準をセルフサービス型のフォームへと変換する自動化エンジン。開発者がいくつかの入力項目を入力するだけで、CI/CD パイプライン、リンター、監視設定があらかじめ組み込まれた検証済みのリポジトリが自動生成されます。

実践ハンズオン:Backstage のデプロイと設定

ステップ 1: Backstage インスタンスの初期化

Node.js(Active LTS バージョン 18 または 20)と Yarn がインストールされていることを確認してください。Backstage は Yarn ワークスペースに依存しているため、そのモノレポ構造を管理する上で npm の使用は推奨されません。公式のブートストラップコマンドを実行します。

npx @backstage/create-app@latest --skip-install
cd my-developer-portal
yarn install
yarn dev

フロントエンドは http://localhost:3000 で起動し、バックエンド API はポート 7007 でリクエストを処理します。ローカル開発ではインメモリの SQLite データベースが使用されますが、本番環境へのデプロイでは通常 PostgreSQL 14 以降に接続します。

ステップ 2: Software Catalog でコンポーネントを定義する

各サービスはコードを通じて自身のメタデータを公開します。サービスリポジトリのルートに catalog-info.yaml ファイルを追加します。

apiVersion: backstage.io/v1alpha1
kind: Component
metadata:
  name: payments-api
  description: StripeのWebhookを処理するコア決済オーケストレーションサービス
  annotations:
    github.com/project-slug: itfromzero/payments-api
    backstage.io/techdocs-ref: dir:.
  tags:
    - payments
    - go
    - grpc
spec:
  type: service
  lifecycle: production
  owner: group:payment-platform-team
  system: core-finance
  providesApis:
    - payments-grpc-api

このエンティティをポータルのグローバル設定ファイル(app-config.yaml)に登録します。

catalog:
  locations:
    - type: url
      target: https://github.com/itfromzero/payments-api/blob/main/catalog-info.yaml
      rules:
        - allow: [Component, System, API]

Backstage はこの場所を定期的にクロールしてエンティティを登録し、チーム間のサービス依存関係グラフを自動的にマッピングします。

ステップ 3: TechDocs(Docs-as-Code)の有効化

一元管理型の Wiki は、日々のプルリクエストから遠く離れた場所にあるため陳腐化しがちです。TechDocs は、技術ドキュメントをそれが説明するコードのすぐ隣に配置することでこの問題を解決します。リポジトリのルートに mkdocs.yml ファイルを作成します。

site_name: Payments API ドキュメント
plugins:
  - techdocs-core
nav:
  - 概要: index.md
  - アーキテクチャ: architecture.md
  - トラブルシューティング: troubleshooting.md

docs/ ディレクトリを作成し、その中に index.md ファイルを用意してガイドを執筆します。

# Payments API

Payments サービスの開発者向けドキュメントへようこそ。

## クイックスタート
Docker Compose を使用してローカルの依存関係を起動します:
```bash
docker-compose up -d redis postgres
go run cmd/server/main.go
```

エンジニアが Backstage 上で該当コンポーネントを開くと、プラットフォームは backstage.io/techdocs-ref アノテーションを検出し、バックグラウンドコンテナまたはビルドワーカーで MkDocs コンパイラを実行して、検索可能なドキュメントをポータル内に直接表示します。

ステップ 4: Software Templates によるゴールデンパスのスキャフォールディング自動化

セルフサービステンプレートは、Backstage が最も迅速に投資対効果を発揮できる機能です。インフラ申請チケットの DevOps によるレビューを何日も待つ代わりに、プロダクト開発者は Web フォームに入力するだけで済みます。テンプレートエンジンがパラメータをバリデーションし、スケルトンリポジトリを複製して変数を置換し、リモートの Git リポジトリを作成してデフォルトの CI/CD ワークフローを注入します。

以下は、実際に動作するテンプレート定義(template.yaml)の例です。

apiVersion: scaffolder.backstage.io/v1beta3
kind: Template
metadata:
  name: create-standard-microservice
  title: 標準 Node.js サービス
  description: DockerとGitHub Actionsを備えた本番環境対応のNode.js REST APIを自動生成します
spec:
  owner: group:platform-core
  type: service
  parameters:
    - title: サービス詳細
      required:
        - component_id
        - description
        - owner
      properties:
        component_id:
          title: サービス名
          type: string
          description: コンポーネントの一意なkebab-case名
        description:
          title: 説明
          type: string
        owner:
          title: オーナーチーム
          type: string
          ui:field: OwnerPicker
          ui:options:
            catalogFilter:
              kind: Group
    - title: リポジトリ設定
      required:
        - repoUrl
      properties:
        repoUrl:
          title: リポジトリの場所
          type: string
          ui:field: RepoUrlPicker
          ui:options:
            allowedHosts:
              - github.com
  steps:
    - id: fetch-base
      name: スケルトンの取得
      action: fetch:template
      input:
        url: ./skeleton
        values:
          component_id: ${{ parameters.component_id }}
          description: ${{ parameters.description }}
          owner: ${{ parameters.owner }}

    - id: publish-github
      name: GitHubへ公開
      action: publish:github
      input:
        allowedHosts: ['github.com']
        description: ${{ parameters.description }}
        repoUrl: ${{ parameters.repoUrl }}
        defaultBranch: main

    - id: register-catalog
      name: Software Catalogに登録
      action: catalog:register
      input:
        repoContentsUrl: ${{ steps['publish-github'].output.repoContentsUrl }}
        catalogInfoPath: '/catalog-info.yaml'
  output:
    links:
      - title: GitHubで開く
        url: ${{ steps['publish-github'].output.remoteUrl }}
      - title: カタログで表示
        icon: catalog
        entityRef: ${{ steps['register-catalog'].output.entityRef }}

テンプレートに対応する skeleton/ ディレクトリ内には、${{ values.component_id }} のような変数を含んだ定型ソースコードを配置します。実行時、Backstage はこれらのアクションを順次処理し、GitHub リポジトリを初期化して、新しいサービスを Software Catalog に即座に登録します。

私たちの本番環境では、このワークフローによってチーム間の調整を含めて約36時間かかっていたサービスプロビジョニング時間を、わずか8分に短縮しました。さらに、設定のドリフト(乖離)を根本から防止できるようになりました。新規リポジトリには、ヘルスチェックエンドポイント、Datadog によるトレーシング、脆弱性スキャナーがあらかじめ有効化された状態でプロビジョニングされます。

持続可能なプラットフォームマインドセットの確立

内部開発者ポータルの導入は単なるソフトウェアのインストールではなく、組織文化の変革です。Backstage を独自のロードマップを持つ社内プロダクトとして扱いましょう。プロダクトチームからのフィードバックを収集し、明確なカタログ所有権ルールを策定し、安全でコンプライアンスに準拠した選択肢が「最も進みやすい道」となるようなゴールデンパスを設計していくことが成功の鍵となります。

Share: