Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
14 changes: 14 additions & 0 deletions docs/userguide/configure.md
Original file line number Diff line number Diff line change
Expand Up @@ -71,6 +71,20 @@ helm install hami hami-charts/hami --set devicePlugin.deviceMemoryScaling=5 -n k
| `scheduler.defaultSchedulerPolicy.nodeSchedulerPolicy` | String | GPU node scheduling policy: `"binpack"` allocates jobs to the same GPU node as much as possible. `"spread"` allocates jobs to different GPU nodes as much as possible. | `"binpack"` |
| `scheduler.defaultSchedulerPolicy.gpuSchedulerPolicy` | String | GPU scheduling policy: `"binpack"` allocates jobs to the same GPU as much as possible. `"spread"` allocates jobs to different GPUs as much as possible. `"mutex"` allocates jobs only to GPUs with no other workloads. | `"spread"` |

## Scheduler Configs: extender arguments

The scheduler extender reads flags from `scheduler.extender.extraArgs`. The chart ships `["--debug", "-v=4"]`, and setting the value replaces the whole list, so repeat the entries you want to keep:

```bash
helm upgrade hami hami-charts/hami -n kube-system --reuse-values \
--set-json 'scheduler.extender.extraArgs=["--debug","-v=4","--node-lock-retry-timeout=28s"]'
Comment on lines +79 to +80

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🎯 Functional Correctness | 🟠 Major | ⚡ Quick win

Use one namespace for the documented Helm release. The Coscheduling guide uses hami-system, while these extender examples use kube-system.

  • docs/userguide/configure.md#L79-L80: use hami-system for this flow, or document an explicit release-namespace parameter.
  • i18n/zh/docusaurus-plugin-content-docs/current/userguide/configure.md#L81-L82: mirror the same namespace rule in Chinese.
📍 Affects 2 files
  • docs/userguide/configure.md#L79-L80 (this comment)
  • i18n/zh/docusaurus-plugin-content-docs/current/userguide/configure.md#L81-L82
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@docs/userguide/configure.md` around lines 79 - 80, Use the same Helm release
namespace, hami-system, in the extender command at docs/userguide/configure.md
lines 79-80 and mirror that namespace change in
i18n/zh/docusaurus-plugin-content-docs/current/userguide/configure.md lines
81-82; do not introduce a separate namespace parameter.

