kubectl plugin 機能を利用してkubectl コマンドを拡張する
最近 kubectl コマンドを拡張したいと思い、調べてみたら kubectl plugin 機構で機能拡張できることを知ったので、公式ドキュメントをベースにまとめておこうと思う。
kubectl plugin 機構とは
kubectl v1.12 以上のバージョンで使用できる、kubectl のサブコマンドを自前で実装できる plugin 機構のこと。
実行可能ファイル(シェルスクリプトやbatファイル、goで実装したバイナリなど)を PATH 上に配置し、kubectl-SUBCOMMAND
というようなファイル名にすれば、kubectl SUBCOMMAND
を実行した際に、kubectl が PATH上を検索し実行するような仕組みとなっている。
現状、v1.15 がリリースされており、機能としても stable となっているが、windwos で実行すると現状以下のエラーが返ってくる。
$ kubectl.exe version Client Version: version.Info{Major:"1", Minor:"15", GitVersion:"v1.15.0", GitCommit:"e8462b5b5dc2584fdcd18e6bcfe9f1e4d970a529", GitTreeState:"clean", BuildDate:"2019-06-19T16:40:16Z", GoVersion:"go1.12.5", Compiler:"gc", Platform:"windows/amd64"} $ cat kubectl-echo.bat echo "HELLO" $ kubectl.exe echo not supported by windows
v1.15 のバージョンにおいてはどうやら Windows 向けの実装が入っていなかったが、このプルリクエストがすでにマージされているので、次のバージョンでは利用できそう。
リンク先から入手できる v1.16 のアルファ版リリースを試してみると、実行できているのできっと大丈夫なはず。
kubernetes/CHANGELOG-1.16.md at master · kubernetes/kubernetes · GitHub
$ kubectl-1.16.exe echo "HELLO"
制約事項
kubectl に既に存在するコマンドをオーバライドすることはできないため、kubectl-version
といったコマンドを実装しても、実装したプラグインは実行されず、もともと存在するコマンドが実行される。
$ cat kubectl-version.bat echo "kubectl version" $ kubectl-1.16.exe version Client Version: version.Info{Major:"1", Minor:"16+", GitVersion:"v1.16.0-alpha.1", GitCommit:"704790e0412842e782904f1c2e7123112a9aab2c", GitTreeState:"clean", BuildDate:"2019-07-17T01:06:25Z", GoVersion:"go1.12.7", Compiler:"gc", Platform:"windows/amd64"}
なので、例えば kubectl-create-foo
みたいなコマンドを実装し、kubectl create foo
というように実行しても、自前で実装したコマンドは実行されない。
実装方法
上述の通り、スクリプトやbatファイル、実行バイナリなどを実装し、実行権限を付与し、PATH上に配置すればあとは kubectl がよしなにしてくれる。
kubectl の実装上、環境変数は kubectl 実行時の環境変数を引き継いでくれるし、パラメータもスクリプト実行時のように渡すことができる。
この編の仕組みは、上で貼ったプルリクエストのリンクを参照すると理解できるかもしれない。
時間があれば自分でもまとめておきたいと思う。
サブコマンドの検索ルール
サブコマンドの検索は最長一致で検索するようになっている。
つまり、実行コマンドが kubectl foo bar baz arg1 --flag=value arg2
だった場合には、kubectl-foo-bar-baz-arg1
という実行可能ファイルを検索し、--flag=value arg2
というパラメータは、kubectl-foo-bar-baz-arg1
にそのまま渡される。
仮に kubectl-foo-bar-baz-arg1
という実行可能ファイルが PATH 上から見つからなかった場合には、kubectl-foo-bar-baz
という実行可能ファイルを検索し、arg1 --flag=value arg2
というパラメータがサブコマンドに引き渡される。
最終的にサブコマンドが見つからない場合には、通常の kubectl コマンドのエラーが表示される。
ちなみに、すでにインストールされているプラグインを表示するには kubectl plugin list
を実行する。
自前で実装したプラグインも、PATH 上に配置されていれば表示される。
sub-command
サブコマンド名に -
を利用したい場合には、実行可能ファイル名に _
を利用する。
kubectl foo-bar
を実行する際には、ファイル名は kubectl-foo_bar
とすればよい。
また、kubectl foo_bar
を実行しても、kubectl-foo_bar
が実行される。
今のところ、これができることの良さがあまり実感できていない。
実行ファイル名被り
同一名の実行ファイルが別々の PATH 上のディレクトリに配置されている際には、常に最初に見つかったサブコマンドが実行される。
これは kubectl plugin list
を実行すれば、そのような警告が表示されるため気づくことができる。
PATHを変更すればよいが、実際にはあまり気にしたくないと思うので名前が被らないようにするのが良いかと思う。
もう少しややこしい問題として、kubectl-foo-bar
や kubectl-foo-bar-baz
といった実行ファイルが同一ディレクトリ上に配置されていた場合がある。
kubectl foo bar
の場合は kubectl-foo-bar
が
kubectl foo bar baz
の場合は kubectl-foo-bar-baz
が実行されることになる。
ややこしいので、あまり自分で実装することはなさそうな気がしている。
k8s.io/cli-runtime パッケージ
今まで見てきたように、kubectl plugin 機構を利用すれば、シェルスクリプトやbatファイルを利用してプラグインを拡張することができる。
ただ、その場合にはパラメータは単純にスクリプトに渡されるだけなので、パラメータの解析などは自前で行う必要があるし、kubectl コマンドをラップするだけになってしまう。
もう少し機能効いた拡張機能を実装したい場合には、kubectl の実装にも利用されている k8s/cli-runtime を利用して Go言語で実装すると良い。ただ、サンプルの実装がGitHubにあるとは言え、ちょっとハードルが高いなと感じてしまったので、簡単なものを作ってみたら再度まとめておきたいと思う。
参考
公式ドキュメント kubernetes.io
今年のKubeCon/CloudNativeConでkubectl plugin についての講演があったので載せておく。 www.youtube.com