TT Lab
はじめる
学ぶ 学習パス コース

CBA — Backstage認定アソシエイト

プラグインの構造と運用 — ポータルを死なせないために

TT Labで続きを見る

一言でいうと

Backstageの拡張は、フロントエンドとバックエンドの2系統のプラグインでできていて、最近は新しいバックエンドシステム(new backend system)で、プラグインのインストールが大幅に簡単になりました。そして、運用で実際にぶつかるのは、華やかな機能ではなく、認証・身元の同期・カタログの処理周期・データベースです。

なぜ必要なのか

ポータルは、「インストールして終わり」にはなりません。接続するシステムが増えるほど、3つのことが問題になります。

  1. 誰が誰なのか: ログインした人が、カタログのどのUserエンティティで、どのGroupに属しているのか。これが合っていないと、「自分のサービス」の一覧が空になり、所有権に基づく機能がすべて無意味になります。
  2. 情報がどれだけ新鮮か: カタログがリポジトリをいつ再び読み取るのか。頻繁すぎるとAPIの上限に引っかかり、まばらすぎると、人々がポータルを信用しなくなります。
  3. 何が状態を持つのか: ポータルはステートレスのように見えますが、カタログとスキャフォルダーの作業履歴はデータベースにあります。

どう動くのか

プラグインの2系統と新しいバックエンドシステム

フロントエンドプラグイン バックエンドプラグイン
形 Reactコンポーネント Node.jsモジュール
提供するもの ルート、エンティティページのタブ・カード、ホームウィジェット HTTPエンドポイント、カタログのプロセッサー・エンティティプロバイダー、スキャフォルダーのアクション
認証情報 あってはいけません ここにあります

以前のバックエンドは、プラグインごとにルーターを手で配線し、依存関係を直接渡す必要がありました。新しいバックエンドシステムは、これをひっくり返し、バックエンドがプラグインとモジュール(module)を登録するだけで、必要なもの(ロガー、設定、データベース、認証、スケジューラーなど)を、依存性の注入で受け取るようにしました。結果として、インストールが「パッケージの追加 + 1行の登録」に減り、プラグイン間の拡張ポイントが明確になりました。CBAでは、この転換(旧バックエンド → 新しいバックエンドシステム)が問われます。

認証と身元の同期

2つを区別する必要があります。

ここに、組織データの収集が加わります。GitHub Org、LDAP、Microsoft Entraのような場所から、ユーザーとチームの一覧を定期的に読み取って、User/Groupエンティティとして入れることです。これができていてはじめて、spec.owner: group:team-checkoutが、実際の人の一覧につながります。

最もよくある導入の失敗が、ここで起きます。カタログにGroupがないのにオーナーとして参照すると、関係が切れたエンティティになり、「自分のサービス」ページが空だと、ユーザーは2回目の訪問をしません。所有権のグラフが埋まる前には、ポータルを公開しないほうがよいです。

Kubernetesプラグインの連結の輪

エンティティページでワークロードを見せる方式が、試験に出ます。

方向を混同しやすいです。エンティティはアノテーション、ワークロードはラベルです。ラベルの代わりにネームスペースで探させるbackstage.io/kubernetes-namespaceアノテーションもあります。そして、問い合わせはバックエンドが行うので、クラスターの認証情報はサーバーにだけあります。

運用: 処理周期とデータベース

カタログは、2つの段階でデータを作ります。

  1. エンティティプロバイダー(entity provider): どこに何があるかを発見して入れます(例: GitHub組織のスキャン)。
  2. プロセッサー(processor): その元のエンティティを読み取って検証し、関係を計算し、派生エンティティを作ります。

この処理は、定期的に繰り返されます。周期を短くすると鮮度は上がりますが、SCMのAPI呼び出しが増えて、上限(rate limit)に引っかかります。大規模では、Webhookやイベントですぐに更新し、周期自体は長くしておく組み合わせを使います。

データベースは、開発の便宜のためにSQLiteのインメモリで始められますが、再起動するとすべて消えます。運用ではPostgreSQLが事実上の標準で、カタログ・スキャフォルダーの作業履歴・検索インデックスがここに入ります。これは、ポータルがステートレスなアプリケーションではなく、バックアップと復旧の計画が必要だという意味です。

そして、忘れやすい運用項目が、アップグレードです。Backstageは活発に変化し、自分たちのアプリは、自分たちが所有するコードツリーです。数か月先延ばしにすると、あとでまとめて上げるコストが急激に大きくなります。定期的に少しずつ上げるのが、唯一の持続可能な方式です。

現場での姿

著者のホームラボには、CloudNativePGでPostgreSQL 18を、2インスタンスのストリーミングレプリケーションで動かした検証の記録があります。ポータルを載せるなら、そのデータベースが、そのままカタログの家になります。そして、このクラスターの最も痛い教訓が、ここにそのまま当てはまります。コントロールプレーン3台でetcdのクォーラムは揃えたのに、controlPlaneEndpointが最初のノードの物理IPなので、そのノードが落ちると、データは生きているのに、誰もAPIに接続できません。データの可用性とアクセスの可用性は別物です。

ポータルも、まったく同じです。カタログのデータベースを複製しておいても、ポータルのアプリが起動できなければ、誰も情報を得られません。逆に、ポータルが生きていても、カタログの処理周期が止まっていれば、画面の情報が静かに古くなります。後者のほうが危険です。障害は目に見えますが、古いデータは見えないからです。

もう1つあります。このクラスターで繰り返し確認された、状態がReadyであることと実際に動作することは別の命題だという点は、ポータル運用の核心となる感覚です。KubeVirtは、すべてのコンポーネントがAllComponentsReadyだったのに、VMが起動しませんでした。ポータルも、ヘルスチェックは緑なのに、カタログのプロセッサーが静かに失敗していることがあります。そのため、処理の成功率と最終更新時刻を、メトリクスとして見る必要があります。

次のクイズで確認すること

このモジュールは、クイズで締めくくります。前のモジュールのラボで作った、backstage.io/kubernetes-idのアノテーション(エンティティ)とラベル(ワークロード)の組を、もう一度確認してみると、プラグインが実際に何をするのかが、見えてきます。