LoginSignup
0

More than 1 year has passed since last update.

Databricksクラスターノード初期化スクリプト

Posted at

Cluster node initialization scripts | Databricks on AWS [2022/2/1時点]の翻訳です。

本書は抄訳であり内容の正確性を保証するものではありません。正確な内容に関しては原文を参照ください。

initスクリプトは、Apache SparkのドライバーやワーカーのJVMがスタートする前にそれぞれのクラスターノードのスタートアップの際に実行されるシェルスクリプトです。

initスクリプトで実行されるタスクの例には以下のようなものがあります。

  • Databricksランタイムに含まれていないパッケージ、ライブラリをインストールします。Pythonライブラリをインストールするには、システムのPython環境ではなく、DatabricksのPython仮想環境にインストールされるように、/databricks/python/bin/pipにあるpipバイナリーを使用します。
  • 特殊なケースでJVMのシステムクラスパスを変更します。
  • JVMで使用されるシステムプロパティ、環境変数を設定します。
  • Spark設定パラメーターを変更します。

initスクリプトのタイプ

Databricksには、クラスタースコープとグローバルの2種類のinitスクリプトが存在します。

  • クラスタースコープ: スクリプトが設定された全てのクラスターで実行されます。initスクリプトを実行する際のお勧めの方法となります。
  • グローバル: ワークスペースのすべてのクラスターで実行されます。これは、ワークスペース全体で一貫性のある設定を適用する際に役立ちます。しかし、ライブラリの競合など予期しないインパクトが起こり得るので、使用する際には注意してください。管理ユーザーのみがグローバルinitスクリプトを作成できます。グローバルinitスクリプトはモデルサービングのクラスターでは実行されません。

注意
利用を推奨しない古いinitスクリプトが2種類存在します。以下の種類のinitスクリプトは移行することをお勧めします。

  • クラスター指定: スクリプトと同じ名前のクラスターで実行されます。クラスター指定initスクリプトはベストエフォート(サイレントに失敗を無視します)であり、クラスター起動プロセスを続行しようとします。代わりにクラスタースコープを使用すべきであり、完全に置き換えるものとなっています。
  • レガシーグローバル: すべてのクラスターで実行されます。新たなグローバルinitスクリプトフレームワークよりもセキュアではなく、サイレントにエラーを無視し、環境変数を参照することができません。既存のレガシーグローバルinitスクリプトを新たなinitスクリプトフレームワークに移行すべきです。レガシーグローバルinitスクリプトから新しいグローバルinitスクリプトへの移行を参照ください。

initスクリプトのタイプを変更した際には、スクリプトを有効にするために全てのクラスターを再起動する必要があります。

initスクリプトの実行順序

initスクリプトの実行順序は以下のようになります。

  1. レガシーグローバル (非推奨)
  2. クラスター指定 (非推奨)
  3. グローバル (新世代)
  4. クラスタースコープ

環境変数

クラスタースコープ、グローバルinitスクリプト(新世代)では、以下の環境変数をサポートしています。

  • DB_CLUSTER_ID: スクリプトが実行されrているクラスターのIDです。Clusters API 2.0を参照ください。
  • DB_CONTAINER_IP: Sparkが実行されているコンテナーのプライベートIPアドレスです。SparkNodeを参照ください。
  • DB_IS_DRIVER: スクリプトがドライバーノードで実行されているかどうかを示します。
  • DB_DRIVER_IP: ドライバーノードのIPアドレスです。
  • DB_INSTANCE_TYPE: ホストVMのインスタンスタイプです。
  • DB_CLUSTER_NAME: スクリプトが実行されているクラスター名です。- DB_PYTHON_VERSION: クラスターで使用されているPythonのバージョンです。
  • DB_IS_JOB_CLUSTER: クラスターがジョブを実行するために作成されたかどうかを示します。ジョブの作成を参照ください。
  • SPARKPASSWORD: シークレットへのパスです。

例えば、ドライバーノードでのみスクリプトのある部分を実行したい場合には、以下のようなスクリプトを記述します。

Bash
echo $DB_IS_DRIVER
if [[ $DB_IS_DRIVER = "TRUE" ]]; then
  <run this part only on driver>
else
  <run this part only on workers>
fi
<run this part on both driver and workers>

ログ

initスクリプトの起動、終了のイベントはクラスターのイベントログで捕捉されます。詳細はクラスターログに記録されます。グローバルinitスクリプトの作成、編集、削除のイベントはアカウントレベルの監査ログでも記録されます。

initスクリプトのイベント

クラスターイベントログは2つのinitスクリプトのイベントを捕捉します。そのスクリプトの実行がスケジュールされたのか、どのスクリプトの処理が成功したのかを示すINIT_SCRIPTS_STARTEDINIT_SCRIPTS_FINISHEDです。INIT_SCRIPTS_FINISHEDでは実行期間も記録されます。

グローバルinitスクリプトはログの詳細では"global"のキーで表示され、クラスタースコープinitスクリプトは"cluster"で表示されます。

注意
クラスターイベントログにはそれぞれのクラスターノードのinitスクリプトのイベントは記録されません。1つのノードのみが選択され、それが全体を代表します。

initスクリプトのログ

クラスターでクラスターログデリバリーが設定されると、initスクリプトのログは/<cluster-log-path>/<cluster-id>/init_scriptsに書き込まれます。クラスターのそれぞれのコンテナーのログはinit_scripts/<cluster_id>_<container_ip>というサブディレクトリに格納されます。例えば、cluster-log-pathcluster-logsが設定されると、特定のコンテナーに対応するログのパスはdbfs:/cluster-logs/<cluster-id>/init_scripts/<cluster_id>_<container_ip>となります。

クラスターがログをDBFSに書き込むように設定されている場合、File system utility (dbutils.fs)DBFS CLIを用いてログを参照することができます。例えば、クラスターIDが1001-234039-abcde739の場合、以下を実行します。

Bash
dbfs ls dbfs:/cluster-logs/1001-234039-abcde739/init_scripts
1001-234039-abcde739_10_97_225_166
1001-234039-abcde739_10_97_231_88
1001-234039-abcde739_10_97_244_199
Bash
dbfs ls dbfs:/cluster-logs/1001-234039-abcde739/init_scripts/1001-234039-abcde739_10_97_225_166
<timestamp>_<log-id>_<init-script-name>.sh.stderr.log
<timestamp>_<log-id>_<init-script-name>.sh.stdout.log

クラスターログデリバリーが設定されていない場合、ログは/databricks/init_scriptsに書き込まれます。ログを一覧、参照するためにノートブックで標準シェルコマンドを使用することができます。

Bash
%sh
ls /databricks/init_scripts/
cat /databricks/init_scripts/<timestamp>_<log-id>_<init-script-name>.sh.stdout.log

クラスターが起動する度、initスクリプトのログフォルダにログが書き込まれます。

重要!
クラスターを作成し、クラスターログデリバリーを有効化したユーザーはグローバルinitスクリプトのstderrstdout出力を参照することができます。お使いのグローバルinitスクリプトから機微な情報を出力させないようにしてください。

監査ログ

Databricksの監査ログは、イベントタイプglobalInitScriptsでグローバルinitスクリプトの作成、編集、削除イベントを捕捉します。Configure audit loggingを参照ください。

クラスタースコープinitスクリプト

クラスタースコープinitスクリプトはクラスター設定で定義されます。クラスタースコープinitスクリプトは作成したクラスター、ジョブを実行するクラスターの両方に適用されます。スクリプトはクラスター設定の一部なので、クラスターアクセスコントロールでスクリプトを変更できる人を制御することができます。

UI、CLIを用いて、あるいはClusters APIを呼び出すことでクラスタースコープinitスクリプトを設定することができます。このセクションではUIによる設定方法にフォーカスします。他の方法に関しては、Databricks CLIClusters API 2.0を参照ください。

任意の数のスクリプトを追加することができ、指定された順にスクリプトは実行されます。

クラスタースコープinitスクリプトが非ゼロの結果を返した場合、クラスターの起動は失敗します。クラスターログデリバリーを設定し、initスクリプトログを検証することで、クラスタースコープinitスクリプトをデバッグすることができます。

クラスタースコープinitスクリプトの場所

initスクリプトをクラスターがアクセスできるDBFS、S3のディレクトリに格納することができます。DBFS内のクラスターノードのinitスクリプトはDBFSルートに格納されている必要があります。Databricksでは、オブジェクトストレージをマウントすることで作成されたDBFSディレクトリへのinitスクリプトの格納をサポートしていません

クラスタースコープinitスクリプトのサンプル

このセクションではinitスクリプトの2つの例を説明します。

サンプル:PostgreSQL JDBCドライバーのインストール

