こんにちは、@ueokandeです。 この記事はKubernetes Advent Calendar 2021の 8 日目の記事です。
Pod 内のアプリケーションをトラブルシュートするとき皆さんどうしていますか? 本日は Kubernetes Pod 内にあるディレクトリを、ローカルファイルシステムにマウントする kubectl プラグインを作ったお話をします。
kubectl-mount プラグイン
Pod 内のアプリケーションをトラブルシュートするとき皆さんどうしていますか?
設定ファイルを参照したりログを閲覧したいときは、 kubectl exec で Pod 内のシェルを立ち上げることがありますよね。
しかし Kubernetes Pod にはエディタやページャーなどの高級なツールはないので、 cat や tail などでファイルの中身を見ることになるかと思います。
kubectl-mount は Pod のファイルシステムをローカルディレクトリにマウントする kubectl プラグインです。
sshfsのように、Pod 内のディレクトリやファイルを、あたかもローカルのコマンドからアクセスできます。 たとえばログファイルを閲覧するためにページャーを使ったり、設定ファイルをエディタで開いてシンタックスハイライトを有効にして閲覧できます。
プラグインは go install でインストールできます。
$ go install github.com/ueokande/kubectl-mount@latest使い方
プラグインのインストール後は、 kubectl mount サブコマンドでマウントできるようになります。
たとえば nginx Pod のログディレクトリをマウントするには以下のように実行します。
$ mkdir -p /tmp/nginx-logs
$ kubectl mount nginx:/var/log /tmp/nginx-logs/tmp/nginx-logs 以下に Pod 内の /var/log 以下がマウントされます。
NGINX のアクセスログは以下のコマンドから閲覧できます。
$ less /tmp/nginx-logs/nginx/access.logしくみ
kubectl-mount は、FUSE (Filesystem in Userspace) という Linux カーネルの機能を使っています。
FUSE はファイルシステムのインターフェイスであり、このインターフェイスを実装するプログラムを記述することでファイルシステムを実装できます。
物理デバイスやネットワークストレージはもちろんのこと、プログラムを書いて任意のファイルシステムを実装できるので、リモートホストのファイルシステムや、/proc のような論理的なファイルシステムも実装できます。
sshfs も FUSE の機能を使った実装の 1 つです。
go-fuseは Go で FUSE の実装ができるライブラリで、 kubectl-mount もこのライブラリを使っています。
また go-fuse は macOS 上で FUSE の機能を使える OSXFUSE もサポートしています。
kubectl-mount は Pod 内のファイルを取得、閲覧するために、Kubernetes exec API を実行します。
ファイル一覧を取得するときには、Pod 上で ls コマンドを実行して、その出力結果が FUSE に返します。
同じようにファイル作成日や更新日などの情報を得るには、 Pod 内で stat コマンドを実行して、その出力結果をパースして FUSE に返します。
制約
Read-only ファイルシステム
Pod 上のファイルの作成や更新はできません。
Kubernetes exec API と FUSE 経由でファイルの更新もできそうですが、安全な書き込み方法が確立できてないので現在はまだ未サポートです。
Pod 内のファイルを保護するために、 kubectl-mount は Read-only ファイルシステムとしてマウントされます。
Linux ディストリビューションの要件
kubectl mount は Pod 内で以下のコマンドを実行します。
findまたはlsstatcat
つまり scratch コンテナなどこれらのユーティリティがない Pod 内のフィルシステムはマウントできません。
