Kubernetes(Helm)
Helm による Busabase Premium のインストール — chart が作るもの、設定を誤ると添付とサインインが静かに壊れる 2 つの値、そして自前の Postgres と S3 に切り替えるべき時期。
chart は公開リポジトリ busabase/busabase-premium の helm/ 以下にあります。Compose 構成を Kubernetes オブジェクトで表現したものなので、Compose での本番構成の内容はそのまま当てはまります。
インストール
git clone https://github.com/busabase/busabase-premium.git
helm install busabase ./busabase-premium/helm \
--namespace busabase --create-namespace \
--set image.tag=0.10.0 \
--set appUrl=https://busabase.company.internalこの 2 つは必須で、欠けている場合 chart は中途半端に動くものをインストールせず、レンダリング自体を拒否します:
image.tag— 意図的にピン留めを必須にしています。動くタグを追う chart は、pod が再起動するたびにインスタンスをアップグレードしてしまいます。データを預かるサーバーに欲しい性質ではありません。appUrl— ユーザーが実際に入力するアドレス。サインイン cookie はこれを基準に発行されるため、食い違うと「サインインは成功したように見えて、すぐログイン画面に戻される」という挙動になり、ログには何も残りません。
作成されるもの
| オブジェクト | 用途 |
|---|---|
Deployment | アプリ |
Job(Helm hook) | マイグレーション。リリースごとに 1 回、アプリのロールアウト前に実行 |
StatefulSet ×2 | 同梱の Postgres とオブジェクトストレージ(外部モードでは作成されません) |
Service ×3 | アプリ、Postgres、ストレージ |
Secret | 生成された認証情報。アップグレード時も保持 |
マイグレーションは hook であり、initContainer ではない
この Job は pre-install,pre-upgrade hook です。理由は 2 つあります:
- レプリカごとではなく、リリースごとに 1 回実行される。 initContainer にすると各レプリカが同じデータベースへのマイグレーションを奪い合い、負けた側は「ロック競合」ではなく「スキーマが壊れている」ように見える形で失敗します。
- マイグレーションの失敗はリリースの失敗になる。
helm upgradeは停止し、既存の pod が旧コードで旧スキーマを処理し続けます — 新しい pod が中途半端なスキーマの上で起動するのではなく。
失敗した Job はログ確認のために残されます。エラーには失敗した SQL 文が出ますが、由来のファイル名は出ません。その文でマイグレーションディレクトリを grep して特定してください。
オブジェクトストレージはブラウザから到達可能である必要がある
アップロードは presigned PUT、ダウンロードはリダイレクトなので、ブラウザがオブジェクトストレージへ直接アクセスします(Busabase Cloud で S3 に対して行うのと同じ形)。このアドレスはブラウザから解決できなければなりません。クラスタ内部の Service 名は解決できず、症状は特徴的かつ紛らわしいものになります: アプリは動き、サインインも動き、添付のアップロードだけがすべて失敗します。
既定では chart が appUrl からストレージのホストを導出します。通常はこれで正しく、ストレージが別のホスト名で応答する場合は storage.publicHost を設定し、両方のホストを Ingress の後ろに置いてください。
自前の Postgres と S3 を使う
同梱のものは helm install で動くものが出来上がるようにするためのものです。どちらも本番向けの答えではありません: 同梱の Postgres は単一 pod で、フェイルオーバーもポイントインタイムリカバリもなく、バックアップはお客様の責任です。
helm install busabase ./busabase-premium/helm \
--set image.tag=0.10.0 \
--set appUrl=https://busabase.company.internal \
--set postgres.mode=external \
--set postgres.external.host=pg.company.internal \
--set storage.mode=external \
--set storage.publicHost=s3.company.internal外部モードでは、どちらの StatefulSet も作成されません。
シークレット
Postgres のパスワード、オブジェクトストレージのキー、セッション署名鍵は初回インストール時に生成され、アップグレード時も保持されます — chart は既存の Secret を読み戻し、新たに生成し直しません。これは細部の話ではありません: セッション署名鍵が変わると全員がログアウトされ、Postgres のパスワードが変わるとアプリが自分のデータベースを開けなくなります。
自分で管理する場合は secrets.existingSecret を設定してください。chart はシークレットを一切作成しなくなります。
有効化
他のデプロイ形態とまったく同じです: システム管理 → ライセンスで貼り付けて保存。検証はマシン上で完結し、ネットワークは不要です。ライセンスを参照してください。