kubectl のプラグイン機能 kubectl plugin を使おう！

## はじめに

一度は実装されながらもその後大きくメカニズムが変わるといったこともありましたが、v1.12 で実行された新しい kubectl[^2] のプラグイン機構がめでたく v1.13 でベータに昇格しました :tada: Kubernetes API におけるベータレベルの扱いは、「今後互換性のない変更があるかもしれないけど、マイグレーションパスを用意する[^0]」ですが、このような機能に関するベータはどういう扱いなんでしょうね。十分に使われてきたといったところでしょうか。

ここでは、そんなベータになった kubectl plugin のつくりかたを紹介します。

:warning: この記事で登場するプラグイン機能は kubectl バージョン **v1.12** 以上で利用できます。注意してください。

## kubectl のプラグイン機能、kubectl plugin とは

kubectl plugin は、kubectl に任意のサブコマンドを追加する機能です。Kubernetes は拡張性を重視していて、その一環として kubectl の拡張機能として提供されています。v1.13 でベータに昇格し、特に問題なければ v1.14 で GA となるでしょう。

## kubectl plugin の仕組みとつくりかた

v1.12 から導入された新しい kubectl plugin のプラグイン機構は一般的に git-style プラグイン機構と呼ばれています。このプラグイン機構は、`PATH` の通ったディレクトリに配置された実行ファイルの名前が特定のプレフィックスで開始しているものを呼び出すというもので、kubectl plugin の場合はプレフィックスが `kubectl-` です。例えば `kubectl-foo` という実行ファイルを作成し、`PATH` の通ったディレクトリに配置すると、`kubectl foo` コマンドとして実行できます。

```
$ echo '#!/bin/bash\n\necho "foo"' > /usr/local/bin/kubectl-foo
$ chmod +x /usr/local/bin/kubectl-foo
$ /usr/local/bin/kubectl-foo
foo
$ kubectl foo
foo
```

もしうまくいかないときは kubectl コマンドのバージョンが 1.12 以上であることを確認してください。

見ていただいて分かるようにただ実行ファイルが呼び出されるだけで他に何もありません。そのため引数の処理なども基本的に作り込む必要があります。さきほどの `kubectl foo` コマンドを指定された第一引数を出力するように変更してみます。

```
$ echo '#!/bin/bash\n\necho "My first command-line argument was $1"' > /usr/local/bin/kubectl-foo
$ kubectl foo tako
My first command-line argument was tako
```

その他、プラグインのサブコマンドは、実行ファイル名にハイフン区切りで指定します。例えば `kubectl foo bar` コマンドを作成したい場合は、`kubectl-foo-bar` という実行ファイル名です。では、`kubectl foo-bar` コマンドを作成したい場合はどうするかというと、`kubectl-foo_bar` コマンドのようにアンダースコア区切りになります。

最後に、利用できるプラグインの一覧は `kubectl plugin list` コマンドで確認できます。もしインストールしているプラグインの実行ファイルに実行権限がついていないなどの問題がある場合もこのコマンドが警告を出力してくれるので、うまく動かないときもこのコマンドを利用しましょう。

```
$ kubectl plugin list
The following kubectl-compatible plugins are available:

/usr/local/bin/kubectl-foo
```

より詳しく情報は公式ドキュメントを参照してください。

