複数のKubernetesクラスターがあった時、kubeconfigを指定してコマンドを実行すると思うのですが、毎回kubeconfigを指定するのはちょっとごちゃごちゃして嫌だなあと思い、効率的な方法がないか調べることにしました。
% ku get no --kubeconfig=$HOME/.kube/kubevirt-demo2-config % KUBECONFIG=$HOME/.kube/kubevirt-demo2-config ku get no
小ネタですが、文中のku
はkubectl
コマンドのエイリアス(alias ku="kubectl")です。
先日「alias k="kubectl"でも設定するか」と言ったところ、1文字エイリアスは危険という声があったので、最近はku
にしてます。
以降、ku
を多用していますので置き換えて実行してください。
また、今回はkubectl v1.21.0
を使った検証になっています。
kubeconfigを切り替える
まずは誰でも思いつく、環境変数に登録する方法を試してみます。 kubeconfigをexportして変数として設定します。
% export KUBECONFIG=$HOME/.kube/kubevirt-demo2-config
printenvでパスを確認します。
% printenv
kubeconfigオプション不要でコマンドを実行し、想定した結果が返ってくるようになりました。
% ku get no NAME STATUS ROLES AGE VERSION kubevirt-demo2 Ready control-plane,master 15d v1.21.0
今度は別のkubeconfigファイルをexportして変数を上書きします。
% export KUBECONFIG=$HOME/.kube/config
printenvでパスが上書きされたことを確認します。
% printenv
実行するとminikubeの結果が出力されました。環境変数が想定通り使えているようです。
% ku get no NAME STATUS ROLES AGE VERSION minikube Ready control-plane,master 4m22s v1.20.2
kubeconfigを切り替える(direnvを利用)
環境変数を指定してkubecotlコマンドを実行するやり方は一見うまく動きますが、思わぬ事故を誘発します。 例えば先のように変数として登録し
% export KUBECONFIG=$HOME/.kube/kubevirt-demo2-config
ターミナルの別タブを開いて何かのアプリケーションをデプロイしたとしましょう。
そうすると他のタブではKUBECONFIGが空の状態になるため、デフォルトの $HOME/.kube/config
が参照されてしまいます。
これを解決する方法として、direnvというものがあるそうです。ディレクトリごとに環境変数を設定できて、その環境変数はそのディレクトリーに移動した時だけ有効になるというものだそうです。
macOSならHomebrewなどでインストールできるんだとか。
% brew install direnv
というわけで、ディレクトリーやファイル名をちょっと変えて次のような感じに設定してみました。
~/.kube/kubevirt-demo2-config ↓ ~/.kube/kubevirt-demo2/config
私のmacOSはzshシェルがデフォルトなので、~/.zshrc
の最終行に次のように追記しました。
eval "$(direnv hook zsh)"
~/.kube/kubevirt-demo2/
ディレクトリーに移動したら、KUBECONFIG=$HOME/.kube/kubevirt-demo2/config
が自動的に設定されるようにしてみます。
% cd ~/.kube/kubevirt-demo2/ % echo export KUBECONFIG=$HOME/.kube/kubevirt-demo2/config > .envrc % direnv allow . direnv: loading ~/.kube/kubevirt-demo2/.envrc direnv: export +KUBECONFIG % ku get no NAME STATUS ROLES AGE VERSION kubevirt-demo2 Ready control-plane,master 16d v1.21.0
ノードの情報が返ってきたので想定通り動きました。 間違いない、direnvを使った方が良いです。
ディレクトリーを抜けると環境変数はunloadされます。当然ながらKUBECONFIGに設定した環境変数はリセットされます。
% cd .. direnv: unloading % echo $KUBECONFIG
ここまで書いて、次のサイトの情報を知りました。
というわけで、このブログに書かれている「複数のkubeconfigファイルをマージ」をやってみたいと思います。
複数のkubeconfigファイルをマージする
KUBECONFIGに複数のkubeconfigを指定して、「kubectl config view --merge」する。
これで複数指定したkubeconfigが$HOME/.kube/out.txt
にマージされます。
% KUBECONFIG=$HOME/.kube/config:$HOME/.kube/kubevirt-demo2-config kubectl config view --merge --flatten > $HOME/.kube/out.txt
マージしたkubeconfigファイルを使う
統合したkubeconfigをデフォルトにしてみます。
% export KUBECONFIG=$HOME/.kube/out.txt
デフォルトは$HOME/.kube/config
側に書かれていた方(minikube)が表示されました。
% kubectl get no NAME STATUS ROLES AGE VERSION minikube Ready control-plane,master 10m v1.20.2
コンテキストとして「kubernetes-admin@kubernetes」(kubeadmでセットアップしたクラスタ側)を指定すると次のように返ってきました。
% kubectl get no --context=kubernetes-admin@kubernetes NAME STATUS ROLES AGE VERSION kubevirt-demo2 Ready control-plane,master 15d v1.21.0
コンテキストとして「minikube」(minikubeでセットアップしたクラスタ側)を指定すると次のように返ってきました。
% kubectl get no --context=minikube NAME STATUS ROLES AGE VERSION minikube Ready control-plane,master 11m v1.20.2
いらない変数はリセットしておきます。
% unset KUBECONFIG
まとめ
kubectl
コマンドツールのkubeconfigの指定について、今回真面目に調べて良かったと思いました。その副産物でdirenvというものを見つけられたし。
複数のkubeconfigをマージして使う方法も想定通り動きましたが、私の場合はクラスターごとにディレクトリーを切ってdirenvを使う方法を選択しようと思います。その理由としては、私はminikubeもたまに使うのですが、minikubeはクラスターを構築すると~/.kube/config
にkubeconfigを書き込みます。minikube delete
すると~/.kube/config
の内容をクリアします。しかし、export KUBECONFIG
を実行してしまうとそのファイルのkubeconfigのみ処理されて~/.kube/config
の情報は残ったままになってしまいます。「これはあまり良くないな」ということで、direnvを使った方法を利用しようと思いました。
これでうっかり別のクラスターに想定していないアプリケーションを投入するという事故を減らすことができそうで、本当に良かったと思います。