【Databricks on AWS】コスト削減のためのクラスターポリシー設定例

## はじめに

Databricksクラスターの利用料金を最小化するためのカスタムポリシーを作成してみます。

:::note info
**Databricksクラスターポリシー**
Databricksクラスター(コンピュート)のポリシーとは、一言で言えばDatabricksのクラスター構成のテンプレート定義のことです。詳細についてはDatabricksの[公式ドキュメント](https://docs.databricks.com/ja/administration-guide/clusters/policies.html)やその[日本語記事](https://qiita.com/taka_yayoi/items/93d7597d7fc739b48bb7)をご参照ください。
:::

## デフォルトのクラスターポリシー

デフォルトのDatabricksクラスターのポリシー設定についての情報を記載します。

### ポリシーの種類(ファミリー)

Databricksのデフォルト設定では、汎用クラスター(all-purpose compute)用に下記の3種類のポリシーが定義されています。

1. パーソナルコンピュート(`Personal Compute`)
2. パワーユーザーコンピュート(`Power User Compute`)
3. 共有コンピュート(`Shared Compute`)

このうち、`Personal Compute`以外のポリシー(`Power User Compute`と`Shared Compute`)は、複数台サーバを前提としたDriver-Worker構成であるため最小の利用料金が高くなります。今回はコスト最小化のために、単独サーバで実行可能な`Personal Compute`ポリシーを継承してカスタムポリシーを作成します。

### デフォルト設定

Personal Computeのデフォルトのポリシー設定は、2024年4月時点で下記となっています。

| 項目 | 設定値 |備考|
|:-:|:-:|:--|
|Databricks Runtimeの<br>バージョン|Runtime: 15.0 ML|Scala 2.12, Spark 3.5.0|
| ノードタイプ | i3.xlarge  |i3.xlarge: メモリ 30.5GB, CPU 4コア, 1 DBU/hr|
| 非アクティブ状態が`X`分<br>継続した後に終了  | 4,320  |4,320分 = 72時間(3日)|

![00_default_personal_compute_policy.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/315655/93185f8e-891d-0e0b-99a0-799381beb80b.png)

このデフォルトのポリシー設定のままクラスターを立ち上げて、クラスターが自動終了するまで放置した場合にかかる料金を計算すると、下記のようになります。

([EC2料金] + [DBU] * [DBU料金] ) * [起動時間]
$= (\\$0.366/hr + 1.0 DBU/hr * \\$0.65/hr) * 72hr$
$= \\$1.016/hr * 72hr$
$= \\$73.152$
$≒ 10972.8円$ (1ドル150円換算)

この計算式では、下記の設定値および価格を前提として計算しています。

|項目| 種類 | 設定値 | 価格 | 備考 |
|:-:|:-:|:-:|:-:|:-:|
|EC2料金| Amazon EC2<br>インスタンスタイプ  | i3.xlarge  | $0.366/hr  | AWSリージョン: 東京(`ap-northeast-1`) |
|DBU| Databricksクラスターノードタイプ  | i3.xlarge  | 1.0 DBU/hr  | - |
|DBU料金| Databricksコンピュートタイプ  | 汎用コンピュート(`All-purpose Compute`)  | $0.65/DBU  | Databricks on AWS Enterpriseプラン  |

DBU(`DataBricks Unit`)はDatabricksのライセンス料金の単位です。なお、Databricksクラスターに関して、EBSやネットワーク通信にかかるAWSの費用は微小と考えられるためこの計算式には含めていません。

:::note warn
正確な料金については、公式のDatabricksおよびAWSのサイトをご確認ください。

- [Databricks料金計算ツール](https://www.databricks.com/jp/product/pricing/product-pricing/instance-types)
- [Amazon EC2オンデマンド料金](https://aws.amazon.com/jp/ec2/pricing/on-demand/)
:::

もちろん、このデフォルトのクラスターポリシーを利用していても、Databricks利用者がクラスター作成時に必要最小限のサイズ・自動終了時間となるように都度手動で設定すれば、必要以上の料金の発生を抑えることができます。しかし、利用者がうっかりデフォルト設定のままクラスターを作成してしまい放置したままにすると、意図せずに1万円以上もの課金が発生する可能性が想定されることになります。


## カスタムポリシー設定

このような意図しないクラスター課金の発生を、カスタムポリシーの利用により防ぎたいと思います。カスタムポリシーの作成方法としては、既存の`Personal Compute`ポリシーの設定を、デフォルトが最小コストの設定となるようにオーバーライドする方法で作成します。

### オーバーライド設定

既存の`Personal Compute`ポリシーの設定値に対して、下記のJSONにより`node_type_id`, `spark_version`, `autotermination_minutes`の3つのパラメータをオーバーライドします。

```json:cluster_policy_override.json
{
  "node_type_id": {
    "type": "allowlist",
    "values": [
      "m5.large",
      "m5d.large",
      "m5d.xlarge",
      "m5d.2xlarge",
      "r5d.large",
      "r5d.xlarge",
      "r5d.2xlarge",
      "i3.xlarge",
      "i3.2xlarge",
      "g4dn.xlarge",
      "g4dn.2xlarge"
    ],
    "defaultValue": "m5.large"
  },
  "spark_version": {
    "type": "unlimited",
    "defaultValue": "auto:latest-lts-ml"
  },
  "autotermination_minutes": {
    "type": "unlimited",
    "defaultValue": 10,
    "isOptional": true
  }
}
```

各パラメータ設定の意味は下記の通りです。設定可能なパラメータ一覧やその詳細については、[databricks公式リファレンス](https://docs.databricks.com/ja/administration-guide/clusters/policy-definition.html)をご参照ください。


#### node_type_id

クラスターのノードタイプ(EC2インスタンスタイプ)を設定します。今回の例では、クラスター作成時に下表のノードタイプ一覧からリスト形式で利用者が好きなノードタイプを選択可能にしています。

| ノードタイプ |  vCPU | メモリ| EC2料金 | Databricks料金 | デフォルト|
|:-:|:-:|:-:|:-:|:-:|:-:|
| m5.large |   2  | 8 GiB |$ 0.124 /hr  | 0.34 DBU/hr |〇|
| m5d.large |   2  | 8 GiB |$ 0.146 /hr | 0.34 DBU/hr |-| 
| m5d.xlarge |   4  | 16 GiB |$ 0.292 /hr | 0.69 DBU/hr |-| 
| m5d.2xlarge |   8  | 32 GiB |$ 0.584 /hr | 1.37 DBU/hr |-| 
| r5d.large  |  2  | 16 GiB  |$ 0.174 /hr | 0.45 DBU/hr |-|
| r5d.xlarge  |  4  | 32 GiB   |$ 0.348 /hr | 0.90 DBU/hr |-|
| r5d.2xlarge  |  8  | 64 GiB  |$ 0.696 /hr | 1.80 DBU/hr |-|
| i3.xlarge  |  4  | 30.5 GiB |$ 0.366 /hr | 1.00 DBU/hr  |-|
| i3.2xlarge  |  8  | 61 GiB |$ 0.732 /hr | 2.00 DBU/hr  |-|
| g4dn.xlarge  |  4  | 16 GiB |$ 0.710 /hr | 0.71 DBU/hr |-|
| g4dn.2xlarge  |  8  | 32 GiB |$ 1.015 /hr | 1.43 DBU/hr |-|

:::note warn
正確な料金については、公式のDatabricksおよびAWSのサイトをご確認ください。

- [Databricks料金計算ツール](https://www.databricks.com/jp/product/pricing/product-pricing/instance-types)
- [Amazon EC2オンデマンド料金](https://aws.amazon.com/jp/ec2/pricing/on-demand/)
:::

上表のノードタイプ一覧は、下記の観点から私の独断と偏見で選定しました。

- databricks利用者自身が重視したいリソースに応じて多様性を持たせる(m系は汎用、r系はメモリ重視、i系はストレージ重視、g系はGPU搭載)
- `2xlarge`よりも大きいサイズは料金が高いため選択不可とし、利用希望時はDatabricksワークスペース管理者に相談する運用とする。
- `m5.large`以外は、Databricksの[ディスクキャッシュ機能](https://docs.databricks.com/ja/optimizations/disk-cache.html)が有効な`d`付きのノードタイプを選択する。
- デフォルト設定のノードタイプは、最もコストが安い`m5.large`とする。

#### spark_version

Databricksランタイムバージョンを設定します。私はLTS(`Long-Term Support`)のバージョンが好みなので、デフォルトで機械学習向けDatabricksランタイムの最新のLTSのバージョンが選択されるように、`defaultValue`項目値を`auto:latest-ml`から`auto:latest-lts-ml`に変更します。本項目はクラスター利用料金には影響しません。

#### autotermination_minutes

クラスターの自動停止時間を設定します。今回は最小の10分に設定します。


## カスタムポリシー作成手順

実際に、上記の設定を持つカスタムポリシーを作成してみます。

:::note warn
**ワークスペース管理者権限**
本手順でカスタムポリシーを作成するには、Databricksのワークスペース管理者権限が必要です。
:::


### ポリシー一覧画面

1. 左メニューの「クラスター」を選択し、クラスター管理画面に遷移します。
2. クラスター画面の「ポリシー」タブを選択し、ポリシー一覧を表示します。
3.  右上の「ポリシーを作成」ボタンをクリックします。

![10_create_policy.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/315655/e2214cc7-8a87-8ea3-ad27-2d313ff8d21a.png)

### ポリシー作成画面

1. 「ファミリー」のプルダウンリストから、「`パーソナルコンピューティング`」を選択します。
2. 「Name」に適当なポリシー名を入力します。(今回は「Custom Personal Compute」)
3. 「定義」タブ内の、「0件のオーバーライド 編集」をクリックします。

![20_create_custom_policy.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/315655/e110e240-3caa-0988-bcdb-3d545d70dffb.png)

4\. 本記事の[オーバーライド設定](#オーバーライド設定)に記載のJSONをコピペして貼り付けます。(JSONの内容は好きにカスタマイズしてください。)

![create_custom_policy_02.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/315655/c38a12e0-1e15-dd67-0a13-632537bbe38a.png)

5\. 「定義」タブの「N件のオーバーライド 編集」の数字が変わり(今回は3件)、JSON設定がオーバーライドされたことを確認します。

![create_custom_policy.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/315655/d0c266f4-03c4-16ed-e7d6-0e70223faa43.png)

6\. 「権限」タブで、 ポリシー利用ユーザ(今回は「`All Users`」)への「`使用可能`」権限を追加します。
7. 画面右上の「更新」ボタンをクリックして、カスタムポリシーを作成します。

![40_create_add_custom_policy_privilege.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/315655/11f5e51b-4fe5-c143-50ae-49817a5a676f.png)


### 結果確認

上記手順作成したカスタムポリシーを利用してクラスターを作成すると、クラスター作成画面のデフォルト値は下記のようになります。

| 項目 | 設定値 |備考|
|:-:|:-:|:--|
|Databricks Runtimeの<br>バージョン|Runtime: 14.3 LTS ML|Scala 2.12, Spark 3.5.0|
| ノードタイプ | m5.large  |m5.large: メモリ 8GB, CPU 2コア, 0.34 DBU/hr|
| 非アクティブ状態が`X`分<br>継続した後に終了  | 10  |10分 = 0.166... 時間|

![create_cluster_with_custom_policy.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/315655/deeb83d1-f44a-fe35-0e94-23838490a2a0.png)

このカスタムポリシーのデフォルト設定値のままクラスターを立ち上げて、クラスターが自動終了するまで放置した場合にかかる料金を計算すると、下記のようになります。

([EC2料金] + [DBU] * [DBU料金] ) * [起動時間]
$= (\\$0.124/hr + 0.34 DBU/hr * \\$0.65/hr) * 10/60 hr$
$= \\$0.345/hr * 10/60 hr$
$= \\$0.0575$
$≒ 8.625円$ (1ドル150円換算)

この計算式では、下記の設定値および価格を前提として計算しています。

|項目| 種類 | 設定値 | 価格 | 備考 |
|:-:|:-:|:-:|:-:|:-:|
|EC2料金| Amazon EC2<br>インスタンスタイプ  | m5.large  | $0.366/hr  | AWSリージョン: 東京(`ap-northeast-1`) |
|DBU| Databricksクラスターノードタイプ  | m5.large  | 0.34 DBU/hr  | - |
|DBU料金| Databricksコンピュートタイプ  | 汎用コンピュート(`All-purpose Compute`)  | $0.65/DBU  | Databricks on AWS Enterpriseプラン  |

このように、ポリシーのデフォルト値でクラスターを作成してクラスター停止し忘れた場合にかかる料金を、同じ条件で`10972.8`円から`8.625`円まで千分の一以下に減らすことができました。

## さいごに

databricksカスタムポリシーは積極的に利用すると良いと思います。