```

| Argument | Type | Description | Default |
| --- | --- | --- | --- |
| `--node-lock-retry-timeout` | Duration | How long `Bind` retries the node lock when it is held by another member of the same PodGroup. Applies only to pods carrying the `scheduling.x-k8s.io/pod-group` label; other pods fail fast as before. `0` disables the retry. Keep this below the extender `httpTimeout` in the KubeSchedulerConfiguration, which the chart sets to `30s`. See [How to use Coscheduling with HAMi](coscheduling/how-to-use-coscheduling.md). | `28s` |
| `--node-lock-timeout` | Duration | How long a node lock stays valid before another pod may take it over. Applies to every pod, not only PodGroup members. | `5m` |

## Pod Configs: Annotations

| Argument | Type | Description | Example |
Expand Down
248 changes: 248 additions & 0 deletions docs/userguide/coscheduling/how-to-use-coscheduling.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,248 @@
---
title: How to use Coscheduling with HAMi
sidebar_label: How to use Coscheduling
---

[Coscheduling](https://github.com/kubernetes-sigs/scheduler-plugins/tree/master/pkg/coscheduling) is a scheduler plugin from [kubernetes-sigs/scheduler-plugins](https://github.com/kubernetes-sigs/scheduler-plugins) that provides gang scheduling. A group of Pods is admitted only when at least `minMember` of them can be placed at once, which is what distributed training needs: a job either gets all of its GPUs or none of them.

This guide covers running Coscheduling inside the HAMi scheduler and tuning the node lock behavior that gang binding exercises.

## How it works

HAMi and Coscheduling operate at two different points of the scheduling cycle.

Coscheduling works in the **Permit** phase. Each member Pod that passes filtering is parked in a waiting queue. Once `minMember` members are waiting, all of them are released into the bind phase at the same time.

HAMi works in the **Bind** phase, through the extender. Before binding, the extender takes a per-node lock by writing the `hami.io/mutex.lock` annotation onto the Node object:

```text
hami.io/mutex.lock: 2026-06-14T15:05:03Z,default,gang-pod-1
```

The lock serializes device allocation on that node. Without it, two Pods bound at the same moment would both read the same device usage snapshot and could be handed overlapping slices of one GPU. The lock is released by the device plugin once `Allocate()` finishes and the Pod annotations are updated, which takes about 20 ms on a real GPU. A lock that is never released expires after the node lock timeout (5 minutes by default).

These two mechanisms meet at gang release. Coscheduling releases every member in the same millisecond, so if several members target the same node, they contend on a lock that is held for only a few tens of milliseconds. The Pod that loses fails its bind, returns to Pending, and comes back through the default kube-scheduler backoff, which is measured in seconds. A five-member gang converges, but it takes several backoff rounds to do it.

To close that gap, the extender retries the node lock for Pods that carry the Coscheduling group label:

- A Pod with a non-empty `scheduling.x-k8s.io/pod-group` label polls the lock every 100 ms until `--node-lock-retry-timeout` expires.
- Any partially acquired lock is released before each retry, so a Pod requesting devices from more than one vendor cannot leave a stale lock behind.
- Errors that are not lock contention are returned immediately and are not retried.
- Pods without the label keep the original fail-fast behavior.

:::note

`--node-lock-retry-timeout` is available in builds newer than v2.9.0.

:::

## Prerequisites

- A Kubernetes cluster with GPU nodes and HAMi installed.
- A [scheduler-plugins release](https://github.com/kubernetes-sigs/scheduler-plugins/releases) built against your Kubernetes minor version. The examples below use v0.34.7 on Kubernetes v1.35.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I checked the scheduler-plugins compatibility matrix : Scheduler Plugins — Compatibility Matrix

It lists scheduler-plugins v0.34.7 as being compiled with Kubernetes v1.34.7, but your docs guide uses scheduler-plugins v0.34.7 with Kubernetes v1.35.

So the versions in the guide don't appear to be aligned with the compatibility matrix.

- Helm 3.
Comment on lines +41 to +43

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🎯 Functional Correctness | 🟠 Major | ⚡ Quick win

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
set -euo pipefail

echo "== Candidate docs files =="
git ls-files | rg '(^|/)docs/userguide/coscheduling/how-to-use-coscheduling\.md$|^i18n/zh/docusaurus-plugin-content-docs/current/userguide/coscheduling/how-to-use-coscheduling\.md$' || true

echo
echo "== Relevant lines in English and Chinese docs =="
for f in "docs/userguide/coscheduling/how-to-use-coscheduling.md" "i18n/zh/docusaurus-plugin-content-docs/current/userguide/coscheduling/how-to-use-coscheduling.md"; do
  if [ -f "$f" ]; then
    echo "--- $f"
    sed -n '35,50p' "$f" | nl -ba -v35
  else
    echo "MISSING: $f"
  fi
done

echo
echo "== Other mentions of v0.34.7 or Kubernetes v1.35 in docs =="
rg -n "v0\.34\.7|scheduler-plugins|Kubernetes v1\.35|v1\.35|v0\.34\.(6|8|7)" docs i18n --glob '*.md' --glob '*.mdx' || true

Repository: Project-HAMi/website

Length of output: 487


🌐 Web query:

scheduler-plugins compatibility matrix v0.34.7 Kubernetes v1.34.7

💡 Result:

Yes, scheduler-plugins version v0.34.7 is explicitly compatible with Kubernetes v1.34.7 [1][2][3]. According to the official compatibility matrix for the Kubernetes SIGs scheduler-plugins project, the minor version of the plugins matches the minor version of the Kubernetes client packages (such as client-go and apimachinery) with which it is compiled [1][3]. Specifically, scheduler-plugins v0.34.7 is compiled with Kubernetes v1.34.7 dependencies [1][2][3]. This alignment is standard for the project, where single-digit patch versions typically align directly with the Kubernetes client package versions used in the build [1][4].

Citations:


🏁 Script executed:

#!/bin/bash
set -euo pipefail

echo "== Relevant lines in English and Chinese docs =="
for f in "docs/userguide/coscheduling/how-to-use-coscheduling.md" "i18n/zh/docusaurus-plugin-content-docs/current/userguide/coscheduling/how-to-use-coscheduling.md"; do
  if [ -f "$f" ]; then
    echo "--- $f"
    sed -n '35,50p' "$f"
  else
    echo "MISSING: $f"
  fi
done

echo
echo "== Other mentions of v0.34.7 or Kubernetes v1.35 in docs =="
rg -n "v0\.34\.7|scheduler-plugins|Kubernetes v1\.35|v1\.35|v0\.34\.(6|8|7)" docs i18n --glob '*.md' --glob '*.mdx' || true

echo
echo "== Official compatibility reference =="
curl -fsSL --max-time 20 "https://scheduler-plugins.sigs.k8s.io/versions/v0.34.7/" || true
echo
curl -fsSL --max-time 20 "https://github.com/kubernetes-sigs/scheduler-plugins/releases/tag/release-1.34.7" || true

echo
echo "== GitHub release tags and Kubernetes compatibility manifests nearby v0.34.7/1.34.7 =="
urls="https://github.com/kubernetes-sigs/scheduler-plugins/releases/release-1.34.7 https://github.com/kubernetes-sigs/scheduler-plugins/releases/release-0.34.7"
python3 - <<'PY'
import urllib.request, re
urls = [
  "https://github.com/kubernetes-sigs/scheduler-plugins/releases/release-1.34.7",
  "https://github.com/kubernetes-sigs/scheduler-plugins/releases/release-0.34.7",
  "https://scheduler-plugins.sigs.k8s.io/versions/v0.34.7/",
]
for url in urls:
    try:
        req = urllib.request.Request(url, headers={"User-Agent":"verify"})
        with urllib.request.urlopen(req, timeout=20) as r:
            data = r.read().decode("utf-8", "replace")
        print("\n---", url)
        # Print compact excerpts around compatible kubernetes strings and release version headings
        hits = re.finditer(r'compatible\s+kubernetes|v1\.34\.7|v1\.35|client-go|Kubernetes', data, re.I)
        shown = False
        for m in hits:
            if not shown:
                start = max(0, m.start()-150)
                end = min(len(data), m.end()+150)
                text = data[start:end].replace('\n', ' ')
                print(text[:300])
                shown = True
                break
        # Also show tag/release title-like lines
        for line in data.splitlines():
            if "Compatible Kubernetes" in line or "Kubernetes" in line or "client-go" in line:
                print(line[:180])
    except Exception as e:
        print("ERROR", url, e)
PY

Repository: Project-HAMi/website

Length of output: 7783


🌐 Web query:

site:scheduler-plugins.sigs.k8s.io version v0.34.7 compatible kubernetes v1.34.7

💡 Result:

Yes, version v0.34.7 of the Kubernetes Scheduler Plugins is officially designed to be compiled and used with Kubernetes version v1.34.7 [1]. According to the official Kubernetes Scheduler Plugins documentation, this compatibility is explicitly maintained for both the scheduler components and controllers [1]. As of August 7, 2026, the project documentation confirms that release v0.34.7 is built specifically for integration with Kubernetes v1.34.7 [1].

Citations:


🌐 Web query:

site:https://github.com/kubernetes-sigs/scheduler-plugins v0.34.7 compatible kubernetes v1.34.7

💡 Result:

The scheduler-plugins release v0.34.7 is explicitly compiled with and compatible with Kubernetes v1.34.7 [1][2][3]. The official compatibility matrix for the Kubernetes SIGs scheduler-plugins project confirms that version v0.34.7 uses Kubernetes v1.34.7 dependencies [1][2]. The project's release notes and go.mod file further verify that the codebase was updated to support Kubernetes v1.34 and specifically bumped its dependencies to v1.34.7 [3][4]. Additionally, users running this version in-cluster should ensure that the scheduler service account has the necessary RBAC permissions for the resource.k8s.io API group, as these are required for proper operation with Kubernetes v1.34 [5].

Citations:


🌐 Web query:

site:https://github.com/kubernetes-sigs/scheduler-plugins releases v0.36.0 Kubernetes v1.35

💡 Result:

As of August 7, 2026, there is no official release of "v0.36.0" for the Kubernetes Scheduler Plugins project [1][2]. While the project's development repository has seen commits related to upgrading dependencies to Kubernetes v1.35 [3][4][5], the most recent stable releases have been in the v0.34.x series (e.g., v0.34.7) [6][1]. The project maintainers have indicated a release process that includes a "soak" period for development versions before officially bumping support to newer Kubernetes versions [2]. Consequently, a "v0.36.0" release matching Kubernetes v1.35 has not been published [1].

Citations:


Correct the scheduler-plugins and Kubernetes version pairing. scheduler-plugins v0.34.7 is compiled for Kubernetes v1.34.7, so the current Kubernetes v1.35 example is misleading.

  • docs/userguide/coscheduling/how-to-use-coscheduling.md#L41-L43 and #L58 and #L69: change the examples to a Kubernetes version compatible with v0.34.7, or update the image tag and CRD URL to a newer scheduler-plugins version that officially supports Kubernetes v1.35.
  • i18n/zh/docusaurus-plugin-content-docs/current/userguide/coscheduling/how-to-use-coscheduling.md#L41-L43 and the matching image/CRD references: apply the same version correction in Chinese.
📍 Affects 2 files
  • docs/userguide/coscheduling/how-to-use-coscheduling.md#L41-L43 (this comment)
  • i18n/zh/docusaurus-plugin-content-docs/current/userguide/coscheduling/how-to-use-coscheduling.md#L41-L43
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@docs/userguide/coscheduling/how-to-use-coscheduling.md` around lines 41 - 43,
Correct the scheduler-plugins/Kubernetes version pairing in
docs/userguide/coscheduling/how-to-use-coscheduling.md at lines 41-43, 58, and
69 by either using Kubernetes v1.34.7 with scheduler-plugins v0.34.7 or updating
the scheduler-plugins image tag and CRD URL to a release supporting v1.35; apply
the same compatible version changes to the matching image and CRD references in
i18n/zh/docusaurus-plugin-content-docs/current/userguide/coscheduling/how-to-use-coscheduling.md
at lines 41-43.

Source: MCP tools

- `kubectl` with cluster-admin rights.

## 1. Install HAMi with the scheduler-plugins kube-scheduler

The HAMi scheduler Pod runs two containers: an upstream `kube-scheduler` and the HAMi `vgpu-scheduler-extender`. Coscheduling is compiled into the scheduler-plugins build of kube-scheduler, so point the chart at that image instead of the stock one:

```bash
helm repo add hami-charts https://project-hami.github.io/HAMi/
helm repo update

helm install hami hami-charts/hami \
--namespace hami-system --create-namespace \
--set scheduler.kubeScheduler.image.registry=registry.k8s.io \
--set scheduler.kubeScheduler.image.repository=scheduler-plugins/kube-scheduler \
--set scheduler.kubeScheduler.image.tag=v0.34.7 \
--wait --timeout 10m
```

On an existing installation, run the same three `--set` flags through `helm upgrade --reuse-values`.

## 2. Install the PodGroup CRD

Coscheduling reads `PodGroup` resources. Install the CRD from the same scheduler-plugins release:

```bash
kubectl apply -f https://raw.githubusercontent.com/kubernetes-sigs/scheduler-plugins/v0.34.7/config/crd/bases/scheduling.x-k8s.io_podgroups.yaml
```
Comment on lines +46 to +70

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🗄️ Data Integrity & Integration | 🟠 Major | ⚡ Quick win

