如何将 kubectl 配置文件与 ~/. kube/config 合并?

是否有一个简单的 kubectl命令来获取一个 kubeconfig文件(包含一个集群 + 上下文 + 用户)并将其合并到 ~/。作为附加上下文的 kube/config 文件?

54403 次浏览

Do this:

export KUBECONFIG=~/.kube/config:~/someotherconfig
kubectl config view --flatten

You can then pipe that out to a new file if needed.

If you want to merge two config files in a single one

I found this way (not sure if this is the simplest)

# Add the two config files to the env var
export KUBECONFIG=~/.kube/config:~/Desktop/configFile2.yaml


# Review that you have two configurations in one view
kubectl config view


# View the raw config and output to a new file
kubectl config view --raw > /tmp/config

Then copy the new config file where you want, also do not forget to unset KUBECONFIG the env variable

If you find yourself doing this a lot... There is now also the krew plugin package manager for kubectl.

The krew plugin "konfig" can help you manage your ~/.kube/config file.

Using the konfig plugin the syntax will be:

kubectl konfig import -s new.yaml

To install krew: https://github.com/kubernetes-sigs/krew

To install konfig: kubectl krew install konfig

Using multiple kubeconfigs at once

Sometimes you have a bunch of small kubeconfig files (e.g. one per cluster) but you want to use them all at once, with tools like kubectl or kubectx that work with multiple contexts at once.

To do that, you need a “merged” kubeconfig file. In the section "Merging kubeconfig files" below, we explain how you can merge the kubeconfigs into a single file, but you can also merge them in-memory.

By specifying multiple files in KUBECONFIG environment variable, you can temporarily stitch kubeconfig files together and use them all in kubectl .

#
# Kubeconfig in-memory merge
#
export KUBECONFIG=file1:file2
kubectl get pods --context=cluster-1
kubectl get pods --context=cluster-2


#
# For your example
# merging your kubeconfig file w/ $HOME/.kube/config (w/ cp backup)
#
cp $HOME/.kube/config $HOME/.kube/config.backup.$(date +%Y-%m-%d.%H:%M:%S)
KUBECONFIG= $HOME/.kube/config:file2: kubectl config view --merge --flatten > \
~/.kube/merged_kubeconfig && mv ~/.kube/merged_kubeconfig ~/.kube/config
kubectl get pods --context=cluster-1
kubectl get pods --context=cluster-2

Merging kubeconfig files

Since kubeconfig files are structured YAML files, you can’t just append them to get one big kubeconfig file, but kubectl can help you merge these files:

#
# Merging your kubeconfig file w/ $HOME/.kube/config (w/ cp backup)
#
cp $HOME/.kube/config $HOME/.kube/config.backup.$(date +%Y-%m-%d.%H:%M:%S)
KUBECONFIG=$HOME/.kube/config:file2:file3 kubectl config view --merge --flatten > \
~/.kube/merged_kubeconfig && mv ~/.kube/merged_kubeconfig ~/.kube/config
kubectl get pods --context=cluster-1
kubectl get pods --context=cluster-2

Extracting a context from a kubeconfig file

Let’s say you followed the before merging kubeconfig files and have a merged kubeconfig file in $HOME/.kube/config. Now you want to extract a cluster’s information to a portable kubeconfig file that only has the parts you need to connect to that cluster.

Run:

KUBECONFIG=$HOME/.kube/config kubectl config view \
--minify --flatten --context=context-1 > $HOME/.kube/config-context-1


#
# using --kubeconfig flag
#
kubectl get pods --kubeconfig=$HOME/.kube/config-context-1


#
# or
# using `KUBECONFIG` environment variable
#
KUBECONFIG=$HOME/.kube/config-context-1 kubectl get pods


#
# or
# keep using kubeconfig file at $HOME/.kube/config (which has the merged context)
#
kubectl get pods --context=cluster-1

In this command, we extract data about context-1 from $HOME/.kube/config to config-context-1 file. The --minify flag allows us to extract only info about that context, and the --flatten flag allows us to keep the credentials unredacted.

ref article: https://ahmet.im/blog/mastering-kubeconfig/

To dynamically merge multiple config files in you .bashrc:

export KUBECONFIG=/Users/<user>/.kube/config:/Users/<user>/.kube/other.config
source <(kubectl completion bash)

After fresh source, verify:

kubectl config view

If you use bash you can use this to simply add the configs:

function kmerge() {
DATE=$(date +"%Y%m%d%H%M")
KUBECONFIG=~/.kube/config:$1 kubectl config view --flatten > ~/.kube/mergedkub && mv ~/.kube/config ~/.kube/config-$DATE && mv ~/.kube/mergedkub ~/.kube/config
}

Then just use "kmerge $newConfigfile" to add this. Be aware the clusternames etc. should be different from existing config entries!

