skip to content

In a platform's 18-chart Helm umbrella, how strict would you make each chart's values.schema.json?

level: principalimportance: should knowfreq 31%

answer

  1. Not one rule for every chart
  2. Close what you own, open what you forward
  3. Some invariants only exist at render time
  4. Tightening breaks yesterday's working values
  5. A contract offered, not a control enforced

basics

~20 s

Strict where the chart makes a promise, open where it passes values through. Type and close the objects the chart owns, leave subchart and global subtrees to their own schemas, and treat tightening a published schema as a breaking chart version rather than a patch.

solid answer

~50 s

I would set strictness per chart rather than by fleet-wide rule. For a leaf chart that many teams install, closing every object the chart owns and typing its leaves is worth the maintenance, because the schema is the only thing standing between a consumer's typo and a silent production change. For the umbrella that composes them, the schema should stay deliberately open at the subchart boundary - each subchart already polices its own subtree, and a closed parent breaks whenever a subchart is added. Second, I decide what a schema cannot express and push it into the template with `required` and `fail`: cross-field rules, cluster-capability checks, anything that depends on rendering. Third, I version it as contract: tightening a schema rejects values that installed yesterday, so it ships with a chart version bump and a note. Finally I place the gate - a render-and-validate job in the chart repo, plus the consumer-side check the packaged schema gives away for free.

go deeper

for a junior

You are not expected to design this. Know that a chart may ship a schema, that it constrains what you may put in your values file, and that a failure names the property so you can fix your file.

for a middle

Be able to argue both sides of a single constraint: what closing an object buys the consumer, and what it costs the author when a subchart or a new key arrives. Concrete examples beat principles here.

for a senior

Show you have maintained one. Talk about the rollout of a tightening, the render matrix that catches drift, and the cases where you deliberately left an object open because the chart only forwards it.

for a principal

Own the contract question: how strict per chart population, what a version bump signals to consumers, where the gate sits given that it can be skipped, and which rules belong at admission rather than in every chart's schema.

### Strictness is a per-chart decision, not a policy An 18-chart umbrella contains at least three populations, and one strictness rule for all of them is wrong. The leaf charts your platform team authors and dozens of consumers install are the ones that earn a tight schema: they promise a key set, that promise is what other teams write files against, and a closed schema converts the worst Helm failure mode - an undeclared key merged in and never read - into an error before anything is rendered. The umbrella that composes those charts is the opposite case: its top level is mostly a pass-through, one key per subchart plus `global`, and closing it means every subchart addition is a schema edit and every mismatch is an install failure with a confusing message. Vendored third-party subcharts are the third case, where you inherit whatever schema the author wrote and your leverage is limited to not making it worse. The rule of thumb that survives contact: close what you own, open what you forward. Objects the chart's own templates read get `additionalProperties: false`, typed leaves, `enum` for the small string sets, and bounds on the numbers. Objects that exist only to be handed to something else stay `{"type": "object"}`. ### What a schema cannot do JSON Schema describes a document's shape. It knows nothing about the cluster, nothing about rendering, and nothing about the semantics of a combination. Invariants that depend on the render - a value that must be set only when a feature flag is on, a check that the target cluster offers an API version through `.Capabilities`, a name that must stay within the length a rendered object allows - belong in the templates with `required` and `fail`. Deciding this split explicitly is part of the design: a team that tries to express everything in the schema ends up with a document nobody can read, and a team that expresses nothing there loses the one check that runs before rendering. It is also worth stating the outer boundary. A per-chart schema constrains one chart's inputs. Rules that apply across every chart in the organisation regardless of who wrote it - what every workload must carry, what nobody may set - are not a values-schema job; they belong to an admission policy engine at the cluster edge, which sees the rendered objects rather than the inputs. Confusing the two produces 18 copies of the same half-enforced rule. ### The schema is a versioned contract This is the part people get wrong. Adding `additionalProperties: false` to a chart that consumers have been feeding extra keys to will break their next upgrade, and tightening a type or narrowing an enum does the same. The schema is packaged into the `.tgz` and published with the chart, so it is not an internal file - it is part of the artifact consumers pull. Tightening therefore belongs to a deliberate version bump with a release note, ideally with a grace period during which the chart's own CI renders the top consumers' values files against the new schema to find out who breaks. Loosening is safe and can ride any release. The corollary is drift. A schema that has fallen behind its templates is worse than none, because it passes and people trust it. The only defence is rendering: a CI job in the chart repository that renders each chart against a small matrix of representative values files exercises schema and templates together, and it is the job that actually catches a key the templates stopped reading two versions ago. ### Where the gate lives, and what it is worth Three placements, with different force. In the chart's own repository the check is authoritative for the chart but says nothing about how consumers configure it. In the consumer's pipeline it catches the typo before delivery, and because the schema ships inside the chart, consumers get it whether or not they opt in - that is the strongest argument for shipping one at all. In the delivery path it is the last chance, and it is the weakest, because `--skip-schema-validation` exists and any operator running the command can pass it. A values schema is a contract you offer, not a control you enforce; if something must be unskippable, it has to sit where the rendered objects arrive, not where the inputs are read. ### What I would actually do For the 18-chart umbrella: tight schemas on the 6 platform-authored leaf charts that other teams consume, typed and closed; an open pass-through schema on the umbrella declaring the subchart keys and `global` and closing only its own handful of top-level knobs; nothing added to vendored subcharts; a render matrix in CI over 4 representative values files per chart; and a written rule that a schema tightening is a minor version bump with a note, never a patch.

  • How do you introduce a stricter schema to a chart many teams already consume?
    Ship it as a version bump with a release note, and buy information first: run the new schema against the values files your top consumers actually use - in the chart repository's CI if you can see them - so you know who breaks before they do. Loosening can go out quietly; tightening is a contract change and deserves to be announced as one.
  • Which invariants would you deliberately keep out of the schema?
    Anything the schema cannot see: cross-field rules that only make sense at render time, checks against what the target cluster supports, and constraints on rendered output such as generated name lengths. Those go into the templates with `required` and `fail`. Organisation-wide rules spanning every chart are a different layer again and belong at admission, not in 18 separate schemas.
  • Is a values schema a security control?
    No. It runs on the caller's machine as part of a command the caller controls, and it can be skipped with a flag. It is a correctness contract that catches honest mistakes early and documents the chart's inputs. Anything that must hold regardless of who ran the command has to be enforced where the objects land, not where the values are read.
  • How do you keep 18 schemas from drifting behind their templates?
    Render, do not just validate. A CI job per chart that renders a matrix of representative values files exercises the templates and the schema together and fails when a declared key is no longer read or a read key was never declared. Reviewing schema and template changes in the same pull request is the cheap half; the render matrix is the half that actually catches drift.

It is the same call as choosing how strict a public library's argument validation should be: rejecting nonsense early saves callers from silent misbehaviour, but every constraint you add later is a breaking change for someone already calling you.

saying these in an interview costs you the question

  • Applies one strictness rule to every chart in the fleet
  • Treats schema tightening as a patch-level change
  • Calls a values schema a security or policy control
  • Tries to express cluster-dependent rules in JSON Schema
  • Adds schemas but never renders charts in CI
  • Closes the umbrella's root and blames the subcharts

context