🧩 Analysis chain

🌐 Web query:

scheduler-plugins v0.34.7 installation PodGroup CRD controller RBAC

💡 Result:

To install the PodGroup CRD and the associated controller for scheduler-plugins v0.34.7, you must follow the official installation procedures, which include applying the necessary CRDs and deploying the scheduler-plugins controller. 1. CRD Installation The PodGroup CustomResourceDefinition (CRD) is required for the coscheduling functionality [1][2]. You can install it by applying the manifest from the scheduler-plugins repository [1]: kubectl apply -f manifests/crds/scheduling.x-k8s.io_podgroups.yaml Alternatively, you can apply all available CRDs located in the manifests/crds/ directory if your deployment requires multiple plugins [2]. 2. Controller Installation and RBAC The scheduler-plugins-controller is responsible for managing custom resource objects, including PodGroups [2][3]. There are two primary ways to install the required components: A. Helm Installation (Recommended for quick start) Using Helm automatically handles the deployment of the controller and the necessary RBAC configurations [4][5]. helm install --repo https://scheduler-plugins.sigs.k8s.io scheduler-plugins scheduler-plugins After installation, verify that the controller pod is running: kubectl get deploy -n scheduler-plugins B. Manual Installation (Production/Custom Environments) If you are manually replacing or supplementing the default scheduler, you must apply the all-in-one manifest, which includes the deployment for the controller and associated RBAC roles [1][2]: kubectl apply -f manifests/install/all-in-one.yaml 3. Scheduler Configuration and RBAC Considerations When running scheduler-plugins (e.g., as a second scheduler or by replacing the default scheduler), the scheduler-plugins binary requires specific RBAC privileges to manipulate custom resources like PodGroups [2][3]. If using the all-in-one manifest, these RBAC permissions are generally included [2]. If deploying manually, ensure that the service account used by the scheduler has permissions to access the scheduling.x-k8s.io API group [6]. You can verify that your kube-scheduler is using the correct image for version 0.34.7: registry.k8s.io/scheduler-plugins/kube-scheduler:v0.34.7 [7] Always ensure your kube-scheduler configuration file includes the necessary plugin settings and is correctly mounted to the pod [2][3].

