APC 技術ブログ

株式会社エーピーコミュニケーションズの技術ブログです。

株式会社 エーピーコミュニケーションズの技術ブログです。

Backstageの組み込みHealth Check機能

こんにちは。暑い中いかがお過ごしでしょうか。Platform Engineering進んでいますか? Backstage活用されていますか??
ご存知無い方のためにあらためて。BackstageはCNCFのプロジェクトの1つで、拡張性の高い開発者ポータルのOSSです。機能拡張などはPluginを追加導入することで実現します。

backstage.io

今回は 2024年7月17日に公開された Backstage v1.29 で追加された Backstage Health Service の触りをご紹介します。

Backstage Health Service

BackstageのようなWebアプリケーションを公開する際、サービスの死活をチェックするエンドポイントとして(liveness/readinessといった)Health checkを用意することが一般的です。

Backstageでは、たしかそうしたHealth checkを追加する仕組みだけ用意されていて公式のHealth check endpointまでは用意されていなかったように思います。

そうした中 v1.29 で追加されたのが Backstage Health Service です。Release Noteには次のように記載されています。

A new health service as been added to the new backend system. This service provides health check endpoints for the backend, and replaces createStatusCheckRouter from @backstage/backend-common.

The service helps implement the new /.backstage/health/v1/readiness and /.backstage/health/v1/liveness endpoints, which provide health checks for the entire backend instance.

You can read more about this new service and how to customize it in the Root Health Service documentation.

この機能はデフォルトで組み込まれます。
上記の通り liveness として/.backstage/health/v1/liveness 、readinessとして /.backstage/health/v1/readiness というパスで公開されています。以下のコードで endpoint のパスを指定している部分です。

import Router from 'express-promise-router';
import { Request, Response } from 'express';

export function createHealthRouter(options: { health: RootHealthService }) {
  const router = Router();

  router.get(
    '.backstage/health/v1/readiness',
    async (_request: Request, response: Response) => {
      const { status, payload } = await options.health.getReadiness();
      response.status(status).json(payload);
    },
  );

  router.get(
    '.backstage/health/v1/liveness',
    async (_request: Request, response: Response) => {
      const { status, payload } = await options.health.getLiveness();
      response.status(status).json(payload);
    },
  );

  return router;
}

そして、Health checkの実行内容は次のようになっています。

github.com

import {
  RootHealthService,
  RootLifecycleService,
  coreServices,
  createServiceFactory,
} from '@backstage/backend-plugin-api';

/** @internal */
export class DefaultRootHealthService implements RootHealthService {
  #isRunning = false;

  constructor(readonly options: { lifecycle: RootLifecycleService }) {
    options.lifecycle.addStartupHook(() => {
      this.#isRunning = true;
    });
    options.lifecycle.addShutdownHook(() => {
      this.#isRunning = false;
    });
  }

  async getLiveness(): Promise<{ status: number; payload?: any }> {
    return { status: 200, payload: { status: 'ok' } };
  }

  async getReadiness(): Promise<{ status: number; payload?: any }> {
    if (!this.#isRunning) {
      return {
        status: 503,
        payload: { message: 'Backend has not started yet', status: 'error' },
      };
    }

    return { status: 200, payload: { status: 'ok' } };
  }
}

調べてみると中身はそれほど難しいことをやっているわけではありませんでしたが、最初から用意されているというのが良いですね。

もちろんHealth Checkのカスタマイズも可能です。カスタマイズ方法は Backstageのドキュメントに記載されています。

backstage.io

もっと簡単に

今回は Backstageの Health Check Serviceをご紹介しました。実現すると本当に簡単なことですが、そうした小さなことがあらかじめ用意されているのとそうでないのとでは、のちのち大きな違いになってくるものと思います。こうした整備が Backstageの新Backend Systemへの移行で増えていっている気がします。どんどん使いやすくなるとよいですね。

それでもまだBackstageって面倒だよね・・・という方にはぜひこちらをご紹介させてください。

techblog.ap-com.co.jp

PlaTT はPlatform Engineeringを推進するに必要な各種サービスの集合体です。その中でBackstageを活用しますが、Backstageのメンテナンスは私達が行いますので、皆さんは利用するだけ。ぜひご検討ください。

それでは、また。

  翻译: