dbt特化型BIツール『Lightdash』を Cloud Run x Cloud SQL でホスティングしてみた

:::note warn
個人的に動かす前提で各設定を行っているため、必要に応じて設定値を変更してください。
:::

# リポジトリの準備

今回は公式が公開している`Cloud Run`で動かす用の[リポジトリ](https://github.com/lightdash/lightdash-production-example)を利用していきます。

また、Private リポジトリで作成したかったため、下記手順を踏みました。

```shell
git clone --bare git@github.com:lightdash/lightdash-production-example.git
cd lightdash-production-example.git
# private リポジトリで空の lightdash-cloud-run-sql リポジトリを作成
git push --mirror git@github.com:{{ 自身のGithubアカウント }}/lightdash-cloud-run-sql.git
cd ../
rm -rf lightdash-production-example.git
```

# `lighdash-entrypoint.sh`の編集

2023年3月7日現在、今の状態でデプロイすると`knex_migrations`というテーブルが生成されないため、一番最初に`yarn workspace backend migrate-production`を実行するように修正します。

```lightdash-entrypoint.sh
#!/bin/bash

yarn workspace backend migrate-production

# -- OPTIONAL --
# Only needed if you want to run dbt commands on deploying lightdash
cd /usr/app/dbt
dbt seed --full-refresh
dbt run
cd /usr/app/packages/backend
# --------------

exec yarn start
```

# `VPC ネットワーク`を作成する

`Cloud Run`から`Cloud SQL`へ接続する際に、`VPC ネットワーク`を利用するため、新規で作成します。

| 項目 | 設定値 |
| :-- | :-- |
| 名前 | lightdash-vpc |
| サブネット作成モード | 自動 |


# サービスアカウントを作成する

`Cloud Run`で利用するサービスアカウントを作成します。

| 権限 | 用途 |
| :-- | :-- |
| BigQuery ジョブユーザー | `Lightdash`から`BigQuery`へジョブを実行できるようにするため |
| BigQuery 閲覧者 | `Lightdash`のプロジェクト作成時に、`BigQuery`のスキーマ情報を読み込めるようにするため) |
| Cloud SQL クライアント | `Lightdash`のユーザー情報や作成したダッシュボードを、`Cloud SQL`に保存できるようにするため |
| Secret Manager のシークレット アクセサー | `Cloud Run`のシークレットに設定する`PostgreSQL`のパスワードを読み取れるようにするため |

# `Cloud SQL`のインスタンスを作成する

<img width="1000px" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/311026/0a34e4fc-8655-30d4-eed1-4942a6303a87.png">

<img width="1000px" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/311026/8b09943a-e445-a597-e63d-4ac98cf40d5a.png">

| 項目 | 入力値 |
| :-- | :-- |
| インスタンスID | lightdash-pg |
| パスワード　| {{ 任意の文字列を設定 }} |
| データベースのバージョン | PostgreSQL 14 |
| 最初に使用する構成の選択 | サンドボックス |
| リージョン | asia-northeast1(東京) |
| ゾーンの可用性 | シングルゾーン |
| マシンタイプ | 1 vCPU、3.75GB |
| ストレージ | SSD, 10GB, ストレージの自動増量：無効 |
| 接続 | プライベートIP:有効 {{ 作成した`VPC ネットワーク` }} 自動的に割り当てられたIP範囲を使用する, パブリックIP:無効 | 

# シークレットの作成

`Cloud Run`から`Cloud SQL`に接続する際に使用する`PostgreSQL`のパスワードを、シークレットとして作成します。

| 項目 | 設定 |
| :-- | :-- |
| 名前 | lightdash-pg-password |
| シークレットの値 | {{ `Cloud SQL`で設定した`PostgreSQL`のパスワード }} |
| ロケーション | asia-northeast1 |


# `サーバーレス VPC アクセス`の作成

`Cloud Run`から`Cloud SQL`へ`VPC ネットワーク`経由で接続する際に必要になるため、新規で作成します。

| 項目 | 設定 |
| :-- | :-- |
| 名前 | lightdash-vpc-connector |
| リージョン | asia-northeast1 |
| ネットワーク | lightdash-vpc |
| サブネット | カスタムIP範囲, {{ Cloud SQL のプライベートIP の前2つ }}.0.0 |

# `Cloud Run`のサービスを作成する

<img width="1000px" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/311026/303e637c-313b-01a5-16ea-8ecfa21f9b27.png">

| 項目 | 入力値 |
| :-- | :-- |
| ソースリポジトリから新しいリビジョンを継続的にデプロイする | {{最初に作成したリポジトリを選択 }}, Build Type Dockerfile `\lightdash-dockerfile` |
| サービス名 | lightdash |
| リージョン | asia-northeast1(東京) |
| インスタンスの最小数 | 1 |
| 認証 | 未承認の呼び出しを許可 |
| 環境変数 | PGHOST:{{ Cloud SQL のプライベートIP }} |
| | PGUSER:postgres |
| | PGDATABASE:postgres |
| | LIGHTDASH_SECRET:not very secret |
| | SITE_URL:Cloud Run が発行する URL(一度サービスをデプロイしないといけない？) |
| | PGMAXCONNECTIONS:30 |
| | GCP_PROJECT_ID:{{ `profiles.yml`で設定しているプロジェクトID }} |
| | GCP_DATASET_ID:{{ `profiles.yml`で設定しているデータセット名 }} |
| | GCP_DATASET_LOCATION:{{ `profiles.yml`で設定しているロケーション }} |
| シークレット | 環境変数として公開, PGPASSWORD:{{ 作成したシークレット }} |
| Cloud SQL 接続 | {{ 作成した Cloud SQL のインスタンス }} |
| ネットワーク | {{ 作成したサーバーレス VPC コネクタ }} |
| セキュリティ | {{ 作成したサービスアカウント }} |

# Lightdash にアクセスする

デプロイが完了したら、`Cloud Run`のサービスURLにアクセスし、初期ユーザーの作成画面が出てきたらOKです。
※ここから先は、`Lightdash`の操作の話になるため、詳しくは[公式ドキュメント](https://docs.lightdash.com/)をご参照ください。

![スクリーンショット 2023-03-05 21.01.47.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/311026/a4ddebe4-59b5-e3d8-c730-16ec10bd4d65.png)


# 今後の課題

ユーザー招待制とは言え、現状は誰でもログイン画面にアクセスできてしまうため、何かしら認証を挟むのが望ましいと考えています。

認証に関しては、`Identity-Aware Proxy`を利用する事例をいくつか見つけたので、必要に応じて設定しておきましょう。