SnowflakeとMetabaseで作る格安データ分析基盤

# 導入の背景
Snowflakeを導入し、Talendと各種バッチ処理を作成してデータ分析基盤を構築しましたが、肝心のBIがコストの関係でストップとなりました。当初はPowerBIを導入する予定でしたが、BIをQuickSightに変更してコストを約半分にまで下げる案に変更しても予算がおりませんでした。コスト問題をクリアする為に仕方なくOSSであるMetabaseで構築した環境でしたが、思った以上に低価格で高性能な環境ができあがり、PowerBIに負けてないどころか、こちらの方が使い勝手が上だと思う環境ができましたので、紹介したいと思います。

###おすすめしたいポイント

■Snowflake
　・クエリが投げられた間だけの課金(停止中は課金されない)
　・停止中でも瞬間に起動するので、遅延は感じない
　・控えめに言っても超高速
　・スタンダード契約なら、最小サイズのXSサイズで1クレジット$2.85(ざっくり300円くらい)
　　　↓ クレジットの考え方や詳しい価格は下記で紹介されています。↓

https://dev.classmethod.jp/articles/snowflake-calculation/

■Metabase
　・使いやすい(直感的なわかりやすさ、操作性の良さ、見やすさ)
　・SQLを直接投げることができる(情シスには非常に楽)
　・ダッシュボードに設定した内容をメール送信できる
　　　メール内容も見やすいので、IT超絶苦手な方々にはメールだけで十分かも
　　　↓　Metabaseの魅力は下記で紹介していただいています　↓

https://knowledge.insight-lab.co.jp/bi/metabase-touch-the-trial

※ダッシュボードからメールを送信する機能は紹介されていなかったので、本記事の後半にて紹介しております。

# 実際にMetabaseを構築する
Snowflake導入の記事を書いていなくて恐縮ですが、Snowflake導入済みの前提で記入します。
(Snowflake導入の良い記事を見つけられませんでした…)

Metabaseの構築方法はJARファイルを使う方法とdockerイメージを使う方法があります。
今回はdockerイメージを使う方法を選択しました。


# まずはdocker用のサーバを構築します
EC2上にAmazon Linux2でサーバを立て、AWS公式で紹介されているEC2 Instance Connectで接続しようとしましたが、接続できませんでしたので、コマンドプロンプトからSSH接続しました。
(Windows10 18.03以降はコマンドプロンプトにSSHが包含されていました)

```
ssh -v -i my_key.pem ec2-user@xxx.xxx.xxx.xxx  ← IP
```

※ec2-userはAmazon Linuxの初期ユーザーです
※.pemにはEC2構成時に指定したpemです

#dockerインストール
SSH接続ができれば、下記のコマンドを順に実行していくことでdockerインストールが完了します。

```
sudo yum update -y
```
```
sudo amazon-linux-extras install docker
```
```
sudo service docker start
```

```
sudo usermod -a -G docker ec2-user
```
```
docker info
```
ここで下記のエラーが出てdocker infoが表示できませんでした。
　**Got permission denied while trying to connect to the Docker daemon socket ～**
調べたところ、ユーザーを(この場合はec2-user)を「docker」グループに追加する必要があるとのこと。そこで下記を実行。

```
sudo gpasswd -a ec2-user docker
```

一旦ログアウト(exit)
再度SSH接続し、docker infoで情報が表示されることを確認しました。
あとは公式サイトの下記コマンドを実行することでMetabaseがインストール出来ました。

```
docker run -d -p 3000:3000 --name metabase metabase/metabase
```

dockerの自動起動を有効にしておきます。

```
sudo systemctl enable docker
```
ついでにMetabaseの自動起動も有効にしておきます。

```
docker update --restart=always metabase
```

以上でMetabaseの環境構築は完了です。

#MetabaseからSnowflakeへの接続

https://knowledge.insight-lab.co.jp/snowflake/snowflake-metabase-connect

既に記事にしていらっしゃる方がいました。この通りで接続できるので大変簡単です。
SnowflakeにIP制限を掛けている場合はMetabaseのIP登録が必要ですので、ご注意ください。

あとはSnowflake上のデータをMetabaseで可視化することで、楽しむことができます。

# Oracleドライバの導入
Oracleにも接続しようとしたところ、Oracleドライバはライセンスの関係で自身で導入する必要があるとのこと。dockerを初めて使うこともあり、非常に苦労しました。そもそもLinuxも初心者なのでもっと楽な方法があると思いますが、下記の方法でOracleドライバをdocker上のMetabaseに導入しました。