You can follow these instruction if you want to have some structure in your ~/.kube directory.

  1. Add the following snippet to your ~/.bashrc
  2. Add config files under ~/.kube/config.d separately.
  3. call update_kubeconfigs, or open new terminal

update_kubeconfigs just looks at ~/.kube/config.d directory and if there were any files newer than the current config file under ~/.kube/config, it updates it.

function update_kubeconfigs() {
[ ! -d "$HOME/.kube/config.d" ] && mkdir $HOME/.kube/config.d -p -v
# Will run only if there are new files in the config directory
local new_files=$(find $HOME/.kube/config.d/ -newer $HOME/.kube/config -type f | wc -l)
if [[ $new_files -ne "0" ]]; then
local current_context=$(kubectl config current-context) # Save last context
local kubeconfigfile="$HOME/.kube/config"               # New config file
cp -a $kubeconfigfile "${kubeconfigfile}_$(date +"%Y%m%d%H%M%S")"  # Backup
local kubeconfig_files="$kubeconfigfile:$(ls $HOME/.kube/config.d/* | tr '\n' ':')"
KUBECONFIG=$kubeconfig_files kubectl config view --merge --flatten > "$HOME/.kube/tmp"
mv "$HOME/.kube/tmp" $kubeconfigfile && chmod 600 $kubeconfigfile
export KUBECONFIG=$kubeconfigfile
kubectl config use-context $current_context --namespace=default
fi
}


# This will call each time you source .bashrc, remove it if you want to call it manually each time
update_kubeconfigs

Removing files form ~/.kube/confing.d will not invoke the script again. Also as @rafaelrezend pointed out, checkout for name conflicts in the config files, that might cause issues.

Github gist

Going forward, I do not recommend merging kubeconfig files using kubectl.

  • it is a manual effort as seen above (set environment variables etc.)
  • has the disadvantage that when using this context via "kubectl config use-context" it WRITES the current context to the kubeconfig file. Thus, this influences other terminal sessions that use a context from the same kubeconfig file (they all suddenly point to the same context).

Instead, I would recommend using a tool that circumvents such issues by e.g recursively search & displays all available contexts for kubeconfig files and works on a temporary copy.

Checkout kubeswitch (the tool I wrote to deal with > 1000 kubeconfig files) and this section explaining how it works.

If you look for a tool that also does namespace switching and other related things, take a look at "kubie".

As mentioned in the comment by @talarczykco on the top answer, piping back to the same ~/.kube/config will only write the second file and you will lose the original content!

Here is a safer way to first capture the full output then pipe.

Note must surround the variable kubeconfig with " otherwise you lose all newlines!

konfig=$(KUBECONFIG=~/.kube/config:new-config.yaml kubectl config view --flatten)


echo "$konfig" > ~/.kube/config

It's possible, follow the steps:

create a backup from your config file: cp ~/.kube/config-bkp

create a file with your new config file: vi ~/.kube/new-config

merge them into config: KUBECONFIG=~/.kube/config:~/.kube/new-config kubectl config view --flatten > ~/.kube/config

To see the available contexts use: kubectl config get-contexts

To change the context use: kubectl config use-context YOUR-CONTEXT-NAME

If you prefer a CLI tool I can highly recommend: KubeCM, which is also able to merge, switch, add...

kubecm add -f ./your_new_config

You would be asked either to merge into ~/.kube/config or create a .yml file in your current folder.

https://github.com/sunny0826/kubecm

I keep the yaml files for each cluster separate and then combine them with this python script:

import argparse
import yaml
parser = argparse.ArgumentParser()
parser.add_argument('files', metavar='YAMLFILES', type=argparse.FileType('r'), nargs='*')
args = parser.parse_args()


y = {'apiVersion': 'v1', 'kind': 'Config', 'clusters': [],'contexts': [],
'current-context': None, 'preferences': {}, 'users': []}
for a in args.files:
f = yaml.load(a, Loader=yaml.Loader)
y['clusters'].append(f['clusters'][0])
y['contexts'].append(f['contexts'][0])
y['users'].append(f['users'][0])
y['current-context'] = f['contexts'][0]['name']


print(yaml.dump(y, Dumper=yaml.Dumper))

Zsh users can use a =(...) process substitution to generate a temporary merged configuration file, and copy it to ~/.kube/config all in one line:

cp =(KUBECONFIG=~/.kube/config:~/.kube/config.other kubectl config view --flatten) ~/.kube/config

Going a step further, we can hold the configuration file in our system clipboard and use a nested process substitution that reads it. Just make sure that the clipboard content is the actual configuration file before pressing Enter:

cp =(KUBECONFIG=~/.kube/config:<(pbpaste) kubectl config view --flatten) ~/.kube/config

Since I have many Kubernetes conf files in the ~/.kube directory, I simply chain them tot the KUBECONFIG env variable in the ~/.zshrc file:

export KUBECONFIG=$HOME/.kube/config
for conf in ~/.kube/*.conf; do
export KUBECONFIG=$KUBECONFIG:$conf
done