Skip to content
Merged
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
Original file line number Diff line number Diff line change
Expand Up @@ -202,11 +202,12 @@ strip CRs. Regenerate it with the commands above.
Kueue's `selectableFields` is gated at 1.31 and helm otherwise substitutes its own built-in version:

```bash
./.sbin/helm version --short # expect v3.21.0
./.sbin/helm version --short # expect v3.21.4
./.sbin/helm template gpustack-operator deploy/gpustack-operator/chart --kube-version 1.33.0
```

6. `make test chart` — `ct install` in a container (docker + `~/.kube/config`, current context) into a
6. `make test chart` — `ct install` in a container (docker + the kubeconfig `KUBECONFIG` names, or
`~/.kube/config` when it names none, mounted read-only with its own context) into a
namespace **chart-testing generates**, which is also what proves the chart names no namespace of its own.
Needs a reachable Kubernetes cluster with **no conflicting release**: the chart templates cluster-scoped
objects and Helm refuses any object carrying another release's ownership metadata. `hack/lib/helm.sh`
Expand Down Expand Up @@ -262,7 +263,7 @@ strip CRs. Regenerate it with the commands above.

- **A PATH `helm` shadows the pin.** `gpustack::helm::helm::validate` returns early on any PATH `helm` and
`make deps` never installs one; a system 3.13 has no `--take-ownership`. Use `./.sbin/helm` and assert
`version --short` is v3.21.0. (chart-testing runs its own bundled helm in a container; the pin is moot there.)
`version --short` is v3.21.4. (chart-testing runs its own bundled helm in a container; the pin is moot there.)
- **`Chart.lock` goes stale silently.** `helm template`/`lint` ignore it; `helm dependency build` — which
chart-testing runs — fails *"the lock file (Chart.lock) is out of sync with the dependencies file"*. Delete
it after any `Chart.yaml` dependency edit.
Expand Down
2 changes: 1 addition & 1 deletion docs/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -152,7 +152,7 @@ A skill link names a procedure; the entry's other fields carry shared facts.
- Use for: build, lint, test and codegen commands; commit and PR conventions; contributor invariants; release steps; site publication and translations.
- Aliases: `make`, `lint`, `codegen`, `vendored dependencies`, `staging`, `Hugo`, `GitHub Pages`
- Guides: commands and targets in [Development](contribute/development.md); a local test cluster in [kind Setup](contribute/kind.md); startup invariants in [Internals](contribute/internals.md); orientation in [Architecture](getting-started/architecture.md).
- Code: [Makefile](../Makefile) and the scripts behind it in [hack](../hack/) · site publication in [Site workflow](../.github/workflows/site.yml) and [publisher](../hack/site/publish.py) · patched modules in [staging](../staging/) · generators in [gen](../gen/) · upgrade compatibility checks in [upgrade-compat.sh](../hack/check/upgrade-compat.sh)
- Code: [Makefile](../Makefile) and the scripts behind it in [hack](../hack/) · site publication in [Site workflow](../.github/workflows/site.yml) and [publisher](../hack/site/publish.py) · patched modules in [staging](../staging/) · generators in [gen](../gen/) · upgrade compatibility checks in [upgrade-compat.sh](../hack/check/upgrade-compat.sh) · the chart test's kubeconfig isolation in [helm.sh](../hack/lib/helm.sh) and [helm-chart-test-selftest.sh](../hack/check/helm-chart-test-selftest.sh)
- Related: [API Changes](#api-changes) (what `make generate` owns) · [Installation](#installation) (chart targets and vendoring)
- Skills: [gpustack-operator-overview](../.agents/skills/gpustack-operator-overview/SKILL.md) (codebase tour) · [gpustack-operator-docs](../.agents/skills/gpustack-operator-docs/SKILL.md) (documentation changes) · [gpustack-operator-code-review](../.agents/skills/gpustack-operator-code-review/SKILL.md) (PR review criteria) · [gpustack-operator-issue-pr](../.agents/skills/gpustack-operator-issue-pr/SKILL.md) (issue and PR titles) · [gpustack-operator-release](../.agents/skills/gpustack-operator-release/SKILL.md) (cut a release) · [gpustack-operator-generate](../.agents/skills/gpustack-operator-generate/SKILL.md) (API codegen)

Expand Down
2 changes: 1 addition & 1 deletion docs/contribute/development.md
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,7 @@ clone. The verdict on committed `.agents` shell comes from `agents-shell.yml` an

- `make generate chart` — regenerate `README.md` (from `README.md.gotmpl`) and `values.schema.json`. **Never hand-edit those two**: edit `values.yaml`/its annotations/`README.md.gotmpl` and re-run, after **any** `values.yaml` edit — the generated schema is what rejects a bad install. Nothing in `values.yaml` is generated: Kueue's *`resources.transformations`* is rendered at install time by a chart helper a patch adds to its config.
- `make lint chart` — `ct lint` in a container, then assert the `global.*` image settings reach every image the chart and its subcharts render (`gpustack::helm::verify_images`).
- `make test chart` — `ct install` onto the current cluster in a container; needs a reachable cluster (e.g. kind) and `~/.kube/config`. It installs `CHART_TEST_IMAGE_REPOSITORY`:`CHART_TEST_IMAGE_TAG`, by default the published `gpustack/gpustack-operator:dev`, which is built from `main`. To test a chart change together with the binary it needs, build the tree, load the image into the cluster, and name it in those two variables. The Chart workflow does this on every run.
- `make test chart` — `ct install` into the cluster the caller's kubeconfig names, in a container; needs a reachable cluster (e.g. kind). The kubeconfig is the file `KUBECONFIG` names, or `~/.kube/config` when `KUBECONFIG` is unset. A path that does not exist, that names a directory, or that lists more than one file is refused before the container starts: Docker turns a missing bind-mount source into a directory, and the container mounts exactly one file. The file is mounted read-only and unchanged, so the cluster the install reaches and the context it uses are the ones that file already names. It installs `CHART_TEST_IMAGE_REPOSITORY`:`CHART_TEST_IMAGE_TAG`, by default the published `gpustack/gpustack-operator:dev`, which is built from `main`. To test a chart change together with the binary it needs, build the tree, load the image into the cluster, and name it in those two variables. The Chart workflow does this on every run.

### Vendored subcharts

Expand Down
2 changes: 1 addition & 1 deletion docs/reference/settings.md
Original file line number Diff line number Diff line change
Expand Up @@ -151,7 +151,7 @@ request that reaches a webhook. Neither window needs a restart.
| `instance-host-path-volume-allowed`<br/>(`GPUSTACK_INSTANCE_HOST_PATH_VOLUME_ALLOWED`) | Effect window: Immediate<br/>Default: `false`<br/>Usage: Whether an `Instance` may mount a hostPath volume (*`spec.additionalVolumes[*].hostPath`*), which reaches the node's filesystem. Kept separate from `instance-privileged-allowed` because it grants strictly less — the filesystem, but not the node's devices or kernel — so an admin can allow node-path mounts without allowing a container escape. Enforced whenever an `Instance` **takes** a hostPath mount, on the same terms; a mount it already has is matched by value, so reordering the list is not a new grant while repointing an entry at a different node path is. |
| `instance-persistent-volume-placement`<br/>(`GPUSTACK_INSTANCE_PERSISTENT_VOLUME_PLACEMENT`) | Effect window: Next trigger<br/>Default: `true`<br/>Usage: Whether an `Instance`'s persistent claims (*`spec.volume.persistent`*, *`spec.additionalVolumes[*].persistent`*) decide where its `Pod` runs, by the [claim placement rules](../modules/model-delivery/artifact.md#claim-delivery-and-placement): a bound claim adds its PV's required node affinity, and a claim nothing binds holds the `Pod` back with the reason in *`status.phaseMessage`*. **`false` is the escape path**: the `Pod` is built from the claim names alone, as before, and Kueue's topology-aware scheduling may then assign a node the volume cannot reach, leaving the `Pod` Pending while its `Workload` holds quota. Read when a `Pod` is created, so a change never moves a running `Instance`; stop and start one to apply it. |
| `instance-privileged-allowed`<br/>(`GPUSTACK_INSTANCE_PRIVILEGED_ALLOWED`) | Effect window: Immediate<br/>Default: `false`<br/>Usage: Whether an `Instance` may request privileged mode (*`spec.privileged`*), which escapes the container boundary and exposes the node's devices and kernel surface. Enforced by the `Instance` admission webhook whenever an `Instance` **takes** privileged mode — at creation, or through a later change, including one made while it is stopped. An `Instance` that already runs privileged keeps it: with this off it stays updatable, editable while stopped, and restartable. Like every setting here, a change takes up to 30s to reach the webhook, so an `Instance` created in that window is judged against the previous value. |
| `instance-ssh-server-image`<br/>(`GPUSTACK_INSTANCE_SSH_SERVER_IMAGE`) | Effect window: Next trigger<br/>Default: `gpustack/ssh-server:v1.3.0`<br/>Usage: Image of the SSH server used when deploying `Instance`s. |
| `instance-ssh-server-image`<br/>(`GPUSTACK_INSTANCE_SSH_SERVER_IMAGE`) | Effect window: Next trigger<br/>Default: `gpustack/ssh-server:v1.4.0`<br/>Usage: Image of the SSH server used when deploying `Instance`s. |
| `instance-isolation-pod-cidrs`<br/>(`GPUSTACK_INSTANCE_ISOLATION_POD_CIDRS`) | Effect window: Immediate<br/>Default: *(blank)*<br/>Usage: The IPv4 pod CIDRs the Instance tenant-isolation `NetworkPolicy` carves out of its 0.0.0.0/0 external rule: `Instance` `Pod`s stay reachable from their own namespace and from outside the cluster, and never from another namespace's `Pod`s — see [Network isolation](../modules/instances/_index.md#network-isolation). **Blank (default) renders no policy at all**: isolation is opt-in, and emptying the list collects the rendered policy again, never a same-named one written by hand. Needs a CNI that enforces `NetworkPolicy`; find the values with `kubectl get ippools.crd.projectcalico.org` on a Calico-IPAM cluster, or `kubectl get nodes -o jsonpath='{.items[*].spec.podCIDRs}'` where the nodes carve the pod addresses. Read by the namespace-isolation controller, which watches the delegated settings Secret: a change reconciles every non-reserved namespace within seconds. The chart carries the same value as `worker.instanceIsolationPodCIDRs`. |
| `instance-type-aware-cpu-manufacturer`<br/>(`GPUSTACK_INSTANCE_TYPE_AWARE_CPU_MANUFACTURER`) | Effect window: Next trigger<br/>Default: `false`<br/>Usage: Whether the derived `ClusterQueue`/`InstanceType`/`InstanceTypeFlavor` aggregation splits by CPU manufacturer. When `false`, non-accelerated flavors collapse into one `generic` pool per os/arch and accelerated flavors pool per accelerator (CPU ignored); when `true`, every pool splits by the CPU key (`gpustack--${gKey}-…` / `gpustack--${gKey}--${aKey}-…`) and the `InstanceType` records the raw CPU detail. The `ResourceFlavor`s themselves are unaffected — they always carry the CPU key, so a flip only re-groups the aggregation layer. Read per-reconcile. |
| `instance-type-derived-from-node`<br/>(`GPUSTACK_INSTANCE_TYPE_DERIVED_FROM_NODE`) | Effect window: Next trigger<br/>Default: `true`<br/>Usage: Whether the operator auto-derives the `InstanceType` (and its backing `ClusterQueue`) from node hardware. When `true`, the `NodeFlavorReconciler` authors the derived `InstanceType` (create-only); when `false`, it only aligns the `ResourceFlavor` and the administrator defines the `InstanceType` via the API, and owns feasibility with it — see [Authoring the InstanceType](#authoring-the-instancetype). Read per-reconcile. |
Expand Down
Loading
Loading