skip to content

How do you make Helm drop a key the chart's values.yaml sets, not just override it?

level: seniorimportance: nice to knowfreq 30%

answer

  1. Overriding is not the same as removing
  2. Empty is not the same as absent
  3. An empty map contributes nothing to a merge
  4. One YAML scalar deletes the key during merge

basics

~20 s

Set the key to null in your override - key: null in a -f file, or --set key=null. Helm's merge drops a key whose override value is null, so it never reaches .Values. An empty string, {} or [] does not remove it.

solid answer

~50 s

Overriding and removing are different operations in Helm, and only `null` removes. During the merge, a key whose higher-precedence value is `null` is dropped from the result, so the template renders as if the chart had never defaulted it. Writing an empty string instead sets the key to an empty scalar, which usually renders an invalid field. Writing `{}` over a defaulted map is worse: an empty map contributes no keys, so the deep merge leaves every default in place and your override does exactly nothing - a silent no-op that looks like a fix in review. Both `-f` files and `--set key=null` can do the deletion, and the deletion works against any lower layer, not only the chart. The caveat is that null only removes the value; if the template emits the field unconditionally rather than guarding it, no values override can make it disappear.

code

yaml · 9 lines
yaml
# monitoring-stack/values.yaml - chart default
billingCron:
  schedule: "*/20 * * * *"
  nodeSelector:
    disktype: ssd

# values/prod-eu.yaml - {} is a silent no-op, null deletes
billingCron:
  nodeSelector: null

go deeper

for a junior

Know that removing a chart default is not the same as overriding it, and that key: null in an override file is the way to make the key disappear from the values the templates see.

for a middle

Explain why the alternatives fail: an empty map contributes no keys so the default survives, and an empty string sets an invalid value rather than removing the field. Describe null as an instruction to the merge rather than as data.

for a senior

Demonstrate the diagnosis: two of the three wrong answers render successfully, so you render and diff before applying, and you know when the field cannot be removed by values at all because the template emits it unconditionally.

for a principal

Frame it as a chart-contract issue: consumers needing null tricks to escape a default is a signal the chart defaults too aggressively. Decide when a platform absorbs that with a wrapper values layer and when it pushes the fix upstream into the chart.

Most values work is overriding: the chart says one thing, you say another, yours wins. Occasionally you need something the override model does not obviously provide - for the key to stop existing. Helm has exactly one way to express that, and every intuitive alternative fails in a different way. ## The mechanism When Helm combines a lower-precedence map with a higher-precedence one, a key whose higher-precedence value is `null` is removed from the merged result rather than carried through as an empty value. So `billingCron: {nodeSelector: null}` in a `-f` file, or `--set billingCron.nodeSelector=null` on the command line, produces merged values in which `nodeSelector` is simply absent. A template that guards the field - emitting it only when the value is present and non-empty - then emits nothing at all, which is the outcome you wanted. ## Why the intuitive alternatives fail Consider a monitoring-stack chart whose `values.yaml` gives its subscription-billing cron a `nodeSelector` of `{disktype: ssd}`, and a new cluster with no such nodes: the CronJob is admitted, never schedules, and about seven minutes into the upgrade window someone notices no billing run has fired. Here is what each thing you might reach for actually does. | What you write in the override | What the merge does with it | Result | | --- | --- | --- | | `nodeSelector: {}` | An empty map contributes no keys to a deep merge | Nothing at all - the chart's `disktype: ssd` coalesces straight back in and the rendered CronJob is byte-identical | | `nodeSelector: ""` | Changes the value, but to an empty string | The API expects a map, so the upgrade fails on a validation error | | Delete the block from your override file | You are simply no longer overriding the key | The most misleading of the three - the chart default applies untouched | | `nodeSelector: null` | Removes the key from the merged values | The field is gone, which is what you wanted | Only `nodeSelector: null` deletes. ## What null does and does not reach The deletion is a property of the merge, so it works against any lower layer: a `null` in the last `-f` file removes a key an earlier `-f` file set, and a `--set key=null` removes one a file set, just as it removes a chart default. What it cannot do is change the template. If the chart writes the field unconditionally, an absent value renders as an empty field rather than as no field, and no combination of values will remove it; the chart itself has to guard that block, and if it does not, the fix is a chart change rather than a values change. Similarly, a chart that demands a value and fails the render when it is missing will now fail - which is arguably the chart telling you the key is not optional. ## Verification Because two of the three wrong answers produce a successful render, reading the rendered output is not optional. Render the chart with exactly the flags and files you intend to apply, find the object in question, and confirm the field is gone rather than empty. Then apply. On a release that is already live, compare the rendered candidate against the stored manifest for the current revision; a field disappearing is a visible line in that diff, and a field that stubbornly refuses to disappear is equally visible. ## `[]` versus null for lists The same distinction applies to sequences. `[]` gives an empty list, so the key exists and renders as an empty sequence; `null` removes the key entirely. Both look false to a simple truthiness check, so charts that only ever do a plain conditional will behave identically either way, and charts that check for the presence of the key will not. When you cannot tell which the chart does, prefer `null` - absent is the state that means "the chart author's default does not apply here", and empty is a value in its own right. ## Why this is worth knowing It is not a screening question, and a strong candidate can have a productive Helm career without meeting it. But it is the difference between a five-minute fix and an afternoon spent adding fields to a values file that changes nothing, and it is a small window onto how the merge actually works: the merge does not overwrite values, it constructs a new map, and `null` is the one instruction that tells it to leave a key out.

  • Why does overriding a defaulted map with {} leave the chart's default in place?
    Because maps are deep-merged. An empty map has no keys to contribute, so the merge recurses into it, finds nothing to override, and every key from the lower layer survives. The result is identical to not writing the override at all. Only `null` is treated as an instruction to remove the key rather than as data to merge.
  • Does --set key=null also remove a key that another -f file set, or only a chart default?
    It removes it either way. The deletion is a property of the merge rather than of the chart, so a null at a higher-precedence layer means the key is absent from the final values regardless of which lower layer supplied it. That includes an earlier `-f` file, which is worth remembering when a wrapper script stacks several override files.
  • You null a value and the field still appears in the rendered object. What is going on?
    The template is emitting that field unconditionally rather than guarding it on the value being present. Values control what the template sees, not what it writes, so an absent value renders as an empty field instead of no field. Fixing it means changing the chart to guard the block; no override can remove output the template always produces.

Overriding a value is writing a new answer in the box. Nulling it is tearing the question out of the form, so the reader never sees the field at all.

saying these in an interview costs you the question

  • Sets the key to an empty string and expects it gone
  • Thinks {} clears a map the chart defaulted
  • Believes only values files, not --set, can null a key
  • Expects null to remove a field the template always emits
  • Assumes deleting the key from the override file removes it
  • Says a nulled key renders as the literal string null

context