💸

Cloud Runの永続ストレージメモ

に公開

家計簿的な集計をやりたくてcloud runでホストするgrafanaで動かそうとした際の経験談です。
その中でタイトルにもあるCloud Runの永続ストレージについてメモしておきます。

要件

  • ローカルで開発していたgrafanaをweb上で動作させる
    • grafanaのdbとしてsqliteを使用するため永続ストレージが必要
  • 外で確認する用途であり月に数時間程度の動作
  • 可能な限り低料金
  • 可能な限り運用の手間をかけない

選定

Filestore

最初は安直にcompute engineでも使用されているFilestoreでいいかと思っていました。
compute engineで使用されているものなら特に実用上の懸念はないはずです。
ちなみにFirestoreと頻繁にtypo、混同しました。
これが以下の理由から要件に対し異様に高い。

$1 = ¥140 として月に約28,000円は流石にオーバースペックです。

gcsのマウント

というわけで検索してたらこちらに辿り着きました。
こちらはgcsに対する料金体系と変わらない(ストレージ保管月額、各種オペレーション)とのこと。
https://cloud.google.com/storage/pricing?hl=ja

1TBでも$23だし、read/writeに対する従量課金が気になりますが1日お試しでやってみようと。

動作するまで

設定してハマる

terraformで以下を設定しrunにアクセス。

  • gcsの作成
  • cloud runのSAにgcsへの読み書き権限付与
  • cloud runにgcsをマウント
  • grafanaの環境変数設定
    • 作業ディレクトリをマウントしたパスに
    • BiqQuery Pluginをinstall

するとgranfanaのpluginが動作しない...

pluginがunsigned?
公式なのに🤔

いろいろ試す

試してみたが全てうまくいかず。貴重な週末を3週間くらい(フルじゃないよ)消費してしまいました。

  • メッセージを信じてそれっぽい環境変数を設定
    • GF_PLUGINS_ALLOW_LOADING_UNSIGNED_PLUGINS
  • イメージをカスタムビルドしてマウントしたディレクトリのオーナーを明示的に設定したり権限付与
  • ENTRYPOINTで上記を再度行うシェルスクリプトを指定

Unsignedって言ってるけど実は別の理由では?

問題の根本で吐かれているエラーが丸められてエンドユーザーに伝わってないケースを思い出しました。
つまりcloud run側で起きてる何かをgrafanaは Unsigned plugins と言っているのでは。
そしてcloud run側では以下のようになっていました。

permission denied権限がない = 署名されていない みたいなニュアンスでは一致しそうですがlinuxでの permission defined は主にユーザーの権限。
先ほど明示的に権限付与してみたりしてもダメだった、ここで一旦詰んでしまいました。

そもそもgcsマウントとは

技術的にどうやってるんだろうという切り口から考えてみました。
FUSEという仕組みのようです。
https://qiita.com/tkusumi/items/6dc204ba964264c72a9a
ストレージへのlist, read, writeをCloud storage APIで実現しているとのこと。

ここな予感がしました。
FUSEマウントなのでexecute権限を付与できないんじゃないかと。
でもそんなのでは使い物にならないので何かやりようがあるはず。
頑張ってググったらオプションの付与に到達!
https://cloud.google.com/run/docs/configuring/services/cloud-storage-volume-mounts?hl=ja#specify-mount-options

fuseマウントのオプションで明示的に実行権限を与える

いろいろ試行錯誤し動作、以下のようになりました。
terraformではgoogle-betaが必要な項目なので設定しておきましょう。
必要箇所だけ抜粋しています。

resource "google_cloud_run_v2_service" "kakeibo_grafana" {
  ...
  template {
    ...
    containers {
      ...
      volume_mounts {
        name       = "grafana-data"
        mount_path = "/var/lib/grafana"
      }
      ...
    }
    volumes {
      name = "grafana-data"
      gcs {
        bucket = google_storage_bucket.grafana_datas.name
        mount_options = ["uid=472", "gid=472", "file-mode=755"]
      }
    }
  }
}

全ユーザーが755がちょっと怖かったのでgrafanaユーザーのuid, gidも添えて設定しています。

料金

1時間くらいgrafanaのダッシュボードをこねてgcs料金は¥100くらいでした。
意外とかかるなという印象です。
grafanaはダッシュボードのyamlインポート/エクスポートがあるのでローカル開発し取り込むのが良さそうです。

安心していたらやらかしがありました。
私用Macのchromeでcloud runのgrafanaを開きっぱなしにしてたら1日で¥2,000課金💸
推測ですが以下の挙動かと。

  • chromeが定期的にバックグラウンドでコンテンツを更新する
  • その度にクエリ実行
  • sqliteなどgcsマウント先のリソースアクセス

不特定ユーザーに公開するとクラウド破産しそうな予感です。
マウント先のファイルの用途によってはgcsのFUSEマウントは不適という学びを得ました。

この辺を意識すると、grafanaを開いて数回クエリ更新した日は¥20程度になりました。
そんなにgrafanaを見るわけでもなく、月5~10日と仮定すると¥100~¥200であり問題ない範囲です。

終わりに

家計簿的なサービスの第一歩的としてgrafanaを外部公開するところまで到達しました。
以降は内部や運用を詰めていこうと思います。
最後までお読みいただきありがとうございました。

Discussion