以下のスニペットをPythonノートブックで実行すると、PostgreSQL JDBCドライバーをインストールするinitスクリプトを作成します。

  1. initスクリプトを格納するDBFSディレクトリを作成します。この例ではdbfs:/databricks/scriptsを使用します。

    Python
    dbutils.fs.mkdirs("dbfs:/databricks/scripts/")
    
  2. 上記のディレクトリにpostgresql-install.shというスクリプトを作成します。

    Python
    dbutils.fs.put("/databricks/scripts/postgresql-install.sh","""
    #!/bin/bash
    wget --quiet -O /mnt/driver-daemon/jars/postgresql-42.2.2.jar https://repo1.maven.org/maven2/org/postgresql/postgresql/42.2.2/postgresql-42.2.2.jar""", True)
    
  3. スクリプトが存在することを確認します。

    Python
    display(dbutils.fs.ls("dbfs:/databricks/scripts/postgresql-install.sh"))
    

あるいは、ローカルでinitスクリプトpostgresql-install.shを作成することもできます。

Bash
#!/bin/bash
wget --quiet -O /mnt/driver-daemon/jars/postgresql-42.2.2.jar https://repo1.maven.org/maven2/org/postgresql/postgresql/42.2.2/postgresql-42.2.2.jar

そして、DBFS CLIを用いてdbfs:/databricks/scriptsにコピーします。

Bash
dbfs cp postgresql-install.sh dbfs:/databricks/scripts/postgresql-install.sh

サンプル:Pythonライブラリのインストールにcondaを使う

Databricksランタイム9.0以降では、Pythonライブラリのインストールにcondaを使うことができません。クラスターへのPythonパッケージのインストール方法については、ライブラリを参照ください。

重要!
Anaconda, Inc.は2020年9月に利用規約をアップデートしています。Anacondaのパッケージ、ディストリビューションに依存している場合、新たな利用規約によりcommercial licenseが必要になる場合があります。詳細はAnaconda Commercial Edition FAQを参照ください。お使いのAnacondaチャンネルは利用規約によって管理されます。

この変更によって、DatabricksはCondaパッケージマネージャーのデフォルトチャンネルを削除しました。これは破壊的変更です。initスクリプトでcondaコマンドを使用する際には、-cでチャンネルを指定するようにアップデートする必要があります。チャンネルを指定しない場合、condaコマンドはPackagesNotFoundErrorで失敗します。

Databricks 8.4ML以下では、PythonパッケージのインストールにCondaパッケージマネージャを使用します。クラスター初期化の際にPythonライブラリをインストールするには、以下のようなスクリプトを使用します。

Bash
#!/bin/bash
set -ex
/databricks/python/bin/python -V
. /databricks/conda/etc/profile.d/conda.sh
conda activate /databricks/python
conda install -c conda-forge -y astropy

クラスタースコープinitスクリプトの設定

UIあるいはAPIを用いてinitスクリプトを実行するようにクラスターを設定することができます。

重要!

  • スクリプトが指定された場所に存在する必要があります。スクリプトが存在しない場合、クラスターが起動する際、あるいはオートスケールする際に失敗します。
  • initスクリプトを64KBより大きくすることはできません。このサイズを超えると、クラスターは起動に失敗し、クラスターログにエラーメッセージが表示されます。

UIによるクラスタースコープinitスクリプトの設定

initスクリプトを実行するようにクラスター設定ページで設定を行うには、以下の手順を踏みます。

  1. クラスター設定ページでAdvanced Optionsを展開します。
  2. ページの下部でInit Scriptsタブをクリックします。
  3. Destinationドロップダウンで、格納場所のタイプを選択します。上述した例では、格納場所はDBFSとなります。
  4. initスクリプトのパスを指定します。この例では、dbfs:/databricks/scripts/postgresql-install.shとなります。
  5. 格納場所がS3の場合:

    1. リージョンを選択します。
    2. 以下のように、アクセスするバケットに対してgetObjectAcl権限を持つインスタンスプロファイルがクラスターに設定されていることを確認します。
    JSON
    {
    "Version": "2012-10-17",
    "Statement": [
    {
      "Effect": "Allow",
      "Action": [
        "s3:getObjectAcl"
      ],
      "Resource": [
        "arn:aws:s3:::<my-s3-bucket>/*"
      ]
    }
    ]
    }
    
  6. Addをクリックします。

クラスター設定からスクリプトを削除するには、スクリプトの右にあるをクリックします。削除を確認すると、クラスターを再起動するように指示されます。任意で、アップロードした場所からスクリプトファイルを削除することができます。

DBFS REST APIによるクラスタースコープinitスクリプトの設定

Clusters API 2.0を用いて、クラスターID1202-211320-brick1のクラスターでinitスクリプトを実行するように設定するには以下のコマンドを実行します。

