仮想化通信

日本仮想化技術株式会社の公式エンジニアブログ

Kubernetes kubctlコマンドのkubeconfigの指定について

複数のKubernetesクラスターがあった時、kubeconfigを指定してコマンドを実行すると思うのですが、毎回kubeconfigを指定するのはちょっとごちゃごちゃして嫌だなあと思い、効率的な方法がないか調べることにしました。

% ku get no --kubeconfig=$HOME/.kube/kubevirt-demo2-config
% KUBECONFIG=$HOME/.kube/kubevirt-demo2-config ku get no

小ネタですが、文中のkukubectlコマンドのエイリアス(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というものがあるそうです。ディレクトリごとに環境変数を設定できて、その環境変数はそのディレクトリーに移動した時だけ有効になるというものだそうです。 

https://direnv.net/

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

ここまで書いて、次のサイトの情報を知りました。

blog.inductor.me

というわけで、このブログに書かれている「複数の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を使った方法を利用しようと思いました。

これでうっかり別のクラスターに想定していないアプリケーションを投入するという事故を減らすことができそうで、本当に良かったと思います。