Citations:


🌐 Web query:

scheduler-plugins v0.34.7 manifests/install/all-in-one.yaml PodGroup RBAC status

💡 Result:

For the scheduler-plugins version v0.34.7, the manifests/install/all-in-one.yaml file is intended to deploy the necessary controller and set up the environment for the scheduler plugins [1][2][3]. Regarding RBAC and PodGroup support, the official documentation for the scheduler-plugins repository specifies that using plugins that rely on Custom Resource Definitions (CRDs), such as the coscheduling plugin that utilizes PodGroup, requires two specific steps [4][5]: 1. Applying extra RBAC privileges to the system:kube-scheduler user, allowing the scheduler binary to manipulate the custom resource objects (like PodGroup) [4][5]. 2. Installing a controller binary (deployed via all-in-one.yaml) that manages these custom resource objects [4][5]. While manifests/install/all-in-one.yaml helps deploy the scheduler-plugins-controller [4][6], users must ensure the cluster has the necessary CRDs installed (typically from the manifests/crds directory) [5][6] and that the scheduler configuration is correctly updated to recognize and use these plugins [5]. As of v0.34.7, the repository continues to provide these components to enable support for features like coscheduling and PodGroups [1][2]. Note that Kubernetes has also introduced native PodGroup support in newer versions (utilizing scheduling.k8s.io/v1alpha2 API) [7][8], which is distinct from the scheduling.sigs.k8s.io/v1alpha1 PodGroup API used by the out-of-tree scheduler-plugins [4][6][7]. Ensure your environment is configured for the specific API group required by your workload and scheduler version [9][7].

Citations:


🏁 Script executed:

#!/bin/bash
set -euo pipefail

