Skip to content

Fix k8smount dropping keys mounted at nested paths - #457

Open
ybai08 wants to merge 1 commit into
knadh:masterfrom
ybai08:fix/k8smount-nested-paths
Open

ybai08 wants to merge 1 commit into
knadh:masterfrom
ybai08:fix/k8smount-nested-paths

Conversation

@ybai08

@ybai08 ybai08 commented Oct 17, 2026

Copy link
Copy Markdown

When a ConfigMap or Secret key is projected at a nested path (items: - key: level, path: log/level, or a projected volume with path: certs/ca.crt), the kubelet does not link the file itself at the top of the mount. It links the first directory instead (createUserVisibleFiles in atomic_writer.go):

..2026_10_17_00_00_00.000000000/name
..2026_10_17_00_00_00.000000000/log/level
..data -> ..2026_10_17_00_00_00.000000000
name   -> ..data/name
log    -> ..data/log

fs.WalkDir doesn't follow symlinks, so log was seen as a directory and never walked, and log.level was missing from the result with no error. The provider docs say such a key "will always produce {"log":{"level":"INFO"}}", and that holds for a plain directory but not for a real volume mount.

before: map[name:app]
after:  map[log:map[level:INFO] name:app]

The fix: when walkDir resolves a top-level symlink to a directory (other than ..data and the timestamped dirs), Read walks it. fs.WalkDir does follow a symlink when it's given as the root. The walk follows only top-level links, because those are the only ones the kubelet creates. A link to a directory further down, such as one pointing back at the mount, is still not followed, so there's no loop.

writeVolumeMountAt in the test helper now makes the same links as the kubelet for nested keys (link the first path segment). Before, it couldn't create a nested key at all, because os.Symlink("..data/log/level", "log/level") fails without a log dir. There's also a new nested path case in Test_K8SMount_Read_WithVolumeMount.

Tests (from providers/k8smount, GOWORK=off because the module isn't in go.work):

  • go test -run Test_K8SMount_Read_WithVolumeMount . without the provider change: nested_path fails (actual: map[a_foo:foo-value]); with it: passes.
  • go test ., go test -race ., go vet ., gofmt -l .: clean.

Not run: Go 1.23/1.24 from the CI matrix, which doesn't cover this module anyway (it needs Go 1.25 and isn't in go.work). Not tried against a real cluster.

Kubernetes mounts a ConfigMap or Secret key with a nested path, such as
"log/level", through a symlink to its first directory ("log ->
..data/log"). fs.WalkDir does not follow symlinks, so the provider never
read the files behind it and the keys were silently missing, although
the docs say they are split into {"log":{"level":...}}.

Walk the directory behind a top-level symlink. The test helper now
creates the same links as the kubelet for nested keys.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant