Andrew Mercer
on this page

How KUBECONFIG merging works

kubectl normally reads a single file at ~/.kube/config, but the KUBECONFIG environment variable can list multiple files separated by : (Linux/macOS) or ; (Windows). When more than one file is listed, kubectl config view reads all of them and merges their clusters, contexts, and users entries into a single in-memory view — it doesn't touch any of the source files unless you redirect the output somewhere yourself.

KUBECONFIG=$HOME/.kube/cluster0:$HOME/.kube/cluster1:$HOME/.kube/cluster2:$HOME/.kube/cluster3 \
  kubectl config view --flatten > $HOME/.kube/config-merged

(Adjust the file list to whatever kubeconfig files you actually have — the numbering above is just an example set of cluster names, not a required naming scheme.)

  • Merging is the default. kubectl config view merges every file in KUBECONFIG automatically (--merge defaults to true, so adding it changes nothing).
  • --flatten inlines any certificate/key data that the source files reference by file path (client-certificate: /path/to/cert) directly into the merged output as base64 (client-certificate-data: ...). Without --flatten, the merged file would still work on this machine, but would break if copied elsewhere, since the embedded file paths wouldn't resolve on a different host.
  • The > ~/.kube/config-merged redirect is what actually writes a new file — kubectl config view on its own only prints to stdout and never modifies anything.

Symlinking it as the default config

ln -s config-merged config

This only creates a working symlink if run from inside ~/.kube, since ln -s config-merged config creates a relative symlink pointing at the plain filename config-merged in whatever directory you're currently in:

cd ~/.kube
ln -s config-merged config

Once ~/.kube/config is a symlink to ~/.kube/config-merged, kubectl picks it up automatically as its default config (no KUBECONFIG env var needed for day-to-day use), since ~/.kube/config is kubectl's built-in default path.

If ~/.kube/config already exists as a real file (not yet a symlink), back it up first rather than overwriting it blindly:

mv ~/.kube/config ~/.kube/config.bak
cd ~/.kube && ln -s config-merged config

Naming collisions

If two source kubeconfig files happen to use the same context, cluster, or user name (e.g. two clusters both named default), the merge keeps only one of them — the first file in the KUBECONFIG list that defines that name wins, and the later ones are silently dropped with no warning. Before merging files from different sources, it's worth checking each one's context/cluster/user names for collisions:

kubectl config view --kubeconfig=$HOME/.kube/cluster0 -o jsonpath='{.contexts[*].name}'

Rename a context to avoid a collision before merging. Use $HOME rather than ~ here, because the shell doesn't expand ~ after --kubeconfig=:

kubectl config rename-context old-name new-name --kubeconfig=$HOME/.kube/cluster0

Verify the merged result

kubectl config get-contexts

This lists every context now available in the merged config, with a * marking the currently active one. Confirm the count matches what you expect (e.g. 4 source files should generally produce 4 contexts, assuming no collisions silently dropped one).

Switch between clusters

kubectl config use-context [ context_name ]

Sets current-context in the config file, so subsequent kubectl commands target that cluster until you switch again. To check which context is currently active without listing all of them:

kubectl config current-context

To temporarily target a different context for a single command without changing the persistent default:

kubectl --context=[ context_name ] get pods

Re-running the merge later

Since config-merged is a generated artifact, not a source of truth, re-run the same KUBECONFIG=... kubectl config view --flatten > ~/.kube/config-merged command any time one of the source cluster kubeconfig files changes (e.g. after rotating a cluster's certificates) — the symlink at ~/.kube/config will automatically reflect the regenerated file without needing to be recreated.

Security note

The merged file contains embedded credentials (client certs/keys or tokens) for every cluster listed, inlined via --flatten — treat ~/.kube/config-merged with the same care as the individual source files, and make sure its permissions aren't more permissive than the originals:

chmod 600 ~/.kube/config-merged

To avoid the file ever existing with looser permissions, generate it under a restrictive umask:

(umask 077; KUBECONFIG=... kubectl config view --flatten > ~/.kube/config-merged)

See also

Monitoring and Inspecting Resources with kubectl covers --context= usage as part of a broader inspection workflow once multiple clusters are configured.