echo "== Target docs excerpts =="
sed -n '46,75p' docs/userguide/coscheduling/how-to-use-coscheduling.md
sed -n '110,150p' docs/userguide/coscheduling/how-to-use-coscheduling.md

echo
echo "== Chinese docs excerpts =="
sed -n '46,75p' i18n/zh/docusaurus-plugin-content-docs/current/userguide/coscheduling/how-to-use-coscheduling.md
sed -n '110,150p' i18n/zh/docusaurus-plugin-content-docs/current/userguide/coscheduling/how-to-use-coscheduling.md

echo
echo "== scheduler-plugins 0.34.7 all-in-one RBAC references around podgroups/status =="
curl -sSL https://raw.githubusercontent.com/kubernetes-sigs/scheduler-plugins/v0.34.7/manifests/install/all-in-one.yaml \
  | sed -n '1,220p' | grep -nE 'apiGroup|resources:|verb|podgroups|scheduler-plugin|serviceAccount|deployment|roleBinding|clusterRoleBinding' || true

Repository: Project-HAMi/website

Length of output: 6732


Complete the scheduler-plugins PodGroup integration. Installing the CRD and a read-only scheduler role is not enough for coscheduling. Add the v0.34.7 scheduler-plugins controller component, or document the equivalent HAMi chart component, and use the controller RBAC, including podgroups/status and the required write permissions. Mirror this with the Chinese docs.

  • docs/userguide/coscheduling/how-to-use-coscheduling.md#L46-L70
  • docs/userguide/coscheduling/how-to-use-coscheduling.md#L117-L143
  • i18n/zh/docusaurus-plugin-content-docs/current/userguide/coscheduling/how-to-use-coscheduling.md#L46-L70
