BackstageでInternal Developer Portalを構築する:ドキュメント・ツール・DevOpsワークフローを一元管理

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

Internal Developer Portalがチームに必要な理由

こんな場面を想像してみてください。新しい開発者がチームに加入した初日、決済サービスのAPIドキュメントを探し、通知マイクロサービスの担当チームを調べ、フロントエンドのCI/CDパイプラインを見つけ、デプロイ手順を把握しなければなりません。情報が一か所にまとまっていなければ、Slackで人に聞いたり、散在するWikiを掘り返したりして、数日を無駄にしてしまいます。

これがまさに、Internal Developer Portal(IDP)が解決しようとしている問題です。複数のサービスを抱えるチームでは、情報の見つけにくさが静かに生産性を蝕みます。APIオーナーを探すのに30分かかる開発者が20人いれば、毎週かなりのエンジニアリング時間が失われていくことになります。

BackstageはSpotifyが開発しCNCFに寄贈したオープンソースフレームワークです。サービスカタログの閲覧、ドキュメントの参照、パイプラインのトリガー、インフラ状況の確認、新しいサービスへのオンボーディングまで、あらゆる作業を1つの場所で行えるようにします。複数のツールを行き来する必要がなくなります。

このガイドでは、Backstageをローカルで動かすこと、最初のカタログエントリを登録すること、そしてポータルの健全性を保つための基本的な監視を設定することに絞って解説します。プラットフォームエンジニアリングの意義についての話は省き、セットアップに集中します。

インストール:Backstageをローカルで起動する

始める前に、以下がインストールされていることを確認してください:

  • Node.js 18以上(node -vで確認)
  • Yarn 1.22以上(yarn -vで確認)
  • Git
  • Docker(任意ですが、後でPostgreSQLを使う場合に必要)

新しいBackstageアプリを作成する

BackstageにはCLIのスキャフォールディングツールが付属しています。ターミナルで以下を実行します:

npx @backstage/create-app@latest

アプリ名を入力するよう求められます。my-developer-portalのような名前で問題ありません。CLIが2つのパッケージを含むモノレポを生成します:packages/app(ReactフロントエンD)とpackages/backend(Node.jsバックエンド)です。依存関係のダウンロードに約800MBかかります。

cd my-developer-portal
yarn install
yarn dev

1〜2分待ってからhttp://localhost:3000を開くと、サンプルカタログが読み込まれたBackstageのホーム画面が表示されます。

プロジェクト構造を理解する

生成されたプロジェクトで特に重要なのは以下の部分です:

my-developer-portal/
├── app-config.yaml          # メイン設定ファイル
├── app-config.local.yaml    # ローカル上書き設定(gitignore対象)
├── packages/
│   ├── app/                 # フロントエンド(React)
│   └── backend/             # バックエンド(Node.js + Express)
└── catalog-info.yaml        # 最初のカタログエントリ(サンプル)

データベース接続、インテグレーション、認証プロバイダー、カタログの場所など、ほぼすべての設定はapp-config.yamlに集約されています。このファイルは頻繁に編集することになります。

設定:サービスカタログをセットアップする

サービスカタログはBackstageの中核機能です。チームが所有するすべてのマイクロサービス、ライブラリ、Webサイト、APIがカタログのコンポーネントとして登録されます。実際のサービスを登録する方法を見ていきましょう。

サービス用のcatalog-info.yamlを作成する

実際のサービスリポジトリ(BackstageのリポジトリではなくPF)のルートにcatalog-info.yamlを作成します:

apiVersion: backstage.io/v1alpha1
kind: Component
metadata:
  name: payment-service
  description: チェックアウトフローの決済処理をすべて担当する
  annotations:
    github.com/project-slug: my-org/payment-service
    backstage.io/techdocs-ref: dir:.
  tags:
    - nodejs
    - payments
    - api
spec:
  type: service
  lifecycle: production
  owner: payments-team
  system: checkout
  providesApis:
    - payment-api

このファイルにより、Backstageはサービスのオーナー、ライフサイクルステージ(productionexperimentaldeprecated)、公開しているAPI、ドキュメントの場所をすべて把握できます。

コンポーネントをBackstageに登録する

http://localhost:3000でポータルを開き、CatalogRegister Existing Componentに進み、catalog-info.yamlのGitHubのRaw URLを貼り付けます:

https://github.com/my-org/payment-service/blob/main/catalog-info.yaml

Backstageはすぐにコンポーネントをインポートします。数秒以内にカタログに表示されます。

GitHubインテグレーションを接続する(自動検出用)

サービスを1つずつ手動で登録する方法は、10リポジトリを超えると現実的ではありません。Backstageを使えば、GitHub組織全体のcatalog-info.yamlファイルを自動検出できます。app-config.yamlを編集します:

integrations:
  github:
    - host: github.com
      token: ${GITHUB_TOKEN}

catalog:
  providers:
    github:
      my-org:
        organization: 'my-org'
        catalogPath: '/catalog-info.yaml'
        filters:
          branch: 'main'
        schedule:
          frequency: { minutes: 30 }
          timeout: { minutes: 3 }

起動前に環境変数を設定します:

export GITHUB_TOKEN=ghp_your_personal_access_token
yarn dev

これでBackstageは30分ごとにGitHub組織をクロールし、mainブランチにcatalog-info.yamlがあるリポジトリを自動的に取り込むようになります。トークンにはreporead:orgのスコープが必要です。どちらか一方でも欠けると、検出中に403エラーが発生します。

TechDocsを有効にする(ポータル内ドキュメント)

TechDocsを使うと、チームはコードと並べてMarkdownでドキュメントを書き、Backstage内で直接読めるようになります。外部のWikiは不要です。まずCLIツールをインストールします:

pip install mkdocs-techdocs-core

サービスリポジトリにmkdocs.ymlを作成します:

site_name: Payment Service
docs_dir: docs
nav:
  - ホーム: index.md
  - APIリファレンス: api.md
  - ランブック: runbooks.md

コンテンツを記述したdocs/index.mdを作成します。BackstageでサービスをクリックするとDocsタブが表示され、Markdownファイルがきちんとしたドキュメントサイトとしてレンダリングされます。このパターンを採用したチームでは、数週間以内に「ドキュメントはどこですか?」というSlackの質問が目に見えて減る傾向があります。

SQLiteからPostgreSQLに切り替える(本番環境向け)

デフォルトでは、BackstageはインメモリのSQLiteデータベースを使用します。再起動するたびにリセットされるため、ローカルでのテストには問題ありませんが、それ以上の用途には使えません。PostgreSQLに切り替えましょう:

docker run -d \
  --name backstage-db \
  -e POSTGRES_USER=backstage \
  -e POSTGRES_PASSWORD=secret \
  -e POSTGRES_DB=backstage \
  -p 5432:5432 \
  postgres:15

app-config.yamlを更新します:

backend:
  database:
    client: pg
    connection:
      host: localhost
      port: 5432
      user: backstage
      password: secret
      database: backstage

バックエンド用のPostgreSQLクライアントをインストールします:

yarn --cwd packages/backend add pg

動作確認と監視:ポータルの健全性を保つ

Backstageをデプロイして放置すると、誰も信頼しない陳腐化したポータルになりかねません。正常に動作していることを確認し、問題を早期に検知する方法を紹介します。

カタログAPIを直接確認する

BackstageはREST APIを公開しており、カタログの取り込みが正常に機能しているかクエリで確認できます:

# 登録されているすべてのコンポーネントを一覧表示
curl http://localhost:7007/api/catalog/entities?filter=kind=Component | jq '.[].metadata.name'

# 特定のコンポーネントを確認
curl http://localhost:7007/api/catalog/entities/by-name/component/default/payment-service | jq '.metadata'

ここにサービスが表示されれば、カタログバックエンドが正しく取り込んでいることを意味します。表示されない場合は、GitHubトークンに適切なスコープがあるか確認してください。

カタログ更新ログを監視する

GitHub自動検出が実行されると、Backstageは各更新サイクルをログに記録します。バックエンドのログで問題がないか確認しましょう:

yarn dev 2>&1 | grep -E '(catalog|error|warn)' | tail -f

正常な出力は[catalog] Processed 42 entitiesのような形式です。403エラーが繰り返し発生する場合、トークンの有効期限切れかrepoまたはread:orgスコープが不足しています。トークンを修正して再起動すれば、次の30分更新サイクルで反映されます。

ヘルスチェックエンドポイント

Backstageバックエンドは、任意のアップタイムモニターに組み込めるヘルスエンドポイントを公開しています:

curl http://localhost:7007/healthcheck
# 期待されるレスポンス: {"status":"ok"}

Kubernetesにデプロイする場合は、readinessProbeとして使用できます:

readinessProbe:
  httpGet:
    path: /healthcheck
    port: 7007
  initialDelaySeconds: 10
  periodSeconds: 15

TechDocsのレンダリングを確認する

TechDocsを有効にしたコンポーネントを登録した後、Docsタブをクリックします。白紙のページや「Documentation not found」というエラーが表示される場合は、ビルド中に問題が発生しています。ローカルでデバッグしましょう:

cd your-service-repo
techdocs-cli generate --no-docker --verbose
techdocs-cli serve

これでドキュメントをローカルでビルドしてプレビューできます。ほとんどの失敗はmkdocs.ymlの欠落、docs_dirパスの誤り、Markdownファイルの破損が原因です。ポータルに反映させる前にここで修正しておきましょう。

カタログカバレッジを追跡する

カタログカバレッジ——実際のサービスのうちcatalog-info.yamlが存在する割合——こそが、ポータルが実際に役立っているかを示す指標です。GitHub CLIで確認できます:

# 組織内のリポジトリ数を数える
gh repo list my-org --limit 200 --json name | jq length

# catalog-info.yamlがあるリポジトリ数を数える
gh search code 'catalog-info.yaml' --owner my-org --json repository | jq '[.[].repository.name] | unique | length'

目標は80%以上のカバレッジです。それを下回っているチームがギャップを最も速く埋める方法は、スプリントのDone定義にカタログエントリの追加を含めることです——新しいサービスは初日からcatalog-info.yamlとともにリリースします。

基本設定後のネクストステップ

カタログにデータが揃い、ドキュメントがレンダリングされるようになったら、次に取り組む価値の高い機能がいくつかあります:

  • ソフトウェアテンプレート——開発者がポータル上で直接新しいサービスをスキャフォールドできるようにします。チームの規約やセキュリティのデフォルト設定が最初から組み込まれた状態で始められます
  • 認証インテグレーション——GitHub SSOや社内のIDプロバイダーを接続し、別途Backstageアカウントを管理することなく既存の認証情報でログインできるようにします
  • カスタムプラグイン——BackstageにはKubernetes、PagerDuty、Grafana、Argo CDをカバーするプラグインエコシステムがあり、各サービスのカタログページに関連データを直接表示できます
  • スコアカード——ドキュメントの有無、ランブックの有無、セキュリティスキャンの合否などの成熟度基準を定義し、組織全体でどのサービスが基準を満たしているか追跡します

カタログに10個のサービスがしっかり登録されているだけで、Slackでの質問やコンテキストスイッチにかかる時間を大幅に削減できます。カバレッジが増えるほどポータルの価値は高まりますが、導入してもらうためには初日から役に立つ必要があります。始める段階では、量より質を優先しましょう。

Share: