APC 技術ブログ

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

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

Backstage Software Templateについてちょっと詳しくなろう

こんにちは!ACS事業部の田中です。

ここ最近、Platform Engineeringの話題を見聞きする機会が増えたように感じます。
それに伴いPlatform Engineeringで構築するIDP(Internal Developer Platform / Portal)の一つとして Backstage の名前を目にする機会も増えてきたのではないでしょうか。

BackstageはCNCFのプロジェクトの1つで、拡張性の高い開発者ポータルのOSSです。
以下のブログにて、Backstageの紹介をさせていただいています。 techblog.ap-com.co.jp

また他にも弊ブログにて話題に取り上げています。 techblog.ap-com.co.jp

さて、本日はそんなBackstageのコア機能のうち Software Template に注目して、概要から導入方法までを簡単に見ていこうと思います。

Backstageにおける Software Templateとは?

BackstageのTemplateは新しいコンポーネントやアプリケーションの開発プロセスを迅速かつ効率的に開始するための枠組みを提供する機能です。

backstage.io

例えば、新しいプログラムを開発する際にCI/CDパイプラインやフレームワーク固有の設定がなされた状態の初期Repositoryがさっと手に入る、そんなことが実現できます。

Backstageを起動した直後は、サンプルのテンプレートが一つ登録されています。
Templateは左ペインの Create... または <backstage URL>/create から利用することができます。

サンプルとして登録されているテンプレートでは、GUI上でBackstageで表示する名前とデプロイ先のGitHubを指定することで、指定したGitHub上にNode.jsのRepositoryが作成される流れを体感することができます。

BackstageへのTemplate追加方法

Templateは自分の利用する環境のものを用意してこそ真価を発揮するかと思います。
ここからは Templateの導入方法やTemplateの構造についてみていきたいと思います。

Templateは、Backstageのソフトウェアカタログのうち Template という種類に分類されており、ソフトウェアカタログに登録するTemplateは template.yaml ファイルにて定義されています。

Backstageのソフトウェアカタログ:

The Backstage Software Catalog is a centralized system that keeps track of ownership and metadata for all the software in your ecosystem (services, websites, libraries, data pipelines, etc).

https://backstage.io/docs/features/software-catalog/ より

この template.yaml をBackstageに取り込むことでBackstageにて該当のTemplateを使用できるようになります。

Backstageに登録するTemplate情報は主に以下2つの方法で取り込むことが可能です。

  • template.yaml ファイルのパスを app-config.yamlcatalog.locations セクションに記載する
  • <backstage URL>/catalog-importからImportする

ファイルパスを app-config.yaml に記載

<backstage URL>/catalog-importからImportする方法は、GUIの手順に従えばよいので、app-config.yaml に記載する方法について補足します。

app-config.yaml とは、Backstageの設定ファイルです。 以下のように記述することで template.yaml を取り込むことができます。

# app-config.yaml

... (中略) ...
catalog:
... (中略) ...
  rules:
    - allow: [Component, System, API, Resource, Location]
  locations:
    # Local template
    - type: file
      target: ../../examples/template/template.yaml
      rules:
        - allow: [Template]
    # Remote template
    - type: url
      target: https://github.com/xxx/yyy/blob/main/template.yaml
      rules:
        - allow: [Template]

Templateの指定方法は、type: file (ローカルファイルパス) と type: url (リモートファイルパス) の2種類があります。

type: local はローカルファイルからコンテンツを取り込むためのものであり、ローカルの開発やテスト、サンプルとしてのみ利用するべきものとされ、本番利用は推奨されていません。
したがって、type: url がTempalteを Static routeから取得する際の推奨される指定方法です。 同じ metadata.name を持つファイルが複数存在する場合は、1つのファイルのみが処理され残りはスキップされます。

補足:rules について

デフォルトでは、カタログに対してComponent, API, Location の取り込みのみ許可されているため、そのほかのエンティティを取り込むためには明示的に rules として取り込みを許可する必要があります。