- [Extend kubectl with plugins \- Kubernetes](https://kubernetes.io/docs/tasks/extend-kubectl/kubectl-plugins/)

## kubectl way なプラグインをつくるには

ここまでで新しくなった kubectl plugin のプラグイン機構について紹介しました。とてもシンプルですぐにでも利用できそうですが、引数の処理は全て自力で実装が必要で何の手助けもありません。そのため、`--namespace` や `--context` などの kubectl コマンドのグローバルオプションを使った kubectl way なプラグインを実装したいとすると非常に大変です。[^1] そこで、kubectl コマンドを主幹する SIG-CLI は、Go 言語で kubectl way なプラグインを実装するためのライブラリ `k8s.io/cli-runtime` を提供しています。

- [kubernetes/cli\-runtime: Set of helpers for creating kubectl commands and plugins\.](https://github.com/kubernetes/cli-runtime)

このライブラリは、kubectl コマンドのグローバルオプションや `--file` (`-f`) オプションといった kubectl コマンドで多用されているオプションを自分のプラグインで利用できます。またこのライブラリは、プラグイン向けでもあるのですが kubectl 自体の実装にも使われています。そのため、今後 kubectl コマンドにコントリビュートしたいという方もこのライブラリの使い方を知っておくと便利です。詳しい使い方は、このライブラリを利用したサンプルプラグインのリポジトリである `kubernetes/sample-cli-plugin` リポジトリを参照してください。

- [kubernetes/sample\-cli\-plugin: Sample kubectl plugin](https://github.com/kubernetes/sample-cli-plugin)

## kubectl plugin マネージャ Krew を使おう

ここまでは作り方を説明してきましたが、プラグインが作れるとなると他の人が作った便利プラグインが利用したいところです。それには kubectl plugin マネージャである Krew を利用しましょう。

- [GoogleContainerTools/krew: 📦 The package manager for "kubectl plugins"](https://github.com/GoogleContainerTools/krew)

Krew は、kubectl plugin のプラグインマネージャで、インデックスに登録された kubectl plugin をインストール、管理できます。これ自体も kubectl plugin として実装されています。

Krew の使い方はとても簡単で、次のようなコマンドが用意されています。お気に入りのプラグインを探してみましょう。

```
kubectl krew search               # 全てのプラグインを表示する
kubectl krew install view-secret  # "view-secret" プラグインをインストール
kubectl view-secret               # プラグインの利用
kubectl krew upgrade                   # インストールされたプラグインのアップグレード
kubectl krew remove view-secret        # プラグインのアンインストール
```

Krew は次のコマンドでインストールできます。

```
(
  set -x; cd "$(mktemp -d)" &&
  curl -fsSLO "https://storage.googleapis.com/krew/v0.2.1/krew.{tar.gz,yaml}" &&
  tar zxvf krew.tar.gz &&
  ./krew-"$(uname | tr '[:upper:]' '[:lower:]')_amd64" install \
    --manifest=krew.yaml --archive=krew.tar.gz
)
```

インストール後に、プラグインがインストールされるディレクトリを `PATH` に追加してください。

```
export PATH="${KREW_ROOT:-$HOME/.krew}/bin:$PATH"
```

## Krew でインストールできるおすすめプラグイン

ここでは Krew でインストールできるおすすめ(私が作成した)プラグインを2つ紹介します。

### `kubectl open-svc` プラグイン

1つ目は、`kubectl open-svc` プラグインです。これは、クラスタ外からアクセスできない ClusterIP タイプの Service にクラスタの外から簡単にアクセスするためのプラグインです。例えば、`nginx` Service にアクセスするには次のように実行します。

```
$ kubectl open-svc nginx
```

`kubectl port-forward` コマンドと異なり、ちゃんと Serivice を通じてアクセスできるのでアクセスが分散されることも確認できます。動きは次の GIF 動画を確認してください。

![Screenshot](https://qiita-image-store.s3.amazonaws.com/0/3780/adf41873-aa32-7f4d-c566-97897b92622f.gif)

インストールは、Krew から行えます。

```
$ kubectl krew install open-svc
```

- [superbrothers/kubectl\-open\-svc\-plugin: A kubectl plugin that open the Kubernetes URL\(s\) for the specified service in your browser\.](https://github.com/superbrothers/kubectl-open-svc-plugin)

### `kubectl view-serviceaccount-kubeconfig` プラグイン

2つ目は、`kubectl view-serviceaccount-kubeconfig` プラグインです。ServiceAccount としてクラスタ外からアクセスするための kubeconfig を標準出力に出力します。例えば、`default` ServiceAccount の kubeconfig を得たければ次のように実行します。

```
$ kubectl view-serviceaccount-kubeconfig default > ./kubeconfig
$ kubectl --kubeconfig=./kubeconfig get po
```

CD として ServiceAccount を使ってデプロイしたいときなどに便利です。このプラグインも Krew でインストールできます。

```
$ kubectl krew install view-serviceaccount-kubeconfig
```

- [superbrothers/kubectl\-view\-serviceaccount\-kubeconfig\-plugin: A kubectl plugin that show a kubeconfig to access the apiserver with a specified serviceaccount\.](https://github.com/superbrothers/kubectl-view-serviceaccount-kubeconfig-plugin)

## その他のプラグイン

その他に Krew に登録されていないプラグインも多く存在します。その多くは、GitHub トピック `kubectl-plugins` がリポジトリに設定されているので、ここからお気に入りを探してみましょう。

- [Topic: kubectl\-plugins](https://github.com/topics/kubectl-plugins)

## まとめ

ここでは、v1.13 でベータに昇格した kubectl plugin の作り方について紹介しました。この git-style のプラグイン機構はシンプルで利用しやすいとは思います。しかし個人の好みを言えば、以前の廃止されたプラグイン機構の方がシェルスクリプトでも簡単に kubectl way なプラグインの開発できて好きでした。もしなんの役にも立たないロストテクノロジを知りたい変わり者がいれば、 [プラグインで kubectl を拡張する \- Speaker Deck](https://speakerdeck.com/superbrothers/extend-kubectl-with-plugins) を参照して知識欲を満たしてください。

[^0]: https://kubernetes.io/docs/concepts/overview/kubernetes-api/#api-versioning
[^1]: ロストテクノロジーとなった以前のプラグイン機構では、シェルスクリプトで実装した場合でも kubectl コマンドのグローバルオプションの利用が簡単でした。
[^2]: キューブコントロール派閥に属しています