skip to content

What does a chart's .helmignore file exclude, and when does it have no effect?

level: middleimportance: should knowfreq 52%

answer

  1. It filters what a chart is on disk
  2. Same idea as gitignore, different list
  3. Only matters while reading a directory
  4. An archive's contents are already decided
  5. Pruned directories swallow later negations

basics

~20 s

.helmignore lists glob patterns, one per line, for files Helm leaves out when it loads a chart from a directory — packaging or installing from source. It never applies to an already-packaged .tgz, whose contents were fixed at package time.

solid answer

~50 s

`.helmignore` sits at the chart root and works much like `.gitignore`: one pattern per line, `#` for comments, shell-style globs, a trailing `/` for directory-only matches, and `!` to negate an earlier pattern. Paths are matched relative to the chart root; a pattern with no slash matches by base name at any depth. It applies whenever Helm **loads a chart from a directory** — `helm package`, and also `helm install ./pdfsign` or `helm template ./pdfsign`. It does **not** apply to a packaged archive: a `.tgz` already contains whatever the ignore rules allowed in, and editing the file afterwards changes nothing for that artifact. Two consequences: an excluded directory is pruned rather than walked, so a `!` line naming a file inside it will not bring it back; and an ignored file is invisible to `.Files` during rendering, because the loader never collected it.

code

text · 14 lines
text
# version control and editor noise
.git/
.gitignore
*.swp
.DS_Store

# repo tooling that is not part of the chart
ci/
Makefile
README-dev.md

# 18 MB of sample PDFs used only by local tests
fixtures/*.pdf
!fixtures/default-stamp.pdf

go deeper

for a junior

Know that the file lives at the chart root, holds one glob pattern per line with # comments, and keeps repository noise like .git and editor files out of the chart Helm builds.

for a middle

Explain the mechanics: patterns matched relative to the chart root, base-name matching for slash-free patterns, trailing-slash directory rules, ! negation, and the fact that the rules run when loading a directory and never touch a packaged archive.

for a senior

Show the operational instinct: verify what was packaged rather than trusting the rules, treat a leaked file in a published archive as an exposure needing rotation and a new version, and watch for patterns that strip files the chart actually needs.

for a principal

Own the standard: a shared baseline ignore file across the org's charts, a CI assertion that packaged artifacts contain no denied paths, and a documented response when something private reaches a published chart.

### What it is for A chart directory in a working tree usually holds more than a chart: a `.git` directory, editor droppings, CI config, a `Makefile`, test fixtures, screenshots, sometimes a local `values-dev.yaml` with a real password in it. `helm package` would otherwise sweep all of that into the artifact you hand to other people. `.helmignore` is the filter that decides what a chart *is* when Helm reads it off disk. `helm create` scaffolds one covering version-control and editor noise, and most teams extend it. ### Syntax One pattern per line. Blank lines and lines beginning with `#` are ignored. Patterns are Unix shell globs, matched against paths relative to the chart root: - A pattern with no slash matches by base name at any depth: `*.bak` drops backups wherever they sit. - A pattern containing a slash is anchored relative to the chart root: `ci/reports` matches only that path. - A trailing slash restricts the match to directories: `tests/` excludes the directory, not a file called `tests`. - A leading `!` negates an earlier pattern, re-including something a broader rule had matched. The negation rule has a sharp edge. Helm prunes an excluded directory rather than descending into it, so once `fixtures/` is excluded, `!fixtures/keep-me.pdf` does not resurrect that file — Helm never looked inside. If you need one file out of a large directory, exclude the contents narrowly (`fixtures/*.pdf`) instead of the directory itself. ### When the rules apply — and when they are irrelevant The rules run when Helm **loads a chart from a directory**. That is `helm package`, and it is equally `helm install ./pdfsign`, `helm upgrade ./pdfsign`, `helm template ./pdfsign` and `helm lint ./pdfsign` — installing straight from a source directory is subject to exactly the same filter as packaging. They are irrelevant to an archive. A `.tgz` is a snapshot of the decision that was already made; Helm loading `pdfsign-2.7.3.tgz` reads whatever is in it. This is the point candidates most often get wrong, and it has a concrete operational shape. Suppose the chart for a PDF-signing service carries a `fixtures/` directory of 41 sample documents, about 18 MB, and nobody noticed until `pdfsign-2.7.3.tgz` was already published. Adding `fixtures/` to `.helmignore` fixes every future build; version 2.7.3 stays 18 MB forever. The remedy is a new chart version, 2.7.4, packaged with the corrected rules — not an edit to a published artifact. The same reasoning applies with more force to a secret. If a values file with a real credential was packaged into a published archive, adding an ignore rule afterwards is not remediation: the credential shipped, it is in whatever repository or registry holds that archive, and it must be rotated. ### Second-order effect: the chart's file set Helm builds an in-memory chart from the files the loader collected, so anything `.helmignore` excluded is simply not part of the chart. If a template reads a file from the chart's own contents, ignoring that file makes the render fail or silently produce nothing, and the failure only appears when someone installs from a packaged copy. When a chart deliberately embeds an asset — a default policy document, a config fragment — make sure no broad pattern (`*.json`, `docs/`) is quietly eating it. The reverse mistake is over-broad exclusion of things Helm needs. A blanket pattern that matches archives or subdirectories can strip vendored dependencies out of `charts/`, producing a package that installs fine on your laptop (where `charts/` is populated) and fails for everyone else. Keep patterns specific, and verify by inspecting the artifact rather than trusting the rules. ### Verifying The honest check is to look at what you built: list the archive's contents, or extract it into a temporary directory and compare. Size is a decent smoke signal — a chart that suddenly grows by an order of magnitude has picked up something it should not have. In CI it is cheap to assert that the packaged archive contains no path matching a deny list, which catches the class of mistake before publication rather than after. ### What it is not `.helmignore` is not security. It is not `.gitignore` (a file can be committed and still excluded from the chart, or vice versa — they are independent lists), it is not a values filter, and it does not stop anything a template renders from reaching the cluster. It only decides which files on disk become part of the chart Helm loads.

  • Does .helmignore affect installing straight from a chart directory, or only packaging?
    Both. The rules run whenever Helm loads a chart from a directory, so `helm install ./pdfsign`, `helm template ./pdfsign` and `helm lint ./pdfsign` see the same filtered file set as `helm package`. That is a useful property: what you test from source is the file set that will be packaged, so an ignore mistake shows up before publication if you test the same way.
  • A credential was packaged into a published chart archive. Does adding an ignore rule fix it?
    No. The rule only affects future loads from the directory; the published archive still contains the file, and anyone who pulled it has the credential. Treat it as an exposure: rotate the credential, publish a new chart version with the corrected rules, and remove the bad artifact from wherever it is served. Ignore rules are hygiene, not remediation.
  • Why might a chart render fine locally but fail after packaging?
    Usually because an ignore pattern excluded a file the chart needs. From a source directory the file may still be found by other tooling or simply not exercised, but the packaged chart genuinely does not contain it, so a template that reads it renders empty or errors. The fix is to narrow the pattern and verify by listing the archive's contents rather than re-running from source.

saying these in an interview costs you the question

  • Thinks .helmignore filters files out of an existing .tgz
  • Says it only applies to helm package, not to installs from a directory
  • Believes a ! line can rescue a file inside an excluded directory
  • Treats it as a way to keep secrets safe
  • Confuses it with .gitignore and assumes one implies the other
  • Uses broad patterns and never inspects the packaged archive

context