■手元のWindowsPCでOracleドライバ(ojdbc8.jar)を入手
　　　https://www.oracle.com/database/technologies/appdev/jdbc-downloads.html
参考：https://www.metabase.com/docs/latest/administration-guide/databases/oracle.html

■Oracleドライバ(ojdbc8.jar)をAmazon Linuxへアップロード
　　SFTPを使い、Amazon Linux上のフォルダにアップロードしました。

■Oracleドライバ(ojdbc8.jar)をmetabaseのpluginsフォルダにコピー
　　下記コマンドでコンテナにファイルをコピーすることができました。
　　docker cp コピー元ファイル コンテナ名:コピー先フォルダ
　　例) docker cp /ドライバを仮置したフォルダ/ojdbc8.jar metabase:/plugins

■サーバ再起動
　　dockerのstop、startだけではOracleドライバが正常に動作しませんでした。
    サーバを再起動した後は問題なく動作しました。

#### 悩んだ点
先人の方々の記載でMetabaseのpluginsフォルダにojdbc8.jarを入れれば良いであろうことは早い段階でわかったのですが、コンテナ上にあるMetabaseのpluginsフォルダにどうすればアクセスできるのかがわからず非常に悩みました。
結論として、コンテナにアクセスするコマンド(docker exec -it)を見つけたことが課題解消に繋がりました。
下記コマンドでコンテナのフォルダ構成を見ることができます。

```
docker exec -it metabase ls -l
```
(上述していますが)下記のコマンドでローカルからコンテナにファイルをコピーできます。

```
docker cp /ドライバを仮置したフォルダ/ojdbc8.jar metabase:/plugins
```

# Metabaseでダッシュボードの内容をメール送信する
ダッシュボードに表示している内容をメール送信することができます。
私はデータに異常があったらメール送信するように設定しておりますので、簡単に異常に気づきやすく非常に重宝しています。
ダッシュボード画面右上にあるボタンから設定が可能です。


![2021-09-08_18h46_09.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/359386/82eff4df-32ae-b05a-cb8d-659219f03324.png)

![2021-09-08_18h48_19.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/359386/702029dd-cf64-518e-65af-91bc31a6fc92.png)

![2021-09-08_18h47_47.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/359386/32fe7387-6653-141f-a6a3-fdb125fff40d.png)

![2021-09-13_10h39_41.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/359386/760c13d5-6659-5ead-87e6-c69565f74e0f.png)



設定しておくと、下記のようにメール本文に結果が記載されている他、添付ファイルを付けて送ることも可能です。

![2021-09-08_19h02_03.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/359386/4bc244ed-badd-71b9-8106-9c4a4e5fdf41.png)


# Metabase構築中に起きたトラブル
Metabase動作確認後に、サーバを再起動するとMetabaseが起動しなくなりました。
後でわかったのですが、このときdocker start metabaseとするだけで良かったのですが、対応方法がわからず、再度docker run -d -p 3000:3000 --name metabase metabase/metabaseを実施したせいで、docker imagesで見るとコンテナが2つ存在する状態となっていました。
ただ、dockerは正常に動作していたので、コンテナを全て削除して、再度docker run -d -p 3000:3000 --name metabase metabase/metabaseを実施してmetabaseのコンテナから作成し直したところ、正常起動可能となりました。

#### docker環境のクリーンアップに使用したコマンド
```
全コンテナ停止: docker stop $(docker ps -q)
全コンテナ削除: docker rm $(docker ps -aq)
全イメージ削除: docker rmi $(docker images -q)
```
https://sagantaf.hatenablog.com/entry/2018/09/09/003826

#### サーバ再起動後の操作
上記の反省から、サーバ再起動時にdockerとMetabaseコンテナが起動するように構築コマンドを変更しております。よって、今回構築に紹介したコマンドを使用している場合は、何もしなくてもサーバ再起動でMetabaseサービスが起動するようになっております。

参考として、コンテナの稼働状況を確認するコマンドを掲載しておきます。

```
docker ps
```

# Metabaseのアップデート
単純にコマンドを流すだけではアップデートできないようで、dockerイメージごと新しくする必要がありました。
Metabase標準のDBであるH2にデータを保存してしまっていたので、metabase.dbを一度ローカルディスクにバックアップしてから、最新のイメージに入れ替えました。
その際に、コンテナ内にMetabaseのデータを持つのではなく、ローカルディスクにデータを置いてコンテナにマウントする方法に変更しました。(ついでにポートもhttpを使うように変更)
サーバ起動時にmetabaseコンテナを起動するコマンドも追加しておくことで、アップデート前と同様の環境となります。

