破産したくないので、個人の検証用 Snowflake にリソースモニターを設定します。せっかくなので、SQL ではなく Terraform を使って設定します。加えて、内部で発行されている SQL 文も確認します。
1. はじめに
Snowflake は計算リソース(仮想ウェアハウス)を細かい単位で起動/停止でき、それがコスト面の優位性になっています。ただ、単位時間当たりの単価は比較的高く、AWS 東京リージョンの Snowflake だと 2023/3/31 時点で以下になります。
- Standard:$2.85 / 時間(= 約 430 円)
- Enterprise:$4.30 / 時間(= 約 640 円)
会社や実プロジェクトで使うのであれば予算もある程度あるのですが、個人で検証用に持っている環境(Snowflake アカウント)だと、とても怖い。
そこで日々の消費コストを監視するとともに、想定以上にコストが増えた場合に自動で通知や停止する仕組みを準備しておくことが重要になります。後者を実現する方法として Snowflake にはリソースモニターという機能があるので、それを個人の検証用 Snowflake アカウントに設定したいと思います。
ついでに、そろそろ Terraform での Snowflake 環境管理も学んでおきたいので、SQL ではなく Terraform でリソースモニターの設定を行いたいと思います。
加えて、こういうツールでは内部で Snowflake にどういうコマンドが発行されているか確認しないと気が済まないので、それも追いかけたいと思います。
2. 準備
この章は Terraform を Snowflake 用に使うための設定です。Terraform と Snowflake の経験がある方は読み飛ばして問題ありません。
今回、Terraform の CLI を Oracle Linux 9.2 にインストールして使いたいと思います。インストールは以下の [CentOS/RHEL] の通りに実施しました。
Terraform から Snowflake の接続ではキーペア認証を用いるので、Snowflake QuickStarts の以下を参考に Terraform 専用の Snowflake ユーザーの作成とキーペア認証の設定を行います。
Terraforming Snowflake - 3. Create a Service User for Terraform
この QuickStart では 仮想ウェアハウス/DB とその権限管理を行うため、SYSADMIN と SECURITYADMIN の2つのロール利用していますが、リソースモニターの作成は ACCOUNTADMIN ロールが必要なので、今回は ACCOUNTADMIN ロールを代わりに付与しています。
create user tf_snow
DEFAULT_ROLE=PUBLIC
MUST_CHANGE_PASSWORD=FALSE
RSA_PUBLIC_KEY= 'MIIBI...';
grant role accountadmin to user tf_snow;
Terraform から Snowflake への接続情報は .bash_profile に環境変数として設定しています。
export SNOWFLAKE_USER=tf_snow
export SNOWFLAKE_AUTHENTICATOR=JWT
export SNOWFLAKE_PRIVATE_KEY=`cat ~/.ssh/snowflake_tf_snow_key.p8`
export SNOWFLAKE_ACCOUNT="<組織名>-<アカウント名>"
最後に、Snowflake アカウントオーナーのユーザーのプロファイル設定画面で通知を有効化しておきます。
以上で準備は完了です。
3. 設定&確認
ファイル main.tf に以下の内容を記載します。
terraform {
required_providers {
snowflake = {
source = "Snowflake-Labs/snowflake"
version = "~> 0.87"
}
}
}
provider "snowflake" {
role = "ACCOUNTADMIN"
}
resource "snowflake_resource_monitor" "monitor" {
name = "account_credit_limit"
credit_quota = 3
frequency = "WEEKLY"
start_timestamp = "IMMEDIATELY"
notify_triggers = [1]
suspend_trigger = 80
suspend_immediate_trigger = 90
set_for_account = true
}
- Snowflake 用の Terraform Provider として
Snowflake-Labs/snowflake
を利用します。- Snowflake + Terraform に関するもう一つの Snowflake Quickstarts DevOps: Database Change Management with Terraform and GitHub では
chanzuckerberg/snowflake
を利用していますが、現時点では Snowflake-Labs の方に置き換わている?
- Snowflake + Terraform に関するもう一つの Snowflake Quickstarts DevOps: Database Change Management with Terraform and GitHub では
- リソースモニターの管理に利用するロールとして ACCOUNTADMIN を指定します。
- リソースモニタの設定は以下です。
- クレジットクォーター = 3, チェック頻度は週次 (WEEKLY) を選択します。
- 1週間で 1,000 円ちょっとぐらいなら良いかと思い、1,000円 ÷ 150円/ドル ÷ $2.85/credit = 約 2.3クレジットを目安にクォーターを設定しています。
-
start_timestamp = "IMMEDIATELY"
で監視を今すぐ開始します。 - クレジットを消費した際の動作を以下のようにしました。
- notify_triggers:クレジットクォーターの 1 % に達したらメールで通知する(通知のテストのため極端に低い値に設定)。
- suspend_trigger:クレジットクォーターの 80% に達したら仮想ウェアハウスを停止する。ただし実行中の処理があった場合は完了を待つ。
- suspend_immediate_trigger:クレジットクォーターの 90% に達したら仮想ウェアハウスを即時停止する(実行中の処理は強制終了)。
- リソースモニターはアカウントレベルで設定する ( = 全仮想ウェアハウス+クラウドサービスの消費クレジット合計が対象)。
- サーバーレスで消費するクレジットは対象外なので注意。
- クレジットクォーター = 3, チェック頻度は週次 (WEEKLY) を選択します。
ちなみに、Snowflake Providerのドキュメント では、Example Usage として suspend_triggers
と suspend_immediate_triggers
(複数形)を使っていますが、これは Deprecated のようです(そもそも複数のしきい値を設定する意味はないはずですが)。
main.tf を作成後、以下の手順を踏んで実行します。
terraform init -upgrade
terraform plan
terraform apply
適用後に少しクレジットを消費すると、以下のような通知がメールで届きます。
想定通り通知は動いているようなので、通知のしきい値を 50% に変更するため、main.tf に以下の変更を加え再実行します。
notify_triggers = [50]
terraform plan
terraform apply
4. 気になる点
Terraform を実行した際に内部で発行されている SQL 文を account_usage.query_history から確認しました。以下に発行されている SQL 文を示します。
-
SELECT 1
やSELECT CURRENT_ACCOUNT() as CURRENT_ACCOUNT
など影響のない SQL 文は除外します。 - 読みやすいように整形しています。
初回(通知しきい値 = 1%)
CREATE RESOURCE MONITOR "account_credit_limit"
WITH CREDIT_QUOTA = 3
FREQUENCY = WEEKLY
START_TIMESTAMP = 'IMMEDIATELY'
TRIGGERS
ON 80 PERCENT DO SUSPEND
ON 90 PERCENT DO SUSPEND_IMMEDIATE
ON 1 PERCENT DO NOTIFY
ALTER ACCOUNT SET RESOURCE_MONITOR = "account_credit_limit"
SHOW RESOURCE MONITORS LIKE 'account_credit_limit'
再実行(通知しきい値 = 50%)
ALTER RESOURCE MONITOR "account_credit_limit"
SET
FREQUENCY = WEEKLY
START_TIMESTAMP = 'IMMEDIATELY'
TRIGGERS
ON 80 PERCENT DO SUSPEND
ON 90 PERCENT DO SUSPEND_IMMEDIATE
ON 50 PERCENT DO NOTIFY
SHOW RESOURCE MONITORS LIKE 'account_credit_limit'
気になる点は以下3点です。
- 再実行で
FREQUENCY
とSTART_TIMESTAMP
が再設定- これは、監視期間の起点が再実行時にリセットされることを意味しています。通常では問題にはならないと思いますが、そういう挙動だと認識はしておいた方が良さそうです。
- 識別子が二重引用符付き
- つまり、大文字/小文字を区別するようになります。今回のリソースモニターの場合は問題にならないと思いますが、テーブル名やカラム名などでこれをやられると、対応していないサードパーティーツール(ETLツール、データカタログツールなど)があった時に悩ましいので、できれば回避したいところ。
-
SHOW RESOURCE MONITORS LIKE '...'
でエスケープ未処理- 現実としては滅多に問題にはならないですが、
account-credit-limit
というような識別子のリソースモニターもあった場合、SHOW コマンドは 2 件ヒットするはずなのですが(LIKE の_
は任意の1文字にマッチするため)、大丈夫なんでしょうか。
- 現実としては滅多に問題にはならないですが、
特に、2番目と3番目については回避できないか追加調査したいです。