Lifematics Corporate Blog

Lifematics社のコーポレートブログへようこそ!

JWT認証から始めるSlurm REST API実践ガイド:安全なジョブ投入とシステム連携のステップ

皆さん、こんにちは!

HPCクラスターの運用において、「ジョブ状況を外部システムと連携したい」「可視化ダッシュボードを作成したい」「CLIコマンドラインインターフェース)に縛られず自動化したい」といった高度なニーズが出てくることもあります。

今回は、これらの課題を解決し、Slurmクラスターをより柔軟かつ効率的に運用するために非常に強力なツールとなる、SlurmのREST API(slurmrestd)の活用方法とメリットについて、実際の運用目線でご紹介します。

Slurm REST API を使うメリット

Slurm REST API(slurmrestd)を活用することで、従来のCLIベースの運用では難しかった柔軟なシステム連携と高い保守性を実現できます。

1. 外部ツールと柔軟に連携できる
REST APIでは、ジョブ情報や操作をHTTP経由で扱うことができます。
この特性により、Webアプリケーション、カスタムダッシュボード、さらには外部サービス(CI/CDツールや可視化ツールなど)とSlurmを直接つなげられるようになります。
CLI前提の制約がなくなるため、システム統合が格段に簡単になります。

2. 自動化しやすい(スクリプト・外部サービス)
APIにリクエストを送るだけで、ジョブの投入、状態取得、キャンセルといった操作が可能です。
このため、Python、Go、Node.jsなど、任意のプログラミング言語で自動化スクリプトや運用フローを簡単に作成できます。
CLI出力のパース(解析)が不要になるため、スクリプトの保守性も向上します。

3. JSON形式で機械可読なデータを取得できる
ジョブ一覧やノード情報などのSlurmデータを、構造化されたJSON形式で取得できます。
これはプログラムで非常に扱いやすく、取得したデータを可視化、分析、またはログ処理にそのまま活用できるという大きな利点があります。
テキスト出力と比較して、連携の容易さは圧倒的です。

実際の運用例:API経由でのジョブ実行と認証

Slurm REST API経由でジョブを実行するには、通常、JWT(JSON Web Token)認証を使用します。

1. JWTトークンによる認証設定
API利用の際は、ユーザー名とパスワードを毎回送信するBasic認証よりも、有効期限や権限情報を含められるJWT(トークン)認証が一般的です。
ジョブ投入を行うユーザー(例:life)として、Slurm Controllerへログインし、JWTトークンを取得します。
有効期限を無制限にしたい場合は、lifespan=infiniteを指定してトークンを生成できます。

 # JWTトークンを取得
 life@control1:~$ unset SLURM_JWT;export $(scontrol token lifespan=infinite)

 # トークン文字列を確認
 life@control1:~$ echo $SLURM_JWT
 eyJhbGciOiJIUzI1NiIsInR5cCI6IkpX(以下略)

取得したJWTトークンは、Slurm REST APIを実行するサーバー上で環境変数 $SLURM_JWT に設定します。

2. JSONファイルでのジョブ定義
ジョブ投入に必要な設定(タスク数、ノード数、パーティション、作業ディレクトリ、環境変数、実行スクリプト)をJSONファイルで定義します。
例えば、testjob.json ファイルでは、job フィールド内にタスク数、ノード数、ジョブ名、パーティション、作業ディレクトリ、環境変数(PATHやLD_LIBRARY_PATH)を指定し、script フィールドに実行するシェルスクリプトのパス(例: /home/life/testjob.sh)を指定します。

 {
  "job":{
      "tasks":1,
      "name":"testjob",
      "nodes":1,
      "partition":"cpu-L",
      "current_working_directory":"/home/life",
      "environment":{
          "PATH":"/usr/local/slurm/24.11/bin:/usr/local/slurm/24.11(以下略)",
          "LD_LIBRARY_PATH":"/usr/local/slurm/24.11/lib/:/lib/:/lib(以下略)"
      }
  },
  "script":"#!/bin/bash /home/life/testjob.sh"
 }

この例では、tasks:1でプロセス1つ、nodes:1でノード1台を使用する設定となっています。

3. curlコマンドによる実行

curlコマンドを使用し、JSONファイルをデータとして渡し、JWTトークンをHTTPヘッダ(X-SLURM-USER-TOKEN)に含めてAPIエンドポイントにPOSTリクエストを送ることで、ジョブが投入されます。

 [root@othersrv01 ~]# curl -H X-SLURM-USER-TOKEN:$SLURM_JWT -H "Content-Type: application/json" -d @testjob.json -X POST 'http://slurmcontrol:6820/slurm/v0.0.42/job/submit'

この実行により、ジョブがキューに追加されます。

重要なセキュリティと権限管理

Slurm REST API経由でジョブを実行する際、curlコマンドで指定するJWTトークンに紐づいたユーザー権限でジョブが実行されます。