rules は catalog.rules セクションに記載するか、各 Static locations セクションに記載する必要があります。

template.yaml と template構造

BackstageへのTemplate追加方法をみたところで、実際のTemplateの構造がどうなっているか気になってきたのではないでしょうか。

ここでは、T3 Stack を採用したアプリケーションをTemplateとして登録する例でtempalte.yaml と template構造についてみていきたいと思います。
Templateでは、サンプル同様指定したGitHub上に所定のデータ(以下でいうskeleton/配下)を含むRepositoryを作成します。

Templateは独立したRepositoryやフォルダを一つの単位としており、以下の形式を基本とします。

  • template.yaml: ソフトウェアカタログに登録するTemplateの定義ファイル Backstageで取り込む際に指定する
  • skeleton/ : Templateを利用した際に実際に展開される部分(任意の名前)
  • skeleton/catalog-info.yaml: Templateを利用して作成されたカタログがどのようにBackstage上に登録されるかを定義するエンティティファイル
.
├── (README.md)
├── skeleton
│   ├── catalog-info.yaml
│   ├── prisma
│   ├── public
│   ├── src
│   └── ... (その他のファイル) ...
└── template.yaml

それぞれ中身を見ていきましょう。

template.yaml

backstage.io

template.yaml にはTemplateのパラメータやカタログ作成時のふるまいを指定します。
template.yaml は 大きく、medadataspecs から構成されるます。Kind: Template

apiVersion: scaffolder.backstage.io/v1beta3
kind: Template
# Template自身のメタデータ、登録情報
metadata:
  name: create-t3-stack-template 
  title: Create T3 Stack Template
  description: Create a new website project
  tags: # オプション、タグ検索用
    - react
    - cra
    - t3stack