Bash
curl -n -X POST -H 'Content-Type: application/json' -d '{
  "cluster_id": "1202-211320-brick1",
  "num_workers": 1,
  "spark_version": "7.3.x-scala2.12",
  "node_type_id": "i3.2xlarge",
  "cluster_log_conf": {
    "dbfs" : {
      "destination": "dbfs:/cluster-logs"
    }
  },
  "init_scripts": [ {
    "dbfs": {
      "destination": "dbfs:/databricks/scripts/postgresql-install.sh"
    }
  } ]
}' https://<databricks-instance>/api/2.0/clusters/edit

グローバルinitスクリプト

グローバルinitスクリプトはお使いのワークスペースのすべてのクラスターで実行されます。グローバルinitスクリプトは、企業全体でライブラリの設定やセキュリティ対策を強制したい場合に役立ちます。管理者のみがグローバルinitスクリプトを作成できます。UI、REST APIを用いて作成することができます。

重要!
グローバルinitは注意して使用してください。

  • 予期しないインパクトをもたらすライブラリの追加や変更を行えてしまいます。可能であれば、クラスタースコープinitスクリプトを使うようにしてください。
  • クラスターを作成し、クラスターログデリバリーを有効化したユーザーはグローバルinitスクリプトのstderrstdout出力を参照することができます。お使いのグローバルinitスクリプトから機微な情報を出力させないようにしてください。

クラスターログデリバリーを設定し、initスクリプトログを検証することで、グローバルinitスクリプトをデバッグすることができます。

UIによるグローバルinitスクリプトの追加

Admin Consoleを用いてグローバルinitスクリプトを設定します。

  1. Admin Consoleにアクセスして、Global Init Scriptsタブをクリックします。

  2. + Addボタンをクリックします。

  3. スクリプト名を入力し、テキストファイルをScriptフィールドにドラッグアンドドロップします。

    注意
    このinitスクリプトを64KB以上にすることはできません。サイズを超えると、保存しようとした際にエラーメッセージが表示されます。

  4. ワークスペースで2個以上のグローバルinitスクリプトを設定したい場合、実行順にスクリプトを並べます。

  5. 保存後にすべての新規クラスター、再起動されたクラスターにスクリプトを適用したい場合には、Enabledスイッチを切り替えます。

    重要!
    実行順序、名前、有効化状態を含むグローバルinitスクリプトを反映させるには、稼働中のクラスターを再起動する必要があります。

  6. Addをクリックします。

UIによるグローバルinitスクリプトの設定

  1. Admin Consoleに移動し、Global Init Scriptsタブをクリックします。
  2. スクリプトをクリックします。
  3. スクリプトを編集します。
  4. Confirmをクリックします。

APIによるグローバルinitスクリプトの設定

Global Init Scripts API 2.0を用いて、管理者はワークスペースのグローバルinitスクリプトの追加、削除、並び替え、情報の取得を行うことができます。

レガシーグローバルinitスクリプトから新しいグローバルinitスクリプトへの移行

お使いのDatabricksワークスペースが2020年8月以前にデプロイされた場合、レガシーなグローバルinitが存在する可能性があります。次世代スクリプトフレームワークに含まれるセキュリティ、一貫性、可視性の機能を活用できるようにこれらのスクリプトを次世代グローバルinitスクリプトフレームワークに移行すべきです。

  1. UIREST APIのいずれかを用いて、レガシーグローバルinitスクリプトをコピーし、次世代グローバルinitスクリプトフレームワークに追加します。

    次のステップを完了するまで、これらを無効化しておきます。

  2. レガシーグローバルinitスクリプトを無効化します。

    Admin ConsoleでGlobal Init Scriptsに移動し、Legacy Global Init Scriptsスイッチをオフにします。

  3. 次世代グローバルinitスクリプトを有効にします。

    Global Init Scriptsタブで、有効化したいinitスクリプトのEnabledスイッチをオンにします。

  4. すべてのクラスターを再起動します。

    • 稼働中のクラスターにおける自動スケールアップで追加された新規ノードではレガシースクリプトは実行されません。これらの新規ノードでは次世代initスクリプトも実行されません。これらのノードで新規スクリプトが実行され、クラスターがグローバルスクリプトなしの新規ノードを追加しないようにするために、すべてのクラスターを再起動してください。
    • 冪等性のないスクリプトにおいては、次世代initグローバルスクリプトフレームワークに移行し、レガシーなスクリプトを無効化する際には変更が必要になる場合があります。

Databricks 無料トライアル

Databricks 無料トライアル

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
What you can do with signing up
0