app-configの階層とマージ結果の予測
目標
Backstageの設定を複数のファイルに分けて書き、そのファイルが重なったときに何が残るかを、手で予測してみます。最後に、本番設定をKubernetesのオブジェクトに移して、実際のデプロイで値がどこから来るのかを確認します。
なぜ重要なのか
設定の階層は、CBAで最もよく間違える箇所です。ルール自体は2行なのに、結果が直感とずれるからです。マッピングはキー単位で深くマージされますが、リストはマージされず、まるごと置き換えられます。基本のファイルにカタログの入口を3件書いておき、オーバーライドに1件だけ書くと、結果は4件ではなく1件で、警告は何も出ません。値の種類が変わるときも同じです。文字列だった場所にマッピングが来ると、文字列は消えます。そして、認証情報は、どのファイルにも値として書いてはいけません。設定ファイルはリポジトリにコミットされ、イメージに焼き込まれるからです。Backstage自体はこの環境にないので、採点は、ファイルとクラスターのオブジェクトを読み取って行います。
ステップ
/root/cba-config/app-config.yamlに基本設定を書いてください。app.titleは任意の値、app.baseUrl: http://localhost:3000、organization.nameは任意の値、backend.baseUrl: http://localhost:7007、backend.listen.port: 7007、backend.cors.origin: http://localhost:3000、backend.database.client: better-sqlite3、backend.database.connection: /tmp/portal.sqliteです。- 同じファイルに、統合とプロキシを続けて書いてください。
integrations.githubの最初の項目のhost: github.comとtoken(GITHUBが入った環境変数の置換形式)、proxy.endpointsの下の/argocd/apiキーに、target(httpsで始まるアドレス)、changeOrigin: true、headers.Cookie(環境変数の置換形式)です。 - 同じファイルに、カタログの設定を続けて書いてください。
catalog.import.entityFilename: catalog-info.yaml、catalog.rulesの最初の項目のallowに、Component、API、Resource、System、Domain、Group、User、Location、Templateの9つの種類、catalog.locationsは2件(1つ目はtype: fileで、targetがentities.yamlで終わるもの、2つ目はtype: urlで、targetがgithub.comのアドレス)、catalog.providers.github.labhubOrgにorganization: labhub、catalogPath: /catalog-info.yaml、schedule.frequency.minutes: 30、schedule.timeout.minutes: 3です。 /root/cba-config/app-config.local.yamlにオーバーライドを書いてください。app.baseUrl: http://portal.labhub.test、backend.baseUrl: http://portal.labhub.test:7007、backend.database.client: pg、backend.database.connectionの下のhost・port・user・databaseをすべて環境変数の置換形式で、catalog.locationsはtype: urlの1件だけです。backend.listen.portは書かないでください。/root/cba-config/merged.yamlに、ステップ1–3のファイルの上に、ステップ4のファイルを重ねたときに残る値を、そのまま書いてください。マッピングは深くマージされ、リストはまるごと置き換えられます。/root/cba-config/app-config.production.yamlに本番設定を書いてください。app.baseUrlとbackend.baseUrlはどちらもhttps://portal.labhub.io、backend.listen.host: 0.0.0.0、backend.database.client: pg、auth.environment: production、auth.providers.github.productionのclientIdとclientSecretは環境変数の置換形式、同じ場所のsignIn.resolversの最初の項目のresolverは、カタログのUserエンティティに合わせるリゾルバーの名前、techdocs.builder: external、techdocs.publisher.typeはlocalではない外部ストレージの種類です。/root/cba-config/env-names.txtに、3つの設定ファイルが参照する環境変数の名前を、波括弧なしで1行に1つずつ、重複なしで並べ替えて書いてください。- 本番設定をクラスターに作成してください。ネームスペース
cba-configを作成し、その中にConfigMapportal-app-configを、ステップ6のファイルから作成してください(キー名がapp-config.production.yamlになっている必要があります)。そして、Deploymentportalを作成してください。イメージはnode:22-alpine、containerPort: 7007、そのConfigMapをボリュームとしてマウントし、環境変数APP_CONFIG_app_baseUrlの値が、ステップ6のファイルのapp.baseUrlとまったく同じである必要があります。
参考
- マージのルールは2行です。マッピングはキー単位で深く、リストはまるごと置き換えです。
- 環境変数の置換は
${NAME}の形式で、この形式で書けば、値がファイルに残りません。 - よくある間違い1: オーバーライドに、変えない値までコピーしておくこと。基本のファイルが動いても、こちらだけが古い値のまま残ります。
- よくある間違い2: リストがマージされると期待することです。基本のファイルの残りの項目は、静かに消えます。
- よくある間違い3:
backend.listen.hostをデフォルトのままにして、コンテナに載せること。ループバックにだけリッスンすると、サービスがPodに届きません。
基本のapp-config
/root/cba-config/app-config.yamlに基本設定を書いてください。app.titleは任意の値、app.baseUrl: http://localhost:3000、organization.nameは任意の値、backend.baseUrl: http://localhost:7007、backend.listen.port: 7007、backend.cors.origin: http://localhost:3000、backend.database.client: better-sqlite3、backend.database.connection: /tmp/portal.sqliteです。
フロントエンドとバックエンドは、別々のポートで起動します。CORSのoriginは、ブラウザーが来る側、つまりフロントエンドのアドレスです。
統合とプロキシ
同じファイルに、統合とプロキシを続けて書いてください。integrations.githubの最初の項目のhost: github.comとtoken(GITHUBが入った環境変数の置換形式)、proxy.endpointsの下の/argocd/apiキーに、target(httpsで始まるアドレス)、changeOrigin: true、headers.Cookie(環境変数の置換形式)です。
認証情報の位置に値を直接書くと、その秘密情報はgitの履歴とイメージのレイヤーに残ります。起動するときに環境変数で置換される形式を使ってください。
カタログのルールとディスカバリー
同じファイルに、カタログの設定を続けて書いてください。catalog.import.entityFilename: catalog-info.yaml、catalog.rulesの最初の項目のallowに、Component、API、Resource、System、Domain、Group、User、Location、Templateの9つの種類、catalog.locationsは2件(1つ目はtype: fileで、targetがentities.yamlで終わるもの、2つ目はtype: urlで、targetがgithub.comのアドレス)、catalog.providers.github.labhubOrgにorganization: labhub、catalogPath: /catalog-info.yaml、schedule.frequency.minutes: 30、schedule.timeout.minutes: 3です。
rulesは許可リストなので、ここにないkindは、登録が拒否されます。Templateを抜かすと、スキャフォルダーがまるごと空に見えます。
ローカルのオーバーライド
/root/cba-config/app-config.local.yamlにオーバーライドを書いてください。app.baseUrl: http://portal.labhub.test、backend.baseUrl: http://portal.labhub.test:7007、backend.database.client: pg、backend.database.connectionの下のhost・port・user・databaseをすべて環境変数の置換形式で、catalog.locationsはtype: urlの1件だけです。backend.listen.portは書かないでください。
オーバーライドのファイルには、変える値だけを書きます。変えない値までコピーしておくと、基本のファイルが動いたときに、こちらだけが古い値のまま残ります。
マージ結果の予測
/root/cba-config/merged.yamlに、ステップ1–3のファイルの上に、ステップ4のファイルを重ねたときに残る値を、そのまま書いてください。マッピングは深くマージされ、リストはまるごと置き換えられます。
マッピングはキー単位で深くマージされ、リストはまるごと置き換えられます。オーバーライドが触れなかったキーは、基本のファイルの値がそのまま残ります。
本番設定
/root/cba-config/app-config.production.yamlに本番設定を書いてください。app.baseUrlとbackend.baseUrlはどちらもhttps://portal.labhub.io、backend.listen.host: 0.0.0.0、backend.database.client: pg、auth.environment: production、auth.providers.github.productionのclientIdとclientSecretは環境変数の置換形式、同じ場所のsignIn.resolversの最初の項目のresolverは、カタログのUserエンティティに合わせるリゾルバーの名前、techdocs.builder: external、techdocs.publisher.typeはlocalではない外部ストレージの種類です。
コンテナの中でループバックにだけリッスンすると、サービスがPodに届きません。そして、認証は、ログインプロバイダーと身元の決定の、2つの段階に分かれます。
環境変数の参照リスト
/root/cba-config/env-names.txtに、3つの設定ファイルが参照する環境変数の名前を、波括弧なしで1行に1つずつ、重複なしで並べ替えて書いてください。
3つの設定ファイルのすべてが対象です。このリストが、そのままデプロイのマニフェストに埋めるべきSecretのキーの一覧になります。
設定をクラスターへ
本番設定をクラスターに作成してください。ネームスペースcba-configを作成し、その中にConfigMap portal-app-configを、ステップ6のファイルから作成してください(キー名がapp-config.production.yamlになっている必要があります)。そして、Deployment portalを作成してください。イメージはnode:22-alpine、containerPort: 7007、そのConfigMapをボリュームとしてマウントし、環境変数APP_CONFIG_app_baseUrlの値が、ステップ6のファイルのapp.baseUrlとまったく同じである必要があります。
ConfigMapをファイルから作成すると、ファイル名がそのままキーになります。そして、設定のパスのドットをアンダースコアに変えた名前の環境変数が、その1行を上書きします。