5
2

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

SupabaseをKubernetesでセルフホスティングする方法について

Posted at

本記事は、Supabase Advent Calendar 2023 18日目の記事です。

概要

FirebaseとSupabaseに同じ名前が付けられているHostingがあります。

これらは、全く別物でFirebaseはインフラ準備無しで静的コンテンツをホストしてくれるサービスで、Supabaseは公式のBaaSを使用せずに自前で用意したインフラに簡単にSupabaseを構築ができてサービス運用できるサービスになります。

今回は、Supabaseが提供しているKubernetesのSelf-Hostingでインフラを自前で準備する詳細やどのくらいコストがかかるのかなどをまとめたいと思います。

Kubernetes

k8sは、Dockerなどでコンテナ化してまとめたアプリケーションをサービス提供する際に活用する管理ツール。
初めて知る方は、以下のリンクなどを参考にk8sで何ができるのかインプットしておきましょう。

Kubernetes on Mac

Kubernetes on Ubuntu

Kubernetes on Windows

ディストリビューションツール

標準のk8s機能に加えて追加機能やさまざまなサポートを提供するカスタマイズされたツール。
Minikube・MicroK8s・K3sなどがあり、今回はMinikubeを使用します。

Minikube

ローカル上に単一ノードのk8sクラスターを作成し、開発やテストなどの目的に使用するツール。

MicroK8s

Ubuntuによって提供される、軽量で簡単にセットアップ可能なk8sディストリビューション。
デスクトップ、サーバー、IoTデバイスなど、幅広い環境で使用できる。

K3s

軽量でシンプルなk8sディストリビューション。リソースが限られた環境やエッジコンピューティング用に設計されています。

その他のツール

ディストリビューションの他にも開発をサポートしてくれるk8sツールがあり、今回はHelmを使用します。

Helm

k8sアプリケーションの定義、インストール、アップデートを簡単に作業できるパッケージマネージャーツール。
Helmを使うことでk8sにデプロイされるアプリケーションの管理がより効率的で、再現性が高くなります。

Skaffold

Googleによって開発されたk8sの継続的開発ツール。
ローカル開発とCI/CDパイプラインの両方で、ソースコードの変更をk8sクラスタに自動的にデプロイするために使われます。

Kustomize

k8sリソースの宣言的な管理を支援し、Helmとは異なるアプローチで
Kustomizeはk8sの一部として直接統合されており、kubectlとともに使用されることが多いです。

YAMLファイルをカスタマイズし、宣言的にk8sリソースを管理するためのk8sの構成管理ツール。

Self-Hosting with Kubernetes

Supabaseのk8sは、GitHubで展開されており概要や使用方法などは、supabase-community/supabase-kubernetes/charts/supabase/README.mdにまとまっています。

supabase-kubernetesは、Helmが活用されており、使用方法をMinikubeで解説されています。

Self-Hosting with Docker

k8sはコンテナを管理するツールなので、もちろんDockerのSelf-Hostingもサポートされています。
本番・検証は、公式のSupabaseまたはk8sで自前で用意した環境を利用して、開発はDockerでローカルにSupabase環境を構築して各開発を並行して進めることもできます。

k8sを構築してSupabaseを起動してみる

環境

  • MacBook Pro 14インチ
  • macOS 14.1.2
  • Apple M2 Max
  • メモリ 96 GB

セットアップ

Minikubeは、Dockerコンテナとして起動するため、以下のようにk8sの設定が必要です。

スクリーンショット 2023-12-22 1.45.31.png

次にMinikubeをインストールして起動します。

$ brew install minikube
Running `brew update --auto-update`...

...省略...

==> minikube
zsh completions have been installed to:
  /opt/homebrew/share/zsh/site-functions


$ minikube version 
minikube version: v1.32.0
commit: xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx


$ minikube start
😄  Darwin 14.1.2 (arm64) 上の minikube v1.32.0
✨  docker ドライバーが自動的に選択されました
📌  root 権限を持つ Docker Desktop ドライバーを使用
👍  minikube クラスター中のコントロールプレーンの minikube ノードを起動しています
🚜  ベースイメージを取得しています...
💾  ロード済み Kubernetes v1.28.3 をダウンロードしています...
    > preloaded-images-k8s-v18-v1...:  341.16 MiB / 341.16 MiB  100.00% 30.21 M
    > gcr.io/k8s-minikube/kicbase...:  410.58 MiB / 410.58 MiB  100.00% 22.59 M
