etcdからkubernetesの動きを見る「kube-ectd-helper」

f:id:febc_yamamoto:20180325223207p:plain

多分すごく限られた層にだけ響くツール「kube-etcd-helper」を作りました。

kube-etcd-helperは、kube-apiserverが利用しているetcdに直接アクセスし、 データのダンプや変更の検知を行うためのツールです。

kubernetesの全体のデータの動きを知りたい方や、kubernetesを開発プラットフォームとして利用するインフラエンジニアの方などは便利にお使いいただけると思います。

kube-etcd-helper

Kubernetesオブジェクトの中身を見るには

Kubernetesオブジェクトとは、Kubernetesのクラスタの状態を表す永続化されるエンティティのことです。
podとかserviceとかdeploymentなどですね。

Understanding Kubernetes Objects

これらは通常kube-apiserverによって公開されるAPIを通じて操作します。
kube-apiserverの背後ではetcdが動いており、エンティティの永続化に使われています。

手っ取り早くKubernetesオブジェクトの中身を確認するにはkubectl getコマンドを利用するのが楽です。
例えばpodオブジェクトの中身を見るには以下のようなコマンドを実行します。

$ kubectl get pod <pod名>
NAME                           READY     STATUS    RESTARTS   AGE
hello-world-55c844bc5b-544h6   1/1       Running   0          3d

より詳細に見るには-o yaml-o jsonといったオプションをつければOKです。
よく使うコマンドですので馴染みのある方も多いですよね。

さらに、--watchというオプションをつけることで、指定オブジェクトの変更を追い続けることも可能です。

# --watchオプションをつけると、オブジェクトの変更を検知できる
$ kubectl get pod <pod名> --watch
NAME                           READY     STATUS    RESTARTS   AGE
hello-world-55c844bc5b-544h6   1/1       Running   0          3d

また、kube-apiserverが提供するREST APIを直接利用する方法でもオブジェクトの内容を確認できます。

# kubectl proxyを併用する場合
$ kube proxy --port=8080 &
$ curl http://localhost:8080/api/v1/namespaces/<ネームスペース>/pods/<pod名> 
{
  "kind": "Pod",
  "apiVersion": "v1",
  "metadata": {
    "name": "<pod名>",

   # 以下略
  }
}

これらの方法以外にも、etcdctlなどのetcdクライアントツールで直接データの中身を覗く方法も取れそうなのですがこの方法には問題があります。
というのも、kubernetes 1.6以降はetcd v3がデフォルトとなりバイナリーフォーマット(protobuf)でシリアライズされたデータが格納されているため、
コマンドラインから覗いても(一部を除き)読めないデータとなっているからです。

ということで多くのケースではkubectlまたはREST APIを利用することになると思います。

問題となるケース

通常はkubectlまたはREST APIを利用すれば事足りると思いますが、いくつか面倒なケースというのもあります。

  • kubectl runなどの複数のオブジェクトにまたがる操作を追いたい場合
  • オブジェクトの変更履歴を比較し、どこが変わったのか確認したい場合

例えばkubectl runを実行すると、Deployment/ReplicaSet/Podが作成されます。 これらの動きを追いたい場合--watchオプションを利用することになるのですが、 現在はkubectl get allに対しての--watchオプションは残念ながらサポートされていないためそれぞれに対し個別にkubectl get --watchしないといけません。

また、--watchで変更履歴を追えますが、変更されるごとに個別のファイルに出力といったことはできないためどこが変わったのか比較するのがなかなかに面倒な作業です。

これらの問題を解決するためにkube-etcd-helperを作りました。

kube-etcd-helperは何をするの?

kube-etcd-helperは、kube-apiserverが利用しているetcdに直接アクセスしデータのダンプや変更の検知を行うためのツールです。
前述の通りkubectlREST APIからではネームスペース/オブジェクトを跨いだ全オブジェクトを追うのはなかなか手間ですが、kube-etcd-helperを利用すれば簡単にできちゃいます。

kube-etcd-helperのインストール

kube-etcd-helperはGoで書いているため、インストールは実行ファイルをダウンロードして実行権を付与するだけでOKです。
以下のGitHubリリースページからダウンロードしてください。

kube-etcd-helper ダウンロード

あとはetcdに接続できる環境で実行するだけです。
master上で直接kube-etcd-helperを実行できる場合は問題ないですが、Docker for Macなどの直接etcdと通信できない環境の場合は 事前に以下のようにポートフォワードしておきます。

kubectl port-forward etcd-docker-for-desktop 2379:2379 --namespace=kube-system

なおデフォルトではlocalhost:2379に対して通信しようとしますがオプションで変更も可能です。 同じく証明書の指定などもオプション指定可能です。

kube-etcd-helperの使い方

ダンプ

etcd内でのキー階層をそのままディレクトリ/ファイルにダンプが可能です。

# etcdのデータをoutディレクトリにダンプ
$ kube-etcd-helper dump -o out/ --pretty

f:id:febc_yamamoto:20180325221247p:plain

変更の追跡(watch)

kubectl--watchオプションと同じく、変更を検知するためのwatchサブコマンドを用意しています。
これを利用すれば、全ネームスペースの全オブジェクトの動きを追うことが可能です。

# etcdのデータの変更を検知して標準出力に書き出し
$ kube-etcd-helper watch --pretty

watchサブコマンドはディレクトリ/ファイルへの出力に対応しているため、diffコマンドなどを併用することでどこが変わったのかを追うことも容易です。

# ディレクトリ/ファイルへの出力
$ kube-etcd-helper watch -o out/ --pretty

f:id:febc_yamamoto:20180325221252p:plain

この例はkubectl runhello-worldというdeploymentを作成した時の動きをwatchサブコマンドで記録したところです。
deployment/replicaset/podそれぞれの配下にJSON形式で変更内容を保存しています。
diffコマンドなどを併用するとオブジェクトのどの値が変更されたのか確認できます。

f:id:febc_yamamoto:20180325221256p:plain

この図はPodの作成〜schedulerがスケジューリングする部分ですね。Podのステータスがどう変わったのか一目瞭然です。

また、ファイル名はetcdのリビジョン番号を利用していますので、ファイル名順に並べればkubernetesがどの順番でetcdに対して操作を行なっているのか追うことも可能ですね。

その他のコマンド

その他にはlistgetサブコマンドがあります。 listはetcdのキーのみを一覧表示します。getは指定キーの内容を表示してくれます。

他にもいくつかオプションがありますので、詳細は--helpを参照してください。

終わりに

ということでkube-etcd-helperの紹介でした。 カスタムのコントローラーを書く方やkubernetesの内部構造をもっと知りたいという方には便利だと思いますのでぜひご利用ください!!

以上です。