Reputation: 1888
Is there a simple kubectl
command to take a kubeconfig
file (that contains a cluster+context+user) and merge it into the ~/.kube/config file as an additional context?
Upvotes: 118
Views: 68318
Reputation: 1942
Here is my improvement based on the answer of @joost-döbken
Add this to your ~/.bashrc
Original answer: https://stackoverflow.com/a/71681738/5243543
# Kubernetes config merge
unset KUBECONFIG
for conf in ~/.kube/config*; do
# -z means is empty
if [ -z "$KUBECONFIG" ]; then
export KUBECONFIG=$conf
continue
fi
export KUBECONFIG=$KUBECONFIG:$conf
done
Upvotes: 1
Reputation: 159
I've modified the script provided by rzjfr to work on Mac zsh:
update_kubeconfigs() {
### Update kubeconfig file based on the individual files on the $config_dir
local config_dir="${1:-$HOME/.kube/config.d}"
local backup_files_to_keep="${2:-10}"
local config_file="$HOME/.kube/config"
local newer_files current_context kubeconfig_files
###
if [[ ! -d "$config_dir" ]]; then mkdir -p -v "$config_dir"; fi
if [[ -f "$config_file" ]]; then
newer_files=$(find "$config_dir" -newer "$config_file" -type f)
else
newer_files=$(find "$config_dir" -type f)
fi
# Only if there were files newer than the existing config_file
if [[ -n "$newer_files" ]]; then
current_context=$(kubectl config current-context) # Save last context
# Backup existing config file and remove old backups
cp -a "$config_file" "${config_file}_$(date +"%Y-%m-%d-%H%M%S")"
find "${config_file%/*}" -maxdepth 1 -name "config_*" -type f -exec sh -c 'echo "$1"' _ {} \; | sort -n | tail -n "+$backup_files_to_keep" | xargs rm -f
# Remove contexts if they have changed to force updates
# Split the string into an array using parameter expansion
newer_files=("${(@f)newer_files}")
for file in "${newer_files[@]}"; do
echo "Checking if context exists for $file"
context_name=$(kubectl config get-contexts --kubeconfig "$file" --no-headers | awk '{print $2}')
context_cluster=$(kubectl config get-contexts --kubeconfig "$file" --no-headers | awk '{print $3}')
context_user=$(kubectl config get-contexts --kubeconfig "$file" --no-headers | awk '{print $4}')
if kubectl config get-contexts | grep -q "$context_name"; then
kubectl config delete-context "$context_name"
kubectl config unset "contexts.$context_name"
kubectl config unset "clusters.$context_cluster"
kubectl config unset "users.$context_user"
fi
done
# Create a new config file
kubeconfig_files="$config_file:$(find "$HOME/.kube/config.d/" -type f -print | tr '\n' ':')"
KUBECONFIG="$kubeconfig_files" kubectl config view --merge --flatten > "$HOME/.kube/tmp"
# install -m 600 "$HOME/.kube/tmp" $config_file
mv "$HOME/.kube/tmp" "$config_file" && chmod 600 "$config_file"
export KUBECONFIG=$config_file
kubectl config use-context "$current_context" --namespace=default
fi
}
# Merge kubeconfig
update_kubeconfigs "$HOME/.kube/config.d" 10 # keep 10 most recent backup
Upvotes: 0
Reputation: 61
You can follow these instruction if you want to have some structure in your ~/.kube
directory.
~/.bashrc
~/.kube/config.d
separately.update_kubeconfigs
, or open new terminalupdate_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 includes a fix for updating credentials
Upvotes: 4
Reputation: 21
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
Upvotes: 2
Reputation: 4075
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
Upvotes: 5
Reputation: 2993
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))
Upvotes: 0
Reputation: 16214
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
Upvotes: 1
Reputation: 61
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
Upvotes: 6
Reputation: 18460
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
Upvotes: 1
Reputation: 185
Going forward, I do not recommend merging kubeconfig files using kubectl.
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".
Upvotes: 1
Reputation: 2462
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
Upvotes: 57
Reputation: 7958
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!
Upvotes: 1
Reputation: 1488
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
Upvotes: 0
Reputation: 13321
Do this:
export KUBECONFIG=~/.kube/config:~/someotherconfig
kubectl config view --flatten
You can then pipe that out to a new file if needed.
Upvotes: 188
Reputation: 5868
kubeconfigs
at onceSometimes 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
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
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/
Upvotes: 37
Reputation: 5896
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
Upvotes: 15