🔥  Creating docker container (CPUs=2, Memory=11908MB) ...
🐳  Docker 24.0.7 で Kubernetes v1.28.3 を準備しています...
    ▪ 証明書と鍵を作成しています...
    ▪ コントロールプレーンを起動しています...
    ▪ RBAC のルールを設定中です...
🔗  bridge CNI (コンテナーネットワークインターフェース) を設定中です...
🔎  Kubernetes コンポーネントを検証しています...
    ▪ gcr.io/k8s-minikube/storage-provisioner:v5 イメージを使用しています
🌟  有効なアドオン: storage-provisioner, default-storageclass
🏄  終了しました!kubectl がデフォルトで「minikube」クラスターと「default」ネームスペースを使用するよう設定されました


$ minikube addons list
|-----------------------------|----------|--------------|--------------------------------|
|         ADDON NAME          | PROFILE  |    STATUS    |           MAINTAINER           |
|-----------------------------|----------|--------------|--------------------------------|
| ambassador                  | minikube | disabled     | 3rd party (Ambassador)         |
| auto-pause                  | minikube | disabled     | minikube                       |
| cloud-spanner               | minikube | disabled     | Google                         |
| csi-hostpath-driver         | minikube | disabled     | Kubernetes                     |
| dashboard                   | minikube | disabled     | Kubernetes                     |
| default-storageclass        | minikube | enabled ✅   | Kubernetes                     |
| efk                         | minikube | disabled     | 3rd party (Elastic)            |
| freshpod                    | minikube | disabled     | Google                         |
| gcp-auth                    | minikube | disabled     | Google                         |
| gvisor                      | minikube | disabled     | minikube                       |
| headlamp                    | minikube | disabled     | 3rd party (kinvolk.io)         |
| helm-tiller                 | minikube | disabled     | 3rd party (Helm)               |
| inaccel                     | minikube | disabled     | 3rd party (InAccel             |
|                             |          |              | [info@inaccel.com])            |
| ingress                     | minikube | disabled     | Kubernetes                     |
| ingress-dns                 | minikube | disabled     | minikube                       |
| inspektor-gadget            | minikube | disabled     | 3rd party                      |
|                             |          |              | (inspektor-gadget.io)          |
| istio                       | minikube | disabled     | 3rd party (Istio)              |
| istio-provisioner           | minikube | disabled     | 3rd party (Istio)              |
| kong                        | minikube | disabled     | 3rd party (Kong HQ)            |
| kubeflow                    | minikube | disabled     | 3rd party                      |
| kubevirt                    | minikube | disabled     | 3rd party (KubeVirt)           |
| logviewer                   | minikube | disabled     | 3rd party (unknown)            |
| metallb                     | minikube | disabled     | 3rd party (MetalLB)            |
| metrics-server              | minikube | disabled     | Kubernetes                     |
| nvidia-device-plugin        | minikube | disabled     | 3rd party (NVIDIA)             |
| nvidia-driver-installer     | minikube | disabled     | 3rd party (Nvidia)             |
| nvidia-gpu-device-plugin    | minikube | disabled     | 3rd party (Nvidia)             |
| olm                         | minikube | disabled     | 3rd party (Operator Framework) |
| pod-security-policy         | minikube | disabled     | 3rd party (unknown)            |
| portainer                   | minikube | disabled     | 3rd party (Portainer.io)       |
| registry                    | minikube | disabled     | minikube                       |
| registry-aliases            | minikube | disabled     | 3rd party (unknown)            |
| registry-creds              | minikube | disabled     | 3rd party (UPMC Enterprises)   |
| storage-provisioner         | minikube | enabled ✅   | minikube                       |
| storage-provisioner-gluster | minikube | disabled     | 3rd party (Gluster)            |
| storage-provisioner-rancher | minikube | disabled     | 3rd party (Rancher)            |
| volumesnapshots             | minikube | disabled     | Kubernetes                     |
|-----------------------------|----------|--------------|--------------------------------|


