cluster-setup Chart Values
Complete values.yaml reference with sections for cluster, operator, agent, frontend, monitoring, networking.
The cluster-setup chart installs the Wingsmith operator, optionally the serving agent, DCGM exporter, Dynamo platform, and monitoring in a GPU cluster.
No chart or image is published yet, so install from the repository and run images from a registry of your own.
Required values
| Field | Description |
|---|---|
cluster.id | The plane-assigned cluster id |
cluster.hubUrl | Hub WebSocket address (wss://) |
enrolmentToken.value or enrolmentToken.existing | Cluster’s enrolment token |
The chart refuses to render without cluster.id and cluster.hubUrl.
Cluster
| Field | Default | Description |
|---|---|---|
cluster.id | required | Cluster id |
cluster.hubUrl | required | Hub WebSocket address |
cluster.readOnly | false | Observe and report only; no reconciler runs |
cluster.allowedOperations | [] | Operation kinds a read-only operator still runs |
On a managed cluster (readOnly: false), all three operation types (cordon, drain, benchmark) are allowed. On a read-only cluster, they come from allowedOperations (empty by default).
A read-only install with no operations has no write access outside the release namespace.
Enrolment token
| Field | Description |
|---|---|
enrolmentToken.value | Token value; chart creates the Secret |
enrolmentToken.existing | true to reference an existing Secret |
enrolmentToken.secretName | Name of existing Secret (when existing: true) |
enrolmentToken.key | Key in the Secret (default: token) |
The enrolment token is the cluster’s alone. Mint it on the register screen or with POST /v1/clusters/{ref}/enrolment-token. The plane has no shared token.
Pools
| Field | Default | Description |
|---|---|---|
pools.labelKey | required | Node label workers are placed by |
pools.gpuValue | required | Value for the GPU pool |
pools.cacheValue | required | Value for the weight download pool |
pools.gpuTolerationKey | nvidia.com/gpu | Taint GPU workers tolerate |
pools.gpuTolerationValue | empty | Value for GPU toleration; empty tolerates any value |
pools.cacheTaintKey | hangar.dev/cache | Taint key for weight download nodes |
pools.cacheTaintValue | empty | Value for cache taint |
Example:
pools:
labelKey: hangar.dev/pool
gpuValue: gpu
cacheValue: cache
gpuTolerationKey: nvidia.com/gpu
cacheTaintKey: hangar.dev/cache
Fabric
| Field | Default | Description |
|---|---|---|
fabric.type | empty | RDMA fabric: empty (none), efa, or rdma |
fabric.devices | 0 (except efa) | Interfaces per worker pod |
fabric.resource | vpc.amazonaws.com/efa under efa | Extended resource |
fabric.privileged | true under efa, else false | Run workers privileged with host IPC |
For AWS EFA:
fabric:
type: efa
devices: 4
resource: vpc.amazonaws.com/efa
privileged: true
For RDMA:
fabric:
type: rdma
devices: 2
resource: rdma/hca
privileged: false
Operator
| Field | Default | Description |
|---|---|---|
operator.image.repository | required | Operator image repository |
operator.image.tag | empty (uses appVersion) | Image tag |
operator.image.digest | empty | Image digest (sha256:...); takes precedence over tag |
operator.image.pullPolicy | IfNotPresent | Pull policy |
operator.replicas | 1 | Replica count (run one) |
operator.resources | {} | Resource requests/limits |
Operator workload namespace
| Field | Default | Description |
|---|---|---|
workloadNamespace.name | dynamo | Where rendered workloads and prefetch jobs go |
workloadNamespace.create | true | Create the namespace |
Operator images
| Field | Default | Description |
|---|---|---|
operator.images.allowedPrefixes | [] | Registries or repositories every engine, frontend, and prefetch image must come from; empty allows any |
allowedPrefixes is a security boundary. When set, the operator refuses any image that does not start with one of the listed prefixes.
Operator engine
| Field | Default | Description |
|---|---|---|
operator.engine.imagePullSecrets | [] | Image pull secrets for engine workers |
Operator prefetch
| Field | Default | Description |
|---|---|---|
operator.prefetch.cpu | unset | CPU request |
operator.prefetch.memory | unset | Memory request |
operator.prefetch.memoryLimit | unset | Memory limit |
Operator benchmarks
| Field | Default | Description |
|---|---|---|
operator.benchmark.images | pinned aiperf and evalscope images | Harness images allowed, matched exactly |
images is a security boundary. The operator refuses any harness image not on the list.
Operator metrics
| Field | Default | Description |
|---|---|---|
operator.metrics.enabled | true | Serve metrics on :8080/metrics |
operator.metrics.podMonitor.enabled | false | Create a PodMonitor for Prometheus Operator |
Agent
| Field | Default | Description |
|---|---|---|
agent.enabled | false | Install the serving agent |
agent.replicas | 2 | Replica count |
agent.image.repository | required | Agent image repository |
agent.image.tag | empty (uses appVersion) | Image tag |
agent.image.digest | empty | Image digest |
agent.image.pullPolicy | IfNotPresent | Pull policy |
agent.resources | {} | Resource requests/limits |
agent.terminationGracePeriodSeconds | 120 | Drain timeout budget |
Agent gateway
| Field | Required | Description |
|---|---|---|
agent.gateway.address | yes (when agent.enabled) | Gateway address as host:port |
The agent dials this one address and finds all replicas by redialling.
Agent frontend
| Field | Default | Description |
|---|---|---|
agent.frontendEndpoint | empty (discovers) | The frontend Service to forward to. Empty discovers by label. |
The chart refuses:
agent.enabledwithcluster.readOnly: trueagent.enabledwith an emptygateway.address- A
gatewaythat is still a flat string or carries a scheme - An empty
enrolmentToken.value
Frontend
| Field | Default | Description |
|---|---|---|
frontend.mode | per-model | per-model, shared, or none |
frontend.replicas | 2 | Frontend replica count |
frontend.imagePullSecrets | [] | Image pull secrets |
frontend.anthropicApi | true | Serve /v1/messages |
Frontend mode
| Mode | Description |
|---|---|
per-model (default) | Operator renders a Frontend into each model’s own graph |
shared | One cluster-wide frontend this chart installs |
none | Neither; for a first install or beside agent.frontendEndpoint |
The first install of a new cluster must use frontend.mode=none. A frontend is a DynamoGraphDeployment, and that CRD is applied by the Dynamo operator at runtime, not shipped in this chart’s crds/. Install once with --set frontend.mode=none --set agent.enabled=false, then upgrade naming the topology and turning the agent on.
Changing the mode later is not a configuration change. Dynamo holds a graph’s component set immutable after creation, so every existing graph must be deleted and re-rendered, and every model reloads its weights. Pick before the first model lands.
Per-model frontend
| Field | Default | Description |
|---|---|---|
frontend.perModel.image | required | Frontend image |
frontend.perModel.cpu | unset | CPU request |
frontend.perModel.memory | unset | Memory request |
frontend.perModel.memoryLimit | unset | Memory limit |
Shared frontend
| Field | Default | Description |
|---|---|---|
frontend.shared.image | Dynamo 1.4.1 | Cluster-wide frontend image |
frontend.shared.tag | 1.4.1 | Image tag |
frontend.shared.cpu | unset | CPU request |
frontend.shared.memory | unset | Memory request |
frontend.shared.memoryLimit | unset | Memory limit |
The shared frontend image must match the Dynamo platform version (1.4.1).
Image pull secrets
| Field | Description |
|---|---|
imagePullSecret.create | false; true with registry, username, token has the chart create it |
imagePullSecret.name | Name of existing Secret in release namespace |
imagePullSecret.registry | Registry address |
imagePullSecret.username | Username |
imagePullSecret.token | Token or password |
If your registry needs a credential, set imagePullSecret: name alone references a kubernetes.io/dockerconfigjson Secret you created, or create: true with registry, username, and token has the chart create it.
The Secret is attached to the operator and agent ServiceAccounts. For engine or frontend images in a private registry, name it in operator.engine.imagePullSecrets or frontend.imagePullSecrets, and the chart copies the Secret to the workload namespace.
Monitoring
| Field | Default | Description |
|---|---|---|
monitoring.enabled | false | Install Prometheus in agent mode with remote write |
monitoring.remoteWrite.url | required | Remote write endpoint |
Remote write authentication
Use one of:
| Field | Description |
|---|---|
monitoring.remoteWrite.basicAuth.useEnrolmentToken | true (default): basic auth with cluster ID as username, enrolment token as password |
monitoring.remoteWrite.basicAuth.username / password | Basic auth credentials (with useEnrolmentToken: false) |
monitoring.remoteWrite.basicAuth.existingSecret | Existing Secret for basic auth |
monitoring.remoteWrite.bearerToken.existingSecret | Existing Secret for bearer token |
Example with enrolment token (default):
monitoring:
enabled: true
remoteWrite:
url: https://metrics.example.com/api/v1/push
basicAuth:
useEnrolmentToken: true
Example with custom basic auth:
monitoring:
enabled: true
remoteWrite:
url: https://metrics.example.com/api/v1/push
basicAuth:
useEnrolmentToken: false
username: my-cluster
password: secret
Every series carries cluster (equal to cluster.id) and region external labels.
Networking
| Field | Default | Description |
|---|---|---|
networkPolicy.enabled | true | Create NetworkPolicies |
Serving egress
| Field | Default | Description |
|---|---|---|
networkPolicy.servingEgress.enabled | false | Close egress from workload namespace |
networkPolicy.servingEgress.apiServer | [] | API server CIDRs to allow |
networkPolicy.servingEgress.to | [] | Additional NetworkPolicyPeer egress rules |
Egress from the workload namespace is open by default. Media URLs in a request are fetched from inside the serving pods, so on an open network a request can make them reach internal addresses.
networkPolicy.servingEgress.enabled closes the pods’ egress: they may then reach only their own namespace, the release namespace, DNS, the API server CIDRs, and the peers in to. Prefetch and benchmark jobs are not selected.
Check what your models fetch at startup before turning it on.
Model cache
| Field | Default | Description |
|---|---|---|
modelCache.storageClassName | required | ReadWriteMany storage class |
modelCache.size | 1Ti | PVC size |
The operator mounts the model-cache PVC by name for weight downloads.
Hugging Face token
| Field | Default | Description |
|---|---|---|
hfToken.create | false | Create hf-token-secret Secret |
hfToken.value | unset | Hugging Face token |
For gated models. The chart creates hf-token-secret in the workload namespace when create: true.
Subcharts
DCGM exporter
| Field | Default | Description |
|---|---|---|
dcgm-exporter.enabled | true | Install dcgm-exporter subchart |
NVIDIA’s DCGM exporter provides device identity (UUIDs), device classes, topology domains, and health.
Dynamo platform
| Field | Default | Description |
|---|---|---|
dynamo-platform.enabled | true | Install dynamo-platform subchart (1.4.1) |
The Dynamo platform is a cluster-wide controller with broad permissions (effectively cluster-admin). You should know what you are granting before you install it.
If the Dynamo platform is already installed, or you want to install it yourself, set dynamo-platform.enabled: false and install a 1.4.x release separately. The operator only needs the DynamoGraphDeployment CRD and a Dynamo operator reconciling it.
Versioning
The chart follows SemVer, and appVersion always equals version. The operator and serving-agent images default to that tag (operator.image.tag and agent.image.tag empty), with pullPolicy: IfNotPresent.
Set a tag only to run a build of your own. A mismatched operator and chart is not a supported combination. operator.image.digest and agent.image.digest (sha256:...) pin the exact build and take precedence over the tag.
| Component | Version |
|---|---|
| hangar operator, serving agent | appVersion |
dynamo-platform subchart (Dynamo operator, NATS) | 1.4.1 |
| shared-mode frontend image | 1.4.1 (kept equal to subchart) |
dcgm-exporter subchart | 4.8.3 |
| metrics agent (Prometheus) | v3.5.5 |
| Kubernetes | 1.29 or later |
The Dynamo version is the one the operator renders DynamoGraphDeployments for, and it is what an engine runtime image must be built against.
CRDs
The chart ships two CRDs in crds/, both in the hangar.dev API group at v1alpha1:
SyncedResource: the operator’s local copy of what the plane declaredStreamCheckpoint: the resume cursor on the hub stream
v1alpha1 means the schema can change between releases without a conversion webhook. Helm installs crds/ on the first helm install and never touches it again.
When a release notes a CRD change, apply it yourself before upgrading:
kubectl apply --server-side -f crds/
Example values
Minimal:
cluster:
id: iad-1
hubUrl: wss://plane.example.com/v1/hub/sync
enrolmentToken:
value: hgro1.abcdef...
pools:
labelKey: hangar.dev/pool
gpuValue: gpu
cacheValue: cache
modelCache:
storageClassName: nfs-client
operator:
image:
repository: registry.example.com/hangar/operator
With agent and monitoring:
cluster:
id: iad-1
hubUrl: wss://plane.example.com/v1/hub/sync
readOnly: false
enrolmentToken:
value: hgro1.abcdef...
pools:
labelKey: hangar.dev/pool
gpuValue: gpu
cacheValue: cache
fabric:
type: efa
devices: 4
modelCache:
storageClassName: nfs-client
operator:
image:
repository: registry.example.com/hangar/operator
agent:
enabled: true
replicas: 2
gateway:
address: hangar.example.com:443
image:
repository: registry.example.com/hangar/agent
frontend:
mode: per-model
perModel:
image: registry.example.com/dynamo/frontend:1.4.1
monitoring:
enabled: true
remoteWrite:
url: https://metrics.example.com/api/v1/push