kubectlのbash completionをMacで導入する

こんにちは。サービスグループの武田です。

最近社内の有志でKubernetesもくもく会が開催されています。私も結局手を出せないまま時間が過ぎてしまっていたので、強制的に触る環境を作るためにも参加しました。今回はKubernetesのCLIツールとしてkubectlを使用する際に、bash補完機能の有効化でつまずいたので紹介します。

環境

次の環境で検証しています。DockerおよびKubernetesは、Docker for Macでインストール・有効化しています。

$ sw_vers
ProductName:	Mac OS X
ProductVersion:	10.14
BuildVersion:	18A391

$ echo $BASH_VERSION
3.2.57(1)-release

$ docker --version
Docker version 18.06.0-ce, build 0ffa825

$ kubectl version
Client Version: version.Info{Major:"1", Minor:"10", GitVersion:"v1.10.3", GitCommit:"2bba0127d85d5a46ab4b778548be28623b32d0b0", GitTreeState:"clean", BuildDate:"2018-05-21T09:17:39Z", GoVersion:"go1.9.3", Compiler:"gc", Platform:"darwin/amd64"}
Server Version: version.Info{Major:"1", Minor:"10", GitVersion:"v1.10.3", GitCommit:"2bba0127d85d5a46ab4b778548be28623b32d0b0", GitTreeState:"clean", BuildDate:"2018-05-21T09:05:37Z", GoVersion:"go1.9.3", Compiler:"gc", Platform:"linux/amd64"}

$ brew --version
Homebrew 1.7.7
Homebrew/homebrew-core (git revision 9f425; last commit 2018-10-22)
Homebrew/homebrew-cask (git revision 1380c; last commit 2018-10-22)

bash-completionのインストール

kubectlの設定をする前に、bashで補完機能を使えるようにするためbash-completionをインストールします。Macの場合はHomebrewでインストールできます。使用しているbashのバージョンによって、bash-completionのバージョンも変わるので注意してください。Macのデフォルトbashのバージョンは3.2です。

3.2の場合。

$ echo $BASH_VERSION
3.2.57(1)-release

$ brew install bash-completion

$ echo '[ -f $(brew --prefix)/etc/bash_completion ] && . $(brew --prefix)/etc/bash_completion' >> ~/.bashrc

4.1以上の場合。

$ echo $BASH_VERSION
4.4.23(1)-release

$ brew install bash-completion@2

$ echo '[ -f $(brew --prefix)/share/bash-completion/bash_completion ] && . $(brew --prefix)/share/bash-completion/bash_completion' >> ~/.bashrc

今回の私の環境は3.2なので上の手順でインストールしました。.bashrcを使うか.bash_profileを使うかは人によってまちまちなので適宜読み替えてください。

失敗例(sourceコマンドでロード)

kubectlはbash/zsh用の補完スクリプトを出力するコマンドが用意されています。次のコマンドはbash用の補完スクリプトを出力しています。

$ kubectl completion bash | head

# Copyright 2016 The Kubernetes Authors.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
#     http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software

そして、.bashrc(あるいは.bash_profile)に次のように追記するとあえなく失敗します。

echo "source <(kubectl completion bash)" >> ~/.bashrc

そもそも追記しているコマンドの意味はなんでしょうか。sourceコマンドは引数にファイル名を取り、それを現在のコンテキストで実行します。kubectl completion bashは補完スクリプトを標準出力に出力します。<()はプロセス置換という機能で、ファイル名が必要な箇所にコマンドが書けます *1

まとめると、kubectlの補完スクリプトを現在のコンテキストで実行するわけです。

最初調べた時この方法が出てきたのでやってみましたがダメでした。sourceコマンドとプロセス置換の組み合わせは動作しないようです。

成功例(bash-completion.dに配置)

さらに調べると上記のsourceコマンドの方法はLinuxの場合らしいことがわかりました。Macの場合はbash-completion.dにスクリプトを配置しておくとbash_completionによって自動的にロードされます。

というわけで、次のコマンドを実行しbashを再起動するとうまく動作しました。

$ kubectl completion bash > $(brew --prefix)/etc/bash_completion.d/kubectl

まとめ

参考サイトに挙げましたが、ちゃんと公式ドキュメントに記載されてました。公式ドキュメントちゃんと読もう。

参考サイト

脚注

  1. 内部的にはファイルディスクリプターに接続された状態でコマンドが実行され、括弧内のコマンドの結果がそこに出力される。tmpファイルをわざわざ作らないで済むので便利