ADR-1074: Helm chart values completeness — missing knobs and schema gaps¶
- Status: Accepted
- Date: 2026-06-06
- Deciders: Lusoris
- Tags:
helm,k8s,bug
Context¶
A systematic audit of deploy/helm/vmafx/values.yaml against values.schema.json and every template under deploy/helm/vmafx/templates/ revealed four completeness gaps that cause either silent misconfiguration or a hard helm lint failure when users supply standard Helm override keys:
-
nameOverride/fullnameOverrideabsent from both values.yaml and schema. The helpers in_helpers.tplread{{ .Values.nameOverride }}and{{ .Values.fullnameOverride }}(lines 10, 18–19, 21). Because the root schema carries"additionalProperties": false, any user who sets--set nameOverride=foogets an immediatehelm lint/helm installschema validation failure — the canonical Helm convention is completely blocked. -
StatefulSet inline PVC size hardcoded to
1Gi.templates/statefulset.yamlline 145 emitsstorage: 1Giliterally. The StatefulSetstatevolume holds MCP server session state at/var/lib/vmafx; operators with large or long-lived sessions cannot tune this without forking the template. -
node.metricsPortabsent from values — 9090 hardcoded in three places.templates/node.yamllines 82 and 188 andtemplates/networkpolicy.yamlline 255 all hardcode port 9090. Operators who need to run vmafx-node alongside another Prometheus-scraped workload on the same port (a common cluster constraint) have no override path. The NetworkPolicy allow-rule silently opens the wrong port if the node binary is reconfigured externally. -
service.extraPortsitems schema is untyped. The schema emits"extraPorts": { "type": "array" }with noitemsdefinition. A malformed port object (missingname, non-integerport) passeshelm lintsilently and only fails atkubectl applytime with an opaque apiserver error.
Decision¶
Fix all four gaps:
- Add
nameOverride: ""andfullnameOverride: ""to values.yaml and to the rootpropertiesblock in values.schema.json (bothtype: string). - Add
statefulSet.statePVCSize: "1Gi"to values.yaml; wire it into thevolumeClaimTemplates[0].spec.resources.requests.storagefield intemplates/statefulset.yaml; add the key to thestatefulSetproperties block in the schema with a Kubernetes-quantitypatternconstraint. - Add
node.metricsPort: 9090to values.yaml; replace all three hardcoded9090occurrences in templates with{{ .Values.node.metricsPort | default 9090 }}; add the key to thenodeproperties block in the schema withminimum: 1, maximum: 65535. - Replace the bare
"extraPorts": { "type": "array" }in theserviceschema with anitemsobject that requiresnameandportand validatesprotocolas an enum.
No template logic changes beyond the four targeted substitutions; no new required fields are introduced; default values preserve existing rendered output byte-for-byte.
Alternatives considered¶
| Option | Pros | Cons | Why not chosen |
|---|---|---|---|
Leave nameOverride/fullnameOverride out of schema; set additionalProperties: true at root | No schema change needed | Loses all type-safety on misspelled top-level keys; ADR-1047 explicitly chose strict root schema | Not chosen; strict root additionalProperties: false is load-bearing |
| Expose operator ports (8081/8082) as values too | Consistent with node.metricsPort pattern | Operator port conflicts are rare and the operator args would need re-wiring beyond just the port | Deferred; operator port exposure is a separate concern with lower urgency |
Validate extraPorts items with unevaluatedProperties: false | Stricter | JSON Schema 2020-12 unevaluatedProperties is not supported by helm's validator (uses draft-07 semantics internally) | Not chosen; required + properties is the portable subset |
Consequences¶
- Positive:
helm lintandhelm install --dry-runnow catch all four classes of misconfiguration. Standard HelmnameOverride/fullnameOverrideconventions work without schema rejection. StatefulSet PVC size and node metrics port are documented operator knobs. - Negative: Users who supplied a custom
extraPortsitem without anamefield will now receive a schema validation error. This is intentional — a nameless port is invalid Kubernetes YAML. - Neutral / follow-ups: The
statePVCSizedefault"1Gi"andmetricsPortdefault9090preserve current rendered output; no migration needed for existing installs.
References¶
deploy/helm/vmafx/values.yaml,deploy/helm/vmafx/values.schema.json.deploy/helm/vmafx/templates/statefulset.yaml(line 145 — hardcoded1Gi).deploy/helm/vmafx/templates/node.yaml(lines 82, 188 — hardcoded9090).deploy/helm/vmafx/templates/networkpolicy.yaml(line 255 — hardcoded9090).deploy/helm/vmafx/templates/_helpers.tpl(lines 10, 18–21 —nameOverride/fullnameOverride).- ADR-1047: preceding Helm schema correctness fixes (R9 batch).