Busabase

Kubernetes(Helm)

Helm による Busabase Premium のインストール — chart が作るもの、設定を誤ると添付とサインインが静かに壊れる 2 つの値、そして自前の Postgres と S3 に切り替えるべき時期。

chart は公開リポジトリ busabase/busabase-premiumhelm/ 以下にあります。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 はシークレットを一切作成しなくなります。

有効化

他のデプロイ形態とまったく同じです: システム管理 → ライセンスで貼り付けて保存。検証はマシン上で完結し、ネットワークは不要です。ライセンスを参照してください。

On this page