spec:
  owner: user:guest # テンプレートの所有者情報
  # テンプレートをフィルタリングするためのコンポーネントタイプ
  type: website
  # テンプレート変数
  parameters:
    - title: Provide some simple information
      required:
        - component_id
        - owner
      properties:
        component_id:
          title: Name
          type: string
          description: Unique name of the component
          ui:field: EntityNamePicker
        description:
          title: Description
          type: string
          description: Help others understand what this website is for.
        owner:
          title: Owner
          type: string
          description: Owner of the component
          ui:field: OwnerPicker
          ui:options:
            allowedKinds:
              - Group
    - title: Choose a location
      required:
        - repoUrl
      properties:
        repoUrl:
          title: Repository Location
          type: string
          ui:field: RepoUrlPicker
          ui:options:
            allowedHosts:
              - github.com
  # カタログ作成アクション
  steps:
    - id: template
      name: Fetch Skeleton + Template
      action: fetch:template
      input:
        url: ./skeleton
        copyWithoutRender:
          - .github/workflows/*
        values:
          component_id: ${{ parameters.component_id }}
          description: ${{ parameters.description }}
          destination: ${{ parameters.repoUrl | parseRepoUrl }}
          owner: ${{ parameters.owner }}

    - id: publish
      name: Publish
      action: publish:github
      input:
        allowedHosts:
          - github.com
        description: This is ${{ parameters.component_id }}
        repoUrl: ${{ parameters.repoUrl }}

    - id: register
      name: Register
      action: catalog:register
      input:
        repoContentsUrl: ${{ steps.publish.output.repoContentsUrl }}
        catalogInfoPath: "/catalog-info.yaml"
  # カタログ作成後の出力
  output:
    links:
      - title: Repository
        url: ${{ steps.publish.output.remoteUrl }}
      - title: Open in catalog
        icon: catalog
        entityRef: ${{ steps.register.output.entityRef }}

以下、それぞれについて補足を記載します。

  • spec.type

    • テンプレートをフィルタリングするためのコンポーネントタイプであり、Catalog画面の左ペイン、Typeにて選択ができる
    • 必須で設定する必要があるが、任意の値を設定可能
    • templateによって作成される Componentのspec.type との一致が望ましい
    • 起動直後、spec.typewebsiteservice、それ以外で各Component詳細を表示した際のタブ情報が異なっている
  • spec.parameter

    • テンプレート変数であり、UIからカタログを作成する際に入力する項目
    • title セクションごとが入力フォームのステップとなる
      • 上記であれば、STEP1: 名前やオーナー情報などの情報入力、STEP2: デプロイ先情報の入力
    • parameters yamlは react-jsonschema-form に基づいて定義されている
      • ui:*の部分で、既存のJsonSchemaにマージする、uiSchema を定義している
      • ui:options については ui:options Examples 参照
    • XxxPicker: Backstage上に保存されているエンティティ情報を利用したい場合に使用する
      • ui:field: EntityPicker: カタログエンティティのリストを表示
      • ui:field: OwnedEntityPicker: 所有しているエンティティのみ表示
      • ui:field: RepoUrlPicker: ユーザーが新しいリポジトリの名前と場所を選択できるようにする
        • allowedHosts を使ってリポジトリの url 出力値を決定する、app-config.yamlintegrationで規定されている対象であればよい
      • ui:field: OwnerPicker: カタログ上に登録されている User や Group を選択できるようにするspec
  • spec/step

    • カタログ作成時のアクションを定義する

    • 最初にワークスペースと呼ばれる一時ディレクトリを作成し、そこでファイルのダウンロード、生成、更新、外部システムへのプッシュを実行していく

    • 各アクションは以下のフォーマットに沿って定義する

      - id: fetch-base # A unique id for the step
        name: Fetch Base # A title displayed in the frontend
        if: ${{ parameters.name }} # Optional condition, skip the step if not truthy
        each: ${{ parameters.iterable }} # Optional iterable, run the same step multiple times
        action: fetch:template # An action to call
        input: # Input that is passed as arguments to the action handler
          url: ./template
          values:
            name: ${{ parameters.name }}
      
    • どのような action が定義できるかは、<backstage URL>/create/actions にてリストを確認することができる

  • テンプレート構文

    • ${{ }} とくくることで、変数を利用できる(型情報は保持される)
    • UIから入力したパラメータは、template.yaml 内、コード内どちらでも利用できる
      • template.yaml内: ${{ parameters.xxx }} を利用する
      • Templateとして展開するコード内: ${{ values.xxx }} をコード内で利用する + fetch:template 内で values として参照させる

skeleton/catalog-info.yaml

Templateを利用して作成されたカタログがどのようにBackstage上に登録されるかを定義するエンティティファイルです。

kind については作成する種別によって変化します。
metadata については Common to All Kinds: The Metadataをください。

apiVersion: backstage.io/v1alpha1
kind: Component
metadata:
  name: ${{values.component_id | dump}}
  {%- if values.description %}
  description: ${{values.description | dump}}
  {%- endif %}
  annotations:
    github.com/project-slug: ${{values.destination.owner + "/" + values.destination.repo}}
    backstage.io/techdocs-ref: dir:.
spec:
  type: website
  lifecycle: experimental
  owner: ${{values.owner | dump}}

終わりに

いかがでしょうか?

本ブログではBackstageのSoftware Template機能について、概要から導入方法までを簡単にご紹介させていただきました。
公式ドキュメントを読む、実際にTemplate機能を導入していく際に理解の一助となれば幸いです。

【PR】

私達ACS事業部はAzure・AKSなどのクラウドネイティブ技術を活用した内製化のご支援をしております。 また、Backstageを実際に業務の環境で導入してみたいのだけど、という方がいらっしゃいましたらぜひ私達にご相談ください。

www.ap-com.co.jp また、一緒に働いていただける仲間も募集中です!
今年もまだまだ組織規模拡大中なので、ご興味持っていただけましたらぜひお声がけください。 www.ap-com.co.jp

本記事の投稿者: 田中 絢子
Azureをメインにしたインフラとアプリの領域をご支援することが多いです。