読者です 読者をやめる 読者になる 読者になる

k8stail: Kubernetes の複数 Pod のログをまとめて流し読みできるツールを作った

Kubernetes の特定の namespace にある、全 Pod のログを一括で流し読みできるコマンドラインツール k8stail を作りました。

github.com

取り急ぎこちらスクリーンショットです。

f:id:dtan4:20161118221101p:plain

インストール

Mac をお使いなら Homebrew でインストールできます。

$ brew tap dtan4/dtan4
$ brew install k8stail

その他の OS 用バイナリは GitHub Releases で配布しています。

また、対応している Kubernetes のバージョンは 1.3 以上 です。

使い方

-namespace で namespace を指定すると、その namespace に所属する全ての Pod のログが tail -f の如くリアルタイムで流れます。 -namespace 指定しなかったら default namespace を使います。

1 Pod に複数のコンテナがぶら下がっている場合は、それらもまとめて表示します。 コマンド実行後に Pod が追加された / 作り直されても、それに追従して新しい Pod のログが流れます。

Ctrl-C で止まります。

$ k8stail -namespace awesome-app
Namespace: awesome-app
Labels:
----------
Pod awesome-app-web-4212725599-67vd4 has detected
Pod awesome-app-web-4212725599-6pduy has detected
Pod awesome-app-web-4212725599-lbuny has detected
Pod awesome-app-web-4212725599-mh3g1 has detected
Pod awesome-app-web-4212725599-pvjsm has detected
[awesome-app-web-4212725599-mh3g1][web]  | creating base compositions...
[awesome-app-web-4212725599-zei9h][web]  |    (47.1ms)  CREATE TABLE "schema_migrations" ("version" character varying NOT NULL)
[awesome-app-web-4212725599-zei9h][web]  |    (45.1ms)  CREATE UNIQUE INDEX  "unique_schema_migrations" ON "schema_migrations"  ("version")
[awesome-app-web-4212725599-zei9h][web]  |   ActiveRecord::SchemaMigration Load (1.8ms)  SELECT "schema_migrations".* FROM "schema_migrations"
[awesome-app-web-4212725599-zei9h][web]  | Migrating to CreatePosts (20160218082522)

-timestamps オプションをつけるとタイムスタンプがつきます。

$ k8stail -namespace awesome-app -timestamps
Namespace: awesome-app
Labels:
----------
Pod awesome-app-web-4212725599-67vd4 has detected
Pod awesome-app-web-4212725599-6pduy has detected
Pod awesome-app-web-4212725599-lbuny has detected
Pod awesome-app-web-4212725599-mh3g1 has detected
Pod awesome-app-web-4212725599-pvjsm has detected
[awesome-app-web-4212725599-mh3g1][web] 2016-11-15T10:57:22.178667425Z  | creating base compositions...
[awesome-app-web-4212725599-zei9h][web] 2016-11-15T10:57:22.309011520Z  |    (47.1ms)  CREATE TABLE "schema_migrations" ("version" character varying NOT NULL)
[awesome-app-web-4212725599-zei9h][web] 2016-11-15T10:57:22.309053601Z  |    (45.1ms)  CREATE UNIQUE INDEX  "unique_schema_migrations" ON "schema_migrations"  ("version")
[awesome-app-web-4212725599-zei9h][web] 2016-11-15T10:57:22.463700110Z  |   ActiveRecord::SchemaMigration Load (1.8ms)  SELECT "schema_migrations".* FROM "schema_migrations"
[awesome-app-web-4212725599-zei9h][web] 2016-11-15T10:57:22.463743373Z  | Migrating to CreatePosts (20160218082522)

また、-labels オプションで Pod についた Label を用いたフィルタリングができます。 下の例では、name: awesome-app-web ラベルが付いた Pod のログのみ表示しています。

$ k8stail -namespace awesome-app -labels name=awesome-app-web
Namespace: awesome-app
Labels:    name=awesome-app-web
----------
Pod awesome-app-web-4212725599-67vd4 has detected
Pod awesome-app-web-4212725599-6pduy has detected
Pod awesome-app-web-4212725599-lbuny has detected
Pod awesome-app-web-4212725599-mh3g1 has detected
Pod awesome-app-web-4212725599-pvjsm has detected
[awesome-app-web-4212725599-mh3g1][web]  | creating base compositions...
[awesome-app-web-4212725599-zei9h][web]  |    (47.1ms)  CREATE TABLE "schema_migrations" ("version" character varying NOT NULL)
[awesome-app-web-4212725599-zei9h][web]  |    (45.1ms)  CREATE UNIQUE INDEX  "unique_schema_migrations" ON "schema_migrations"  ("version")
[awesome-app-web-4212725599-zei9h][web]  |   ActiveRecord::SchemaMigration Load (1.8ms)  SELECT "schema_migrations".* FROM "schema_migrations"
[awesome-app-web-4212725599-zei9h][web]  | Migrating to CreatePosts (20160218082522)

Why

Kubernetes のコマンドラインツール kubectl には、Pod のログを見るためのコマンド kubectl logs があります。 ですが、このコマンドは一つの Pod のログしか見られないため、予め Pod の名前を把握しておく必要があります。 ReplicationController を使って動的にポコポコ Pod を作っている場合は Pod 名にランダムな Suffix がつくので、いちいち kubectl get po で確認しないといけません。 また、大抵は1サービスに対して冗長性や負荷分散の目的で複数 Pod を立てることになります。 その場合は kubectl logs を使っていると「サービス全体の」ログを一度に見ることが困難です。 Pod の数だけターミナルを開くとかになります…

Fluentd で Elasticsearch に飛ばして云々…とか Logentries などの SaaS に飛ばしてフィルタリングする方法もありますが(所属先はもともと後者で全ログを取ってる)、確か Pod 名とかそういうフィールドがなくてフィルタリングが面倒くさそうでした。 あとターミナルからサクッと確認するのが難しいですね。

あと、Deployments / ReplicationController 使ってると Pod spec の設定をミスったときに Pod 作り直しループに突入するのですが、そうなると Pod が速攻で削除されて別名の Pod が立つのでログが全然負えなくて厳しかったです。

所属先では現在積極的に Kubernetes の導入を進めていて、先日リリースしたサービスもバックエンドはマイクロサービス化されて Kubernetes 上で稼働しています。 そういうわけで「サービス全体の」ログを手元で見たい、という需要が高まってきたので今回 k8stail を作りました。

既に johanhaleby/kubetail というのはあって、これは同じ機能をシェルスクリプトで提供しています。 が、Known issues にかかれているように終了時の挙動が微妙なのと途中から Pod が追加された場合も追従できなさそうだったので今回 Go で一から作りました。

おわりに

k8stail の紹介をしました。 さくっと作ったという感じなので詰めが甘い部分ありますが、ちょくちょく改善していく所存です。

最近公式で出た Go の Kubernetes クライアントライブラリ kubernetes/client-go を使ってみたかったので、良い題材になりました。 ただ、Kubernetes でかいので仕方ないんですがビルドにかなり時間食うようになるのが厳しいですね…