📍 Affects 2 files
  • docs/userguide/coscheduling/how-to-use-coscheduling.md#L46-L70 (this comment)
  • docs/userguide/coscheduling/how-to-use-coscheduling.md#L117-L143
  • i18n/zh/docusaurus-plugin-content-docs/current/userguide/coscheduling/how-to-use-coscheduling.md#L46-L70
  • i18n/zh/docusaurus-plugin-content-docs/current/userguide/coscheduling/how-to-use-coscheduling.md#L117-L143
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@docs/userguide/coscheduling/how-to-use-coscheduling.md` around lines 46 - 70,
Complete the scheduler-plugins PodGroup setup in
docs/userguide/coscheduling/how-to-use-coscheduling.md at lines 46-70 and
117-143, and mirror the same changes in
i18n/zh/docusaurus-plugin-content-docs/current/userguide/coscheduling/how-to-use-coscheduling.md
at lines 46-70 and 117-143. Document installation of the v0.34.7
scheduler-plugins controller component, or the equivalent HAMi chart component,
and provide controller RBAC with podgroups/status plus all required write
permissions instead of only read access.

Source: MCP tools


## 3. Enable Coscheduling in the scheduler config

The chart renders the KubeSchedulerConfiguration into the `hami-scheduler` ConfigMap. Add the plugin to the profile:

```bash
kubectl edit configmap hami-scheduler -n hami-system
```

The `profiles` entry must look like this:

```yaml
profiles:
- schedulerName: hami-scheduler
plugins:
multiPoint:
enabled:
- name: Coscheduling
queueSort:
disabled:
- name: PrioritySort
pluginConfig:
- name: Coscheduling
args:
permitWaitingTimeSeconds: 10
```

:::warning

`PrioritySort` must be disabled. Coscheduling registers its own queue sort plugin, and kube-scheduler refuses to start with two of them:

```text
only one queue sort plugin required for profile with scheduler name "hami-scheduler", but got 2
```

:::

The ConfigMap is owned by the chart, so `helm upgrade` overwrites this edit. Re-apply it after every upgrade, or manage the ConfigMap outside the chart.

Restart the scheduler to pick up the change:

```bash
kubectl rollout restart deploy/hami-scheduler -n hami-system
kubectl rollout status deploy/hami-scheduler -n hami-system
```

## 4. Grant access to PodGroups

The scheduler ServiceAccount installed by the chart cannot read `PodGroup` resources. Add the permission:

```yaml
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
name: hami-podgroup-reader
rules:
- apiGroups: ["scheduling.x-k8s.io"]
resources: ["podgroups"]
verbs: ["get", "list", "watch", "create", "update", "patch"]
---
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
name: hami-podgroup-reader
roleRef:
apiGroup: rbac.authorization.k8s.io
kind: ClusterRole
name: hami-podgroup-reader
subjects:
- kind: ServiceAccount
name: hami-scheduler
namespace: hami-system
```

Without it, `PreFilter` fails for every member and the whole group stays Pending.

## 5. Submit a gang

Create a `PodGroup` and label every member with its name. Each member requests vGPU resources as usual:

```yaml
apiVersion: scheduling.x-k8s.io/v1alpha1
kind: PodGroup
metadata:
name: gang-training
spec:
minMember: 4
scheduleTimeoutSeconds: 60
---
apiVersion: v1
kind: Pod
metadata:
name: gang-worker-1
labels:
scheduling.x-k8s.io/pod-group: gang-training
spec:
schedulerName: hami-scheduler
containers:
- name: worker
image: ubuntu:22.04
command: ["sleep", "3600"]
resources:
limits:
nvidia.com/gpu: "1"
nvidia.com/gpumem: "3000"
nvidia.com/gpucores: "30"
```

The manifest above defines one member. Create `minMember` Pods from the same template with distinct names, otherwise the group never reaches its quorum and every member stays Pending.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The manifest above defines one Pod that belongs to the gang. Create additional Pods with the same scheduling.x-k8s.io/pod-group label to satisfy minMember. Each Pod should have a distinct name; otherwise, the group cannot reach the required number of members and the Pods will remain Pending.


:::warning

`scheduling.x-k8s.io/pod-group` must be under `metadata.labels`. Placing it under `metadata.annotations` bypasses gang logic without any error: the Pods schedule one by one regardless of `minMember`.

:::

Verify that the group was admitted together:

```bash
kubectl get pods -l scheduling.x-k8s.io/pod-group=gang-training -o wide
```

When fewer than `minMember` members exist, `PreFilter` rejects the group before the HAMi extender is reached:

```text
pre-filter pod gang-worker-1 cannot find enough sibling pods,
current pods number: 3, minMember of group: 5
```

## Tune the node lock

Two independent timeouts control node lock behavior.

| Flag | Default | Description |
| --- | --- | --- |
| `--node-lock-retry-timeout` | `28s` | How long `Bind` retries the node lock for a Pod labeled with `scheduling.x-k8s.io/pod-group`. `0` disables retry and restores fail-fast behavior. Polling interval is 100 ms. |
| `--node-lock-timeout` | `5m` | How long a lock stays valid before another Pod may take it over. Applies to every Pod, not only gang members. |

Set the retry timeout through the chart. `scheduler.extender.extraArgs` replaces the default list, so keep the existing entries:

```bash
helm upgrade hami hami-charts/hami -n hami-system --reuse-values \
--set-json 'scheduler.extender.extraArgs=["--debug","-v=4","--node-lock-retry-timeout=28s"]'
```

:::warning

Keep `--node-lock-retry-timeout` below the extender `httpTimeout` in the KubeSchedulerConfiguration, which the chart sets to `30s`. If the retry outlives the HTTP call, kube-scheduler abandons the bind request while the extender is still waiting for the lock, and the Pod is retried from the top.

:::

The default of `28s` leaves 2 seconds of headroom under that `30s` timeout.

## Troubleshooting

**Pods stay Pending with `BindingFailed: node <name> has been locked within 5m0s`**

The retry is not active for these Pods. Check that the `scheduling.x-k8s.io/pod-group` label is on the Pod (not the PodGroup only, and not in annotations), and that `--node-lock-retry-timeout` is not set to `0`.

**The scheduler container crash-loops on startup**

Look for `only one queue sort plugin required` in the kube-scheduler logs. `PrioritySort` is still enabled alongside Coscheduling. See [step 3](#3-enable-coscheduling-in-the-scheduler-config).

**All members of a group stay Pending and no node is ever selected**

Either fewer than `minMember` members were created, or the scheduler cannot read `PodGroup` resources. Check the kube-scheduler logs for `PreFilter failed` and confirm the RBAC from [step 4](#4-grant-access-to-podgroups) is applied.

**Containers fail with `libdl.so.2: cannot open shared object file`**

HAMi injects `LD_PRELOAD` pointing at a glibc build of `libvgpu.so`. Images based on musl, such as `busybox` and `alpine`, cannot load it. Use a glibc image for GPU workloads.

## Related links

- [Coscheduling plugin](https://github.com/kubernetes-sigs/scheduler-plugins/tree/master/pkg/coscheduling)
- [scheduler-plugins releases](https://github.com/kubernetes-sigs/scheduler-plugins/releases)
- [Global Config](../configure.md)
- [Using HAMi with Kueue](../kueue/how-to-use-kueue.md)
- [Using HAMi with KAI Scheduler](../kai-scheduler/how-to-use-kai-scheduler.md)
4 changes: 4 additions & 0 deletions i18n/zh/docusaurus-plugin-content-docs/current.json
Original file line number Diff line number Diff line change
Expand Up @@ -103,6 +103,10 @@
"message": "在 Kueue 中使用 HAMi",
"description": "The label for category 'Using HAMi with Kueue' in sidebar 'docs'"
},
"sidebar.docs.category.Using HAMi with Coscheduling": {
"message": "在 HAMi 中使用 Coscheduling",
"description": "The label for category 'Using HAMi with Coscheduling' in sidebar 'docs'"
},
"sidebar.docs.category.nvidia-examples": {
"message": "示例",
"description": "The label for category 'Examples' in sidebar 'docs'"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -73,6 +73,20 @@ helm install hami hami-charts/hami --set devicePlugin.deviceMemoryScaling=5 -n k
| `scheduler.defaultSchedulerPolicy.nodeSchedulerPolicy` | 字符串 | GPU 节点调度策略:`"binpack"` 表示尽可能将任务分配到同一个 GPU 节点;`"spread"` 表示尽可能将任务分配到不同的 GPU 节点。 | `"binpack"` |
| `scheduler.defaultSchedulerPolicy.gpuSchedulerPolicy` | 字符串 | GPU 调度策略:`"binpack"` 表示尽可能将任务分配到同一个 GPU;`"spread"` 表示尽可能将任务分配到不同的 GPU。 | `"spread"` |

## 调度器配置:扩展器参数

调度器扩展器从 `scheduler.extender.extraArgs` 读取命令行参数。chart 默认值为 `["--debug", "-v=4"]`,设置该值会替换整个列表,因此需要保留想要沿用的条目:

```bash
helm upgrade hami hami-charts/hami -n kube-system --reuse-values \
--set-json 'scheduler.extender.extraArgs=["--debug","-v=4","--node-lock-retry-timeout=28s"]'
```

| 参数 | 类型 | 描述 | 默认值 |
| --- | --- | --- | --- |
| `--node-lock-retry-timeout` | 时长 | 当节点锁被同一个 PodGroup 的其他成员持有时,`Bind` 重试该锁的时长。仅对带有 `scheduling.x-k8s.io/pod-group` 标签的 Pod 生效,其他 Pod 保持原有的快速失败行为。设为 `0` 关闭重试。该值需小于 KubeSchedulerConfiguration 中扩展器的 `httpTimeout`(chart 设为 `30s`)。参见[如何在 HAMi 中使用 Coscheduling](coscheduling/how-to-use-coscheduling.md)。 | `28s` |
| `--node-lock-timeout` | 时长 | 一把节点锁在被其他 Pod 接管前的有效期。对所有 Pod 生效,不限于 PodGroup 成员。 | `5m` |

## Pod 配置:注解

| 参数 | 类型 | 描述 | 示例 |
Expand Down
Loading