```
sudo docker cp metabase:/metabase-data/metabase.db metabase-data
docker stop metabase
docker rename metabase metabase_old
docker update --restart=no metabase_old

docker pull metabase/metabase:latest

docker run -d -p 80:3000 \
-v ~/metabase-data:/metabase-data \
-e "MB_DB_FILE=/metabase-data/metabase.db" \
--name metabase metabase/metabase

docker stop metabase
docker cp metabase_driver/ojdbc8.jar metabase:/plugins
docker start metabase

docker update --restart=always metabase
```

https://koni.hateblo.jp/entry/2019/11/26/144850

###Metabaseのアップデート後のコンテナとイメージの削除
アップデートでコンテナを入れ替えた後、古いコンテナとイメージは下記コマンドで削除を行いました。

```
docker rm コンテナ名
　※コンテナ名はdocker psで表示されるNAMESのこと
docker rmi イメージID
　※イメージIDはdocker imagesで表示されるIMAGE IDのこと
```

#追記：H2からPostgresへの移行(未完了)
公式の情報のコマンドを試してみたが、うまくいかない。
試行錯誤した記録(結局ダメだったが)。

metabase公式
https://www.metabase.com/docs/latest/operations-guide/migrating-from-h2.html

```
export MB_DB_TYPE=mysql
export MB_DB_DBNAME=metabase
export MB_DB_PORT=3306
export MB_DB_USER=<username>
export MB_DB_PASS=<password>
export MB_DB_HOST=localhost
java -jar metabase.jar
```

java -jar metabase.jarでエラーが発生している状態。
ExportするとMB_DB_HOSTなどの環境変数は書き換わっておりました。
よってexport MB_DB_HOSTコマンドは正常実行されたと判断。

metabase.jarはコンテナ内にあるので、下記コマンドでmetabaseコンテナに入ります。

```
docker exec -it metabase bash
```

カレントディレクトリで下記のコマンドを実行

```
java -jar app/metabase.jar load-from-h2 /metabase-data/metabase.db
```

しかし、ERROR Set up h2 source database and run migrations...と出て失敗。

また後日チャレンジします。

# [トラブル] dockerコマンドが使用できなくなった
```
Cannot connect to the Docker daemon at unix:///var/run/docker.sock. Is the docker daemon running?
```
docker系のどのコマンドを投げても反応しなくなった。
下記の通りサービスを再起動したら解消した。

```
sudo service docker stop
sudo service docker start
```

# 今回の構成で改善したい点
　・Metabase側のスペックを上げておかないとSnowflakeの性能を活かせない
　　　ここがコストが嵩むポイントになっている(Snowflakeが激安なのに)
　　　AmazonECS(Fargate)で安く運用できるか試してみたい。
　　　Snowflakeのように、使う時に素早く起動する方法はないか？
　・今回の構成ではMetabaseの設定情報を標準のDBであるH2に保存しています。
　　　公式サイトでも紹介しているPostgresへ移行を予定しています
　・今回は社内LAN用に作成しましたが、タブレットからも使えるようHTTPS対応にしたい


# 参考にしたサイトです
https://docs.aws.amazon.com/ja_jp/AmazonECS/latest/developerguide/docker-basics.html

https://qiita.com/ashidaka/items/734856443f922ff175b1

https://www.metabase.com/docs/latest/operations-guide/upgrading-metabase.html

https://www.metabase.com/docs/latest/operations-guide/migrating-from-h2.html

https://qiita.com/shanonim/items/5496e0c6f6bf09e76f7c

https://qiita.com/ryoya-s/items/36579e834400a6018e41

↓ あなたの質問には時間がかかりすぎました ↓

https://zenn.dev/0yan/articles/14f0564f6abc069a8ab2#%E3%81%82%E3%81%AA%E3%81%9F%E3%81%AE%E8%B3%AA%E5%95%8F%E3%81%AB%E3%81%AF%E6%99%82%E9%96%93%E3%81%8C%E3%81%8B%E3%81%8B%E3%82%8A%E3%81%99%E3%81%8E%E3%81%BE%E3%81%97%E3%81%9F

最後までお読み頂きありがとうございました。