> ## Documentation Index
> Fetch the complete documentation index at: https://docs.coreweave.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Integrate sandboxes with the SUNK Pod Scheduler

> Route sandbox pods through the SUNK Pod Scheduler so Slurm places them alongside your Slurm jobs.

CPUのみのサンドボックスPodをSUNK Pod Schedulerを通じてルーティングし、クラスター内で実行中のSlurmジョブと並行してSlurmが配置を管理できるようにします。サンドボックスは通常のSlurmジョブとなり、クラスター内の利用可能なリソースを持つ任意のノードで実行可能で、同じノード上で既に実行中の他のSlurmジョブやサンドボックスとCPUリソースを共有することもできます。

ランナーのポリシーは、そのランナーに配置されるすべてのサンドボックスに対してSUNKスケジューラーを設定します。クライアントはCoreWeave Kubernetes Service (CKS)配置でランナーを選択します。このガイドは、ポリシーを構成するクラスターオペレーターと、サンドボックスを起動するワークロード作成者を対象としています。

<Info>
  **CPUのみのサポート**

  GPUサンドボックスはプライベートプレビュー中であり、SUNK Pod Schedulerインテグレーションではまだサポートされていません。サポートされる配置オプションとアクセスをリクエストする方法については、[GPUサンドボックス](/ja/products/sandboxes/gpu-sandboxes)を参照してください。

  CPUのみのサンドボックスは、アイドル状態のCPU Nodeに配置したり、他のサンドボックスやSlurmジョブとCPU Nodeを共有したり、他のワークロードが実行中のGPU Node上でCPUリソースを共有したりできます。詳細については、[既知の制限事項](/products/sunk/run_workloads/schedule-kubernetes-pods#known-limitations)を参照してください。
</Info>

<h2 id="prerequisites">
  前提条件
</h2>

* [SUNK](/products/sunk) がデプロイされ、[SUNK Pod Scheduler](/products/sunk/run_workloads/schedule-kubernetes-pods) が有効になっている CKS クラスター。
* 同じクラスターにデプロイされた [CoreWeave サンドボックス ランナー](/ja/products/sandboxes/operations/managed-runners)。
* インストールおよび認証済みの [CoreWeave Intelligent CLI](https://github.com/coreweave/cwic) (`cwic`) v1.44.0 以降。セットアップの詳細については、[ランナーのデプロイと管理](/ja/products/sandboxes/operations/managed-runners) を参照してください。
* ランナーのポリシーを読み取りおよび更新するための `sandbox_admin` ロール、および Slurm デプロイメントを更新する権限。
* v1 サンドボックス API 用の、インストールおよび認証済みの `cwsandbox >= 1.0.0`。
* クラスター検査用の `kubectl` および `yq`。HTTP の例では `curl`、`jq`、および `$TOKEN` 内の CoreWeave API トークンも使用します。

このページ全体で `[RUNNER-ID]` を、SUNK クラスター上のランナーの ID に置き換えてください。

<h2 id="step-1-verify-the-sunk-pod-scheduler">
  ステップ 1: SUNK Pod Scheduler の検証
</h2>

SUNK デプロイメントが CoreWeave Sandboxes で動作するように設定されていることを検証します。

1. スケジューラーが実行中であることを検証します:

   ```bash theme={"system"}
   kubectl get pods -n tenant-slurm -l app.kubernetes.io/name=sunk-scheduler
   ```

   Pod が返されない場合は、Slurm Helm values で `scheduler.enabled: true` を設定してスケジューラーを有効にしてください。詳細は [Enable the scheduler](/products/sunk/run_workloads/schedule-kubernetes-pods#enable-the-scheduler) を参照してください。

2. スケジューラー名を確認します。この名前はステップ 2 でランナーのポリシーに設定します。SUNK 8.0 以降では、スケジューラーは ConfigMap から名前を読み取ります:

   ```bash theme={"system"}
   kubectl get configmap -n tenant-slurm -l app.kubernetes.io/component=scheduler \
     -o jsonpath='{.items[0].data.scheduler\.conf}' | yq '.scheduler.name'
   ```

   ```text theme={"system"}
   slurm-scheduler
   ```

   SUNK 7.x では、代わりにスケジューラー Pod の `--scheduler-name` 引数で名前が指定されます。内部の動作については [Look up the scheduler configuration](/products/sunk/run_workloads/schedule-kubernetes-pods#look-up-the-scheduler-configuration) を参照してください。

3. `KillWait` の値を確認します。この値は Pod の終了を確認する際に使用します:

   ```bash theme={"system"}
   kubectl get pods -n tenant-slurm -l app.kubernetes.io/name=sunk-scheduler -o yaml \
     | yq '.items[0].spec.containers[] | select(.name == "scheduler").args'
   ```

   出力で `--slurm-kill-wait` を確認します:

   ```text theme={"system"}
   - --slurm-kill-wait=30s
   ```

4. サンドボックス Pod 向けに Slurm の終了ウィンドウを設定します。SUNK では、`terminationGracePeriodSeconds` が `--slurm-kill-wait` から 5 秒を引いた値より厳密に小さい必要があります。

   ポリシーでは `base.spec.terminationGracePeriodSeconds` を指定できません。Kubernetes のデフォルトである 30 秒の猶予期間を持つ Pod の場合は、`KillWait` を 35 秒より大きい値に設定してください。たとえば、次の内容を Slurm Helm values にマージし、通常の SUNK デプロイ手順で更新を適用します:

   ```yaml theme={"system"}
   slurmConfig:
     KillWait: 60
   ```

   この変更は、クラスター全体のジョブに対する Slurm の終了ウィンドウに影響します。前述のコマンドを実行し、スケジューラーが `--slurm-kill-wait=60s` を報告していることを検証してください。詳細は [Slurm configuration parameters](/products/sunk/reference/slurm-parameters#slurmConfig) および [Set the termination grace period](/products/sunk/run_workloads/schedule-kubernetes-pods#set-the-termination-grace-period) を参照してください。

   <Warning>
     スナップショット対応ストレージを使用するサンドボックスでは、Pod の猶予期間が 300 秒になる場合があります。`KillWait` が 60 秒では、これらの Pod には不十分です。生成された Pod の `terminationGracePeriodSeconds` を確認し、`KillWait` をその値に 5 秒を加えた値より大きく設定してください。300 秒の場合は、330 などの値を使用します。スケジューラーの kill-wait 設定は Slurm の設定と一致させてください。
   </Warning>

5. スケジューラーのスコープがサンドボックスの namespace を対象に含んでいることを確認します。namespace の選択はランナーが管理するもので、ポリシーのフィールドではありません。新規ユーザー用に作成されるものも含め、すべてのサンドボックス namespace を監視するには、`scheduler.scope.type: cluster` を設定してください。`scheduler.scope.type: namespace` を使用する場合は、各サンドボックス namespace を `scheduler.scope.namespaces` に追加し、新しい namespace が作成されるたびにリストを更新してください。スコープの変更は Helm で適用してください。これにより、スケジューラーにそれらの namespace で必要な RBAC 権限も付与されます。詳細は [Enable the scheduler](/products/sunk/run_workloads/schedule-kubernetes-pods#enable-the-scheduler) を参照してください。

6. サンドボックスと共有する NodeSet で、`slurmd` のリソースリクエストを引き下げます。これはサンドボックスの設定ではなく、Slurm 側 (Slurm Helm values) で行う変更です。デフォルトの NodeSet リソースリクエストは Kubernetes のノードの割り当て可能キャパシティの大部分を占有するため、サンドボックス Pod を配置する余地が残りません。この変更を行わないと、サンドボックス Pod は `OutOfMemory` または `OutOfcpu` エラーで拒否されます。設定の詳細は [SUNK Pod Scheduler を使用したリソースの管理](/products/sunk/run_workloads/manage-scheduler-resources) を参照してください。

<h2 id="step-2-configure-the-runner-policy">
  ステップ 2: ランナーのポリシーを設定する
</h2>

各ランナーには 1 つのポリシーが付属しています。そのポリシー内で `base.spec.schedulerName` を設定すると、サンドボックスの Pod が SUNK を経由するようにルーティングできます。別途ポリシーリソースを作成したりバインドしたりする必要はありません。

<Warning>
  ポリシーの更新はポリシードキュメント全体を置き換えます。現在のポリシーを読み取り、既存の `base` アタッチメントと `constraints` を保持したうえで、SUNK に必要な設定のみを変更してください。この変更はランナー上の新しいサンドボックスに適用されます。実行中のサンドボックスは移動しません。
</Warning>

次のフラグメントをランナーの既存のポリシーにマージしてください。`slurm-scheduler` はステップ 1 で取得したスケジューラー名に置き換えてください:

```yaml theme={"system"}
base:
  spec:
    schedulerName: "slurm-scheduler"
```

<Tabs>
  <Tab title="CLI">
    現在のポリシーを読み取り、`$EDITOR` で開きます:

    ```bash theme={"system"}
    cwic sandbox runner policy get [RUNNER-ID]
    cwic sandbox runner policy edit [RUNNER-ID]
    ```

    `base.spec` の下に `schedulerName` を追加し、ドキュメントの残りの部分はそのままにします。変更を保存してエディターを閉じると、ポリシーが適用されます。

    完全なポリシーをファイルで管理している場合は、そのファイルを検証して適用します:

    ```bash theme={"system"}
    cwic sandbox runner policy validate -f slurm-policy.yaml
    cwic sandbox runner policy edit [RUNNER-ID] -f slurm-policy.yaml
    ```
  </Tab>

  <Tab title="curl">
    Connect HTTP API を使用して、ポリシーのリビジョン (`etag`) を含むランナー情報を取得します:

    ```bash theme={"system"}
    curl --fail-with-body --silent --show-error -X POST \
      'https://api.coreweave.com/coreweave.sandbox.v1.RunnerManagementService/GetManagedRunner' \
      -H "Authorization: Bearer $TOKEN" \
      -H "Content-Type: application/json" \
      -H "Connect-Protocol-Version: 1" \
      --data '{"runnerId": "[RUNNER-ID]"}' \
      -o runner.json
    ```

    ランナーにポリシーがない場合は、続行する前に [サンドボックスポリシーを設定する](/ja/products/sandboxes/profiles/configure) に従ってポリシーを設定してください。

    他のすべてのポリシーフィールドを保持したままスケジューラー名を追加します。取得した `etag` を更新リクエストに含めます:

    ```bash theme={"system"}
    jq -e '
      if .policy == null or .etag == null then
        error("Read a configured runner policy and its etag before updating")
      else . end |
      .policy.base.spec.schedulerName = "slurm-scheduler" |
      {
        runnerId: .identity.runnerId,
        managedRunner: {identity: .identity, policy: .policy, etag: .etag},
        updateMask: "policy"
      }' runner.json > runner-policy-update.json
    ```

    `runner-policy-update.json` ファイルを確認してから適用します:

    ```bash theme={"system"}
    curl --fail-with-body -X POST \
      'https://api.coreweave.com/coreweave.sandbox.v1.RunnerManagementService/UpdateManagedRunner' \
      -H "Authorization: Bearer $TOKEN" \
      -H "Content-Type: application/json" \
      -H "Connect-Protocol-Version: 1" \
      --data-binary @runner-policy-update.json
    ```

    `etag` がないリクエストは拒否されます。リクエストを送信する前に別の管理者がポリシーを更新すると、`etag` が古くなるため更新は `FAILED_PRECONDITION` で失敗し、何も変更されません。ランナー情報を再度取得し、返されたポリシーに変更を再適用してから、新しい `etag` を指定して再送信してください。
  </Tab>
</Tabs>

<Warning>
  Slurm の配置と競合する `base.spec.nodeSelector` やサンドボックスのインスタンスタイプ制限は避けてください。Slurm がノードを選択するため、Kubernetes セレクターが競合すると `NodeAffinity` エラーが発生する可能性があります。対象のノードを指定するには、ステップ 4 のアノテーションで Slurm パーティションまたは制約を使用してください。
</Warning>

`constraints.network` フィールドとサンドボックスで宣言された外向き通信の設定が、ネットワークアクセスを制御します。SUNK スケジューリングを追加する際は、ランナーの既存のネットワーク制約を保持してください。[サンドボックスポリシーを設定する](/ja/products/sandboxes/profiles/configure#constrain-network-access) を参照してください。

ポリシーの変更がサンドボックス作成に反映されるまで時間がかかる場合があります。新しいスケジューラーや固定アノテーションを前提に運用する前に、サンドボックスを作成し、[Pod が Pending のままになる](#pods-remain-pending) の説明に従って Pod のフィールドを確認してください。ポリシーを読み取った際に新しい値が表示されても、新しいサンドボックスにはまだ反映されていない場合があります。

完全なスキーマについては [ポリシーリファレンス](/ja/products/sandboxes/reference/profile) を参照してください。ランナーのセットアップについては [ランナーのデプロイと管理](/ja/products/sandboxes/operations/managed-runners) を参照してください。

<h2 id="step-3-create-sandboxes">
  ステップ 3: サンドボックスを作成する
</h2>

`placement_mode="cks"` と `runner_ids` を設定して、ポリシーを設定したランナーを選択します。ランナーのポリシーによって、スケジューラーが自動的に指定されます。

```python theme={"system"}
from cwsandbox import Sandbox

with Sandbox.run(placement_mode="cks", runner_ids=["[RUNNER-ID]"]) as sb:
    print(f"Sandbox ID: {sb.sandbox_id}")
    result = sb.exec(["hostname"]).result()
    print(result.stdout)
```

サンドボックスが Slurm ジョブとして実行されていることを確認するには、前の例で出力されたサンドボックス ID を使用して、Slurm 内で対応するプレースホルダージョブを検索します。

```bash theme={"system"}
sacct --format=JobID,JobName%60,State,NodeList -X | grep [SANDBOX-ID]
```

Slurm がノードを選択します。Slurm のスケジューラーを誘導する [Slurm アノテーション](#step-4-control-placement-with-slurm-annotations)を追加しない限り、サンドボックスが配置されるノードを制御することはできません。

セッション内のすべてのサンドボックスで SUNK が設定された同じランナーを使用するには、`SandboxDefaults` の配置フィールドを設定します。

```python theme={"system"}
from cwsandbox import Sandbox, SandboxDefaults

defaults = SandboxDefaults(
    placement_mode="cks",
    runner_ids=("[RUNNER-ID]",),
)

with Sandbox.session(defaults) as session:
    sb1 = session.sandbox()
    sb2 = session.sandbox()

    r1 = sb1.exec(["hostname"]).result()
    r2 = sb2.exec(["hostname"]).result()
    print(f"sb1: {r1.stdout.strip()}, sb2: {r2.stdout.strip()}")
```

<h3 id="resource-requests-and-slurm-accounting">
  リソースリクエストと Slurm アカウンティング
</h3>

SUNK は Pod のリソース **リクエスト** (制限ではなく) を読み取り、Slurm ジョブパラメーターに変換します。

| Pod フィールド | Slurm パラメーター |
| - | - |
| `requests.cpu` | `CPUsPerTask` |
| `requests.memory` | `MinMemoryNode` |

Slurm はこれらの値をスケジューリングの判断と `sacct` アカウンティングに使用します。SUNK は特定のサービス品質クラスを必要としません。Guaranteed (リクエストと制限が等しい) と Burstable (リクエストが制限より小さい) の両方が動作します。

`ResourceOptions` でリクエストを制限より低く設定した場合、キャパシティに空きがあるときに Pod は制限までバーストできますが、Slurm が見るのはリクエストのみです。たとえば、次のように設定されたサンドボックスでは:

```python theme={"system"}
requests={"cpu": "500m", "memory": "512Mi"},
limits={"cpu": "2",     "memory": "2Gi"},
```

`sacct` では 500m CPU、512Mi メモリ のジョブとして表示されますが、ノードに余裕がある場合、サンドボックスは最大 2 CPU と 2Gi まで使用できます。完全な `ResourceOptions` のリファレンスについては、[リソース](/ja/products/sandboxes/client/guides/sandbox-configuration#resources) を参照してください。

サンドボックスのワークロードが必要とするものに合わせてリクエストのサイズを調整し、ステップ 1 で下げた `slurmd` のリクエスト分、ターゲットノードに十分な余裕を残してください。基本的なルールについては、[リソースリクエストの設定](/products/sunk/run_workloads/schedule-kubernetes-pods#set-resource-requests) と [SUNK Pod Scheduler を使用したリソースの管理](/products/sunk/run_workloads/manage-scheduler-resources) を参照してください。

<h2 id="step-4-control-placement-with-slurm-annotations">
  ステップ 4: Slurm アノテーションで配置を制御する
</h2>

サンドボックスの配置を制御するには、起動時にサンドボックスに SUNK アノテーションを設定します。次の例では、サンドボックスを `hpc-prod` パーティションに固定します：

```python theme={"system"}
from cwsandbox import Sandbox

sb = Sandbox.run(
    placement_mode="cks",
    runner_ids=["[RUNNER-ID]"],
    annotations={
        "sunk.coreweave.com/partition": "hpc-prod",
    },
)
```

<h3 id="common-annotations">
  共通のアノテーション
</h3>

すべてのアノテーションは `sunk.coreweave.com/` 接頭辞を共有します。サンドボックスの配置を制御するために一般的に使用されるアノテーションは次のとおりです：

| アノテーション キー | 説明 |
| - | - |
| `partition` | Slurm パーティション名 |
| `constraint` | Slurm 機能制約 |
| `account` | Slurm アカウント名 |
| `qos` | Slurm QoS レベル |
| `user-id` | アカウンティング用の Slurm ユーザー ID。数値の Linux UID でなければなりません (例: `"1000"`) |
| `exclusive` | ノードの排他性 (`none`、`user`、または `ok`) |

`user-id` アノテーションに数値 UID の代わりにユーザー名を渡すと、Slurm がサンドボックスをスケジューリングするのを妨げるブロックエラーが発生します。Slurm ログインノードから数値 UID を検索するには、検索する Linux ユーザー名で `[USERNAME]` を置き換えます：

```bash theme={"system"}
id -u           # ご自身の UID
id -u [USERNAME]  # 他の方の UID
whoami          # 必要に応じてまずユーザー名を確認してください
```

完全なリストについては、[Annotations reference](/products/sunk/run_workloads/schedule-kubernetes-pods#annotations-reference) を参照してください。

<h3 id="enforce-annotations-in-the-policy">
  ポリシーでアノテーションを強制する
</h3>

ランナー上のすべてのサンドボックスに Slurm ジョブのパラメーターを設定するには、そのアノテーションを `base.metadata.annotations` に追加します。たとえば、`sandboxes` パーティションを使用するには、この断片を既存のポリシーにマージします。

```yaml theme={"system"}
base:
  metadata:
    annotations:
      sunk.coreweave.com/partition: "sandboxes"
  spec:
    schedulerName: "slurm-scheduler"
```

ポリシーのアノテーションは、同じキーに対してクライアントが指定した値よりも優先されます。クライアントが値を選択できるようにするには、`base.metadata.annotations` からそのキーを省略し、`constraints.metadata.denied_annotation_prefixes` で許可されていることを確認してください。たとえば、クライアントがトレーニング ジョブのユーザーと一致させる必要がある場合は、`sunk.coreweave.com/user-id` を固定しないでください。

<h3 id="match-the-slurm-user-from-a-training-job">
  トレーニング ジョブの Slurm ユーザーに合わせる
</h3>

トレーニング ジョブは、ノード全体を単一のユーザーで占有するために `--exclusive=user` を指定して実行されることがよくあります。これにより、他のユーザーのジョブがそのノードのリソースを奪い合うことを防ぎつつ、同じユーザーであれば、GPU トレーニングと並行して空き CPU を使用するサンドボックスなど、追加のジョブをそのノードで実行できます。

デフォルトでは、SUNK のプレースホルダー ジョブは root (UID 0) として実行されます。root はトレーニング ジョブを送信したユーザーとは別のユーザーであるため、Slurm はサンドボックスのプレースホルダーを排他ノードに配置しません。

トレーニング コードが実行中の Slurm ジョブ内から `cwsandbox` Python クライアントを使用してサンドボックスを作成する場合、環境からジョブの Slurm ユーザー ID を読み取り、アノテーションとして渡すことができます。これにより、サンドボックスのプレースホルダー ジョブがトレーニング ジョブと同じ Slurm ユーザーで送信されるため、Slurm はそれらを同じ排他ノードに配置できます。

```python theme={"system"}
import os
from cwsandbox import Sandbox, SandboxDefaults

slurm_uid = os.environ["SLURM_JOB_UID"]

defaults = SandboxDefaults(
    placement_mode="cks",
    runner_ids=("[RUNNER-ID]",),
    annotations={
        "sunk.coreweave.com/user-id": slurm_uid,
    },
)

with Sandbox.session(defaults) as session:
    sb = session.sandbox()
    result = sb.exec(["hostname"]).result()
    print(result.stdout)
```

`user-id` アノテーションには、ユーザー名ではなく数値の Linux UID を指定する必要があります。これを設定すると、SUNK は `group-id` にもデフォルトで同じ値を設定します。グループ ID が異なる場合は、`sunk.coreweave.com/group-id` を別途設定してください。

<h2 id="troubleshooting">
  トラブルシューティング
</h2>

SUNK Pod Scheduler を通じてサンドボックスを実行する際のよくある問題を診断するには、以下のセクションを使用します。

<h3 id="pods-remain-pending">
  Pod が Pending のままになる
</h3>

サンドボックス Pod を検査して、ランナーがスケジューラー名を適用したことを確認し、終了猶予期間をチェックします：

```bash theme={"system"}
kubectl get pods -A -l 'sandbox.coreweave.com/sandbox-id=[SANDBOX-ID]' \
  -o custom-columns='NAMESPACE:.metadata.namespace,NAME:.metadata.name,SCHEDULER:.spec.schedulerName,GRACE:.spec.terminationGracePeriodSeconds,PARTITION:.metadata.annotations.sunk\.coreweave\.com/partition'
```

サンドボックスがアクティブな間にこれを実行してください。`SCHEDULER` が SUNK スケジューラーと一致し、そのスコープに `NAMESPACE` が含まれ、`GRACE` がスケジューラーの kill wait から 5 秒を引いた値より厳密に小さいことを確認してください。30 秒の猶予期間は、デフォルトの 30 秒の kill wait で失敗します。ポリシーがパーティションをピン留めしている場合は、`PARTITION` がそれと一致することを確認してください。

スケジューラー名または固定アノテーションが欠落しているか不正な場合は、ランナーのポリシーを読み戻して、クライアントが意図したランナーを選択したことを確認してください。新しく作成された Pod が以前の値を使用している場合は、ポリシーの伝播にさらに時間をかけ、別のサンドボックスで再試行してください。

<h3 id="placeholder-jobs-temporarily-in-completing-state">
  プレースホルダージョブが一時的に completing 状態になる
</h3>

サンドボックスが停止すると、その Slurm プレースホルダージョブは、クリーンアップスクリプトが実行されノードがプールに戻される間、30 から 60 秒間 `CG` (completing) 状態になります。これは通常の Slurm 動作であり、同じノードで実行中の他のジョブには影響しません。完全な状態リファレンスについては [Slurm job states](/products/sunk/manage_sunk/slurm-job-states) を参照してください。

<h3 id="sandboxes-not-landing-where-expected">
  サンドボックスが想定した場所に配置されない場合
</h3>

Slurm は、ポリシーが設定するか、クライアントが渡すアノテーションに基づいてサンドボックスの配置を決定します。サンドボックスが想定したノードに配置されない場合は、Slurm ジョブのパラメーターを確認してください。

SUNK は、各サンドボックス Pod に対して、`<namespace>/<pod-name>` という名のプレースホルダー Slurm ジョブを作成します。Pod 名にはサンドボックス ID が含まれます。この ID はクライアントから `sb.sandbox_id` として取得できます。サンドボックス ID でプレースホルダージョブを検索し、そのパラメーターを確認してください：

```bash theme={"system"}
sacct --format=JobID,JobName%60,Partition,Account,AllocCPUS,ReqMem,State,NodeList,Start,End -X \
  | grep [SANDBOX-ID]
```

`[SANDBOX-ID]` を Python クライアントの `sb.sandbox_id` の値に置き換えます。

<h2 id="see-also">
  関連項目
</h2>

* [CoreWeave Sandboxes について](/ja/products/sandboxes)
* [ランナーのデプロイと管理](/ja/products/sandboxes/operations/managed-runners)
* [サンドボックスポリシーを設定する](/ja/products/sandboxes/profiles/configure)
* [SUNK Pod Scheduler で Kubernetes Pod をスケジュールする](/products/sunk/run_workloads/schedule-kubernetes-pods)
* [サンドボックスを使用した RL トレーニング](/ja/products/sandboxes/client/guides/rl-training)
* [サンドボックスの設定](/ja/products/sandboxes/client/guides/sandbox-configuration)