例えば、ユーザー:ogaが取得したJWTトークンを使用して、ユーザー:lifeのホームディレクトリ (/home/life) を作業ディレクトリとするジョブを実行しようとした場合、ジョブは実行されずにFAILEDとなります。
これは、トークンが認証情報として機能し、ユーザーごとの権限が適切に適用されていることを示しています。

APIを利用した状態取得の例(Python

APIの利点であるJSON形式のデータ取得を活用し、Pythonでノード情報を取得し、sinfo形式で見やすく表示するツールを作成できます。

Pythonプログラムでは、環境変数SLURM_JWTからJWTを取得し、/slurm/v0.0.42/nodesエンドポイントにHTTP GETリクエストを送信します。

取得したJSONデータから、ノード名、状態、CPU総数、割り当て済みメモリなどを抽出し、tabulateライブラリなどを使って表形式で整形・表示できます。
これにより、CLIを使わずに、外部システム上でリアルタイムかつ機械可読なノード情報を取得・表示することが可能です。

 # vi slurm_nodeinfo.py

 #!/usr/bin/env python3
 import requests
 import os
 from tabulate import tabulate

 # -----------------------------
 # 環境変数から JWT を取得
 # -----------------------------
 SLURM_JWT = os.environ.get("SLURM_JWT")
 if not SLURM_JWT:
     raise RuntimeError("環境変数 SLURM_JWT が設定されていません。scontrol token generate で生成してください。")

 # -----------------------------
 # REST API エンドポイント設定
 # -----------------------------
 SLURMREST_URL = "http://slurmcontrol:6820/slurm/v0.0.42/"
 SINFO_ENDPOINT = SLURMREST_URL + "nodes"

 # -----------------------------
 # HTTP ヘッダ設定
 # -----------------------------
 headers = {
     "X-SLURM-USER-TOKEN": SLURM_JWT,
     "Accept": "application/json"
 }

 # -----------------------------
 # API 呼び出し
 # -----------------------------
 try:
     response = requests.get(SINFO_ENDPOINT, headers=headers, verify=False)
     response.raise_for_status()
 except requests.exceptions.RequestException as e:
     print(f"Error connecting to Slurm REST API: {e}")
     exit(1)

 # -----------------------------
 # JSON を解析して sinfo 形式で表示
 # -----------------------------
 data = response.json()
 table = []

 for node in data.get("nodes", []):
     state = ",".join(node.get("state", []))  # リストを文字列に変換
     cpus_total = node.get("cpus", 0)
     cpus_alloc = node.get("cpus", 0) - node.get("alloc_idle_cpus", 0)  # 使用中CPU
     cpus_idle = node.get("alloc_idle_cpus", 0)
     cpus_other = cpus_total - cpus_alloc - cpus_idle
     mem_total = node.get("real_memory", "")
     mem_alloc = node.get("alloc_memory", 0)
     mem_free = node.get("free_mem", {}).get("number", 0)

     table.append([
         node.get("name", ""),
         state,
         cpus_total,
         cpus_alloc,
         cpus_idle,
         cpus_other,
         mem_total,
         mem_alloc,
         mem_free
     ])

 # 列ヘッダ
 headers_tab = ["NODELIST", "STATE", "CPUS", "CPUS(A)", "CPUS(I)", "CPUS(O)", "MEM(TOTAL)", "MEM(A)", "MEM(FREE)"]

 # 表示
 print(tabulate(table, headers=headers_tab, tablefmt="pretty"))

Pythonプログラム実行

 # chmod +x /root/slurm_nodeinfo.py

 # /root/slurm_nodeinfo.py
 +----------+-------+------+---------+---------+---------+------------+--------+-----------+
 | NODELIST | STATE | CPUS | CPUS(A) | CPUS(I) | CPUS(O) | MEM(TOTAL) | MEM(A) | MEM(FREE) |
 +----------+-------+------+---------+---------+---------+------------+--------+-----------+
 |   com1   | IDLE  |  8   |    0    |    8    |    0    |   32095    |   0    |   30448   |
 | control1 | IDLE  |  4   |    0    |    4    |    0    |    7941    |   0    |    805    |
 +----------+-------+------+---------+---------+---------+------------+--------+-----------+
まとめ

Slurm REST API(slurmrestd)は、HPCクラスター運用における「外部連携」「自動化」「機械可読データ取得」といった現代的なニーズを満たすための、不可欠なインターフェースです。

特にJWT認証の導入とJSONベースのデータ連携により、CLI出力のパース作業から解放され、より保守性の高いシステム構築が可能になります。

私たちライフマティックス株式会社では、このようなSlurmの複雑な設定や運用、特にREST APIを活用したカスタムシステムの連携でお困りのお客様向けに、Slurmの保守サービスをご提供しております。

お客様の計算環境を最大限に活用できるよう、専門のエンジニアが強力にサポートいたしますので、ぜひお気軽にご相談ください。

このブログ記事が、皆さんの研究や開発を加速させる一助となれば幸いです!