$ minikube dashboard
🔌  ダッシュボードを有効化しています...
    ▪ docker.io/kubernetesui/dashboard:v2.7.0 イメージを使用しています
    ▪ docker.io/kubernetesui/metrics-scraper:v1.0.8 イメージを使用しています
💡  いくつかのダッシュボード機能は metrics-server アドオンを必要とします。全機能を有効にするためには、次のコマンドを実行します:

	minikube addons enable metrics-server	


🤔  ダッシュボードの状態を検証しています...
🚀  プロキシーを起動しています...
🤔  プロキシーの状態を検証しています...
🎉  デフォルトブラウザーで http://127.0.0.1:57050/api/v1/namespaces/kubernetes-dashboard/services/http:kubernetes-dashboard:/proxy/ を開いています...

minikube dashboardを実行すると以下のようにk8sのダッシュボードがブラウザで表示されます。

スクリーンショット 2023-12-22 2.36.18.png

ローカルでSupabaseの起動確認

次にSupabaseの起動を行います。
READMEの解説に従って進めますが、Helmをまだインストールしていない場合は、brewで簡単にインストールできます。

$ git clone https://github.com/supabase-community/supabase-kubernetes
Cloning into 'supabase-kubernetes'...
remote: Enumerating objects: 561, done.
remote: Counting objects: 100% (333/333), done.
remote: Compressing objects: 100% (98/98), done.
remote: Total 561 (delta 274), reused 235 (delta 235), pack-reused 228
Receiving objects: 100% (561/561), 409.25 KiB | 4.31 MiB/s, done.
Resolving deltas: 100% (355/355), done.

$ cd supabase-kubernetes 
$ kubectl -n default create secret generic demo-supabase-jwt \
  --from-literal=anonKey='eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.ewogICAgInJvbGUiOiAiYW5vbiIsCiAgICAiaXNzIjogInN1cGFiYXNlIiwKICAgICJpYXQiOiAxNjc1NDAwNDAwLAogICAgImV4cCI6IDE4MzMxNjY4MDAKfQ.ztuiBzjaVoFHmoljUXWmnuDN6QU2WgJICeqwyzyZO88' \
  --from-literal=serviceKey='eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.ewogICAgInJvbGUiOiAic2VydmljZV9yb2xlIiwKICAgICJpc3MiOiAic3VwYWJhc2UiLAogICAgImlhdCI6IDE2NzU0MDA0MDAsCiAgICAiZXhwIjogMTgzMzE2NjgwMAp9.qNsmXzz4tG7eqJPh1Y58DbtIlJBauwpqx39UF-MwM8k' \
  --from-literal=secret='abcdefghijklmnopqrstuvwxyz123456'
secret/demo-supabase-jwt created

$ kubectl -n default create secret generic demo-supabase-smtp \
  --from-literal=username='your-mail@example.com' \
  --from-literal=password='example123456'
secret/demo-supabase-smtp created

$ kubectl -n default create secret generic demo-supabase-db \
  --from-literal=username='postgres' \
  --from-literal=password='example123456'
secret/demo-supabase-db created

$ helm -n default install demo -f values.example.yaml .
zsh: command not found: helm

$ brew install helm
==> Downloading https://formulae.brew.sh/api/formula.jws.json
#################################################################################################################### 100.0%
==> Downloading https://formulae.brew.sh/api/cask.jws.json
#################################################################################################################### 100.0%
==> Downloading https://ghcr.io/v2/homebrew/core/helm/manifests/3.13.3
#################################################################################################################### 100.0%
==> Fetching helm
==> Downloading https://ghcr.io/v2/homebrew/core/helm/blobs/sha256:1a6fd49305a1d9aa469785bb6d02cdbaf618a31db1752ccfce5015ce
#################################################################################################################### 100.0%
==> Pouring helm--3.13.3.arm64_sonoma.bottle.tar.gz
==> Caveats
zsh completions have been installed to:
  /opt/homebrew/share/zsh/site-functions
==> Summary
🍺  /opt/homebrew/Cellar/helm/3.13.3: 65 files, 53.7MB
==> Running `brew cleanup helm`...
Disable this behaviour by setting HOMEBREW_NO_INSTALL_CLEANUP.
Hide these hints with HOMEBREW_NO_ENV_HINTS (see `man brew`).

$ cd supabase-kubernetes/charts/supabase 
$ helm -n default install demo -f values.example.yaml .
NAME: demo
LAST DEPLOYED: Fri Dec 22 02:21:54 2023
NAMESPACE: default
STATUS: deployed
REVISION: 1
TEST SUITE: None

$ kubectl -n default get pod 
NAME                                     READY   STATUS             RESTARTS   AGE
demo-supabase-auth-6d7686db6-gfhbm       0/1     ImagePullBackOff   0          2m20s
demo-supabase-db-54bbdcbf66-xc5q6        1/1     Running            0          2m20s
demo-supabase-kong-78696ccf55-p8mfr      1/1     Running            0          2m20s
demo-supabase-meta-6d74588dff-2rvt6      1/1     Running            0          2m20s
demo-supabase-realtime-9f45bdfc6-t7rcc   1/1     Running            0          2m20s
demo-supabase-rest-8454676765-6vgcs      1/1     Running            0          2m20s
demo-supabase-storage-74cfb8fc5c-l42lj   1/1     Running            0          2m20s
demo-supabase-studio-6b7db68f86-btlw5    1/1     Running            0          2m20s

$ minikube addons enable ingress
💡  ingress is an addon maintained by Kubernetes. For any concerns contact minikube on GitHub.
You can view the list of minikube maintainers at: https://github.com/kubernetes/minikube/blob/master/OWNERS
💡  アドオンを有効にした後、「minikube tunnel」を実行することで、ingress リソースが「127.0.0.1」で利用可能になります
    ▪ registry.k8s.io/ingress-nginx/controller:v1.9.4 イメージを使用しています
    ▪ registry.k8s.io/ingress-nginx/kube-webhook-certgen:v20231011-8b53cabe0 イメージを使用しています
    ▪ registry.k8s.io/ingress-nginx/kube-webhook-certgen:v20231011-8b53cabe0 イメージを使用しています
🔎  ingress アドオンを検証しています...
🌟  'ingress' アドオンが有効です

$ minikube tunnel
✅  トンネルが無事開始しました

📌  注意: トンネルにアクセスするにはこのプロセスが存続しなければならないため、このターミナルはクローズしないでください ...

❗  demo-supabase-kong service/ingress は次の公開用特権ポートを要求します:  [80 443]
🔑  sudo permission will be asked for it.
❗  demo-supabase-studio service/ingress は次の公開用特権ポートを要求します:  [80 443]
🔑  sudo permission will be asked for it.
🏃  demo-supabase-kong サービス用のトンネルを起動しています。
🏃  demo-supabase-studio サービス用のトンネルを起動しています。
Password:

上記のように全て正常に起動できるとhttp://api.localhosthttp://studio.localhostにそれぞれアクセスすると以下のように表示されます。

スクリーンショット 2023-12-22 2.34.25.png

スクリーンショット 2023-12-22 2.34.05.png

minikube tunnelを停止したい場合は、controlキー & cキーを入力して、k8sも使用しなければminikube stopをお忘れなく。

まとめ

筆者は、初めてk8s・Minikube・Helmを触りましたが、とても簡単にSupabase環境を構築することができました。
まだ、ローカル構築でクラウドサーバーにk8sを載せてSupabaseを構築しておらず、その環境での開発・運用もやったことないですが、諸々のコストが気になるのでセルフホスティングを採用するプランはなかなかないかも?

ただ先日、構築済みKubernetes環境を提供する『cloud tap』が大幅料金改定というニュースがあったので、インフラが安く済むならSupabaseのProプランが必要な開発であれば検討アリなのかも??

筆者的には、公式のBaaSを利用する方が楽だからセルフホスティングはやりたくない所管で、個人的にk8sを入門したかったので良い題材になりましたw

 

5
2
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
5
2

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?