🔍

Kubernetes History Inspector(KHI)でたわむれる

2025/02/03に公開

Google Cloud Japan のRyuSAです💪

Kubernetes は大変便利です。多くのコンテナを論理的にまとめてデプロイしたりノードのオートスケールのエコシステムが充実していたり、昨今のクラウドネイティブな環境においてなくてはならない存在です。

しかし便利である一方その挙動は複雑です。Pod をデプロイするだけでも内部的には kube-scheduler や kubelet、containerd など複数のプロセスが関与し、トラブルシューティングするためには様々なログやステータスを確認しなくてはいけません。

Kubernetes History Inspector は Google Cloud リポジトリで公開されたOSS で、Kubernetes の監査ログなどを元に特定の時間枠で Kubernetes 内で起きていたイベントをタイムライン化、オブジェクトのヒストリーをGUIで眺めることができる Agentless なツールです。
本記事では KHI を使って GKE の中で起きていたイベントをトレースし、Kubernetes がどのように動いているのかをビジュアルで見れるようにしてみます。

https://github.com/GoogleCloudPlatform/khi

Pod の一生

さて、まず Kubernetes に Pod が作成されるとどうなるでしょうか?

kubectl run --image nginx nginx

ざっくり、このような流れで Pod が作成されてコンテナが起動します。

  1. kube-scheduler が Pod に適切な Node を割り当てる
  2. その Node 上の kubelet が containerd に Pod の作成をリクエスト
  3. containerd がサンドボックスを作成
  4. containerd がコンテナイメージを Pull
  5. containerd がコンテナを起動する

タイムラインにするとこのような感じでしょう。

Pod を削除するとどうなるでしょう?

kubectl delete pod nginx
  1. kubelet が Pod の削除を認識してcontainerdに StopContainer を実行します
  2. containerd がコンテナのプロセスに SIGTERM を実行します
  3. containerd がコンテナが停止したことを確認します
  4. kubelet が ContainerDied のイベントを発行します
  5. Pod が Kubernetes から削除されます

タイムラインにするとこのような感じでしょう。

ここまでの流れを図解すると、このようなタイムラインが出来上がりますね。

KHI は"リソースタイムライン"を作成します。各リソースに関連するイベントをポイント、さらにリソースの時系列ごとのステータスに色付けをして次のようなタイムラインを作成します。

KHI はクラスタレベルで多くのリソースに対してタイムラインを自動生成し、WebUI で見れるようにしてくれます。

……便利ではありませんか??

Deployment の一生を眺める

KHI は Kubernetes の過去のイベントを読み取ってタイムラインを作成します。今回は Getting Started に沿って次のストーリーを辿ることにします。

  1. Deployment を作成する
  2. Deployment をスケールアウトする
  3. Deployment をロールアウトする
  4. Deployment をロールバックする
  5. Deployment を削除する

事前準備

チュートリアルを進めるために、次のコマンドがインストールされていることを確認してください。

  • kubectl
  • Docker or podman
  • gcloud

また利用可能な GKE クラスタを用意しておいてください。

GKE クラスタを作成する

Deployment を動かすための GKE クラスタがない場合、まず GKE クラスタを作成しましょう。

gcloud container clusters create --location asia-northeast1 khi-tutorial

作成には15分ほどかかります。作成完了後、GKE クラスタの認証情報を kubectl を設定しておきましょう。

gcloud container clusters get-credentials --location asia-northeast1 khi-tutorial

まず GKE クラスタに Deployment を作成します。その後、レプリケーション数を増やしてスケールアウトします。

# 開始する時間を計測しておきます
$ TZ=Asia/Tokyo date --iso-8601=minutes
2025-01-29T21:50+09:00

# Deploymentを作成し、完了まで待機する
$ kubectl create deployment --image nginx --replicas 3 nginx
deployment.apps/nginx created

$ kubectl rollout status deployment nginx
deployment "nginx" successfully rolled out

# DeploymentのPodの数を8個に増やす
$ kubectl scale deployment nginx --replicas 8
deployment.apps/nginx scaled

$ kubectl rollout status deployment nginx
deployment "nginx" successfully rolled out

さらに Deployment をロールアウトし、完了後に Deployment を削除します。

# Deploymentをロールアウトします
# 今回はrestartで代用します
$ kubectl rollout restart deployment nginx
deployment.apps/nginx restarted

$ kubectl rollout status deployment nginx
deployment "nginx" successfully rolled out

# ロールバックします
$ kubectl rollout undo deployment nginx
deployment.apps/nginx rolled back

$ kubectl rollout status deployment nginx
deployment "nginx" successfully rolled out

# Deploymentを削除します
$ kubectl delete deployment nginx

# 終了時刻を記録しておきます
$ TZ=Asia/Tokyo date --iso-8601=minutes
2025-01-29T22:00+09:00

これで準備が整いました。KHI を起動して Kubernetes の中で何が起きていたのかを確認しましょう。

GKE クラスタを削除する

KHI は動いている GKE クラスタに依存せず動かすことができます。GKE クラスタをこれ以上使わない場合は削除できます。

gcloud container clusters delete --location asia-northeast1 khi-tutorial

KHI でクラスタを調査する

KHI はコンテナで提供されているので次のコマンドを使って KHI を起動できます。起動すると 8080番ポートから KHI の WebUI にアクセスできるようになります。

$ docker run -p 127.0.0.1:8080:8080 asia.gcr.io/kubernetes-history-inspector/release:latest -access-token=`gcloud auth print-access-token`

global > INFO Initializing Kubernetes History Inspector...
global > INFO Starting Kubernetes History Inspector server...
 Starting KHI server with listening 0.0.0.0:8080
For Cloud Shell users:
        Click this address >> http://localhost:8080 << Click this address

(For users of the other environments: Access http://localhost:8080 with your browser. Consider SSH port-forwarding when you run KHI over SSH.)

まずは “New Inspection” ボタンをクリックして Inspection を開始します。まず “Kubernetes Engine” を選択し、収集するログ種類に "Kubernetes Node Logs"を追加 して “Next” ボタンをクリックします。

パラメータの入力画面で、調査したいクラスタや時間帯を入力する必要があります。今回は次の通りに入力して”Run”ボタンをクリックします。

  • End Time: 終了時刻
  • Duration: 作業時間
  • Project: プロジェクトID
  • Cluster Name: GKEクラスタ名

しばらく待つとログの収集が完了します。完了した Inspection の “Open” ボタンをクリックして、先ほど変更を加えた Deployment のタイムラインを確認してみましょう。

リソースビュー(画面左側)はKubernetesリソースのタイムラインを表現しており、タイムラインをクリックすることで対応するログや変更履歴が右側のトレイで見ることができます。

もう一度振り返ると、先ほど次の操作をしました。

  1. Deployment を作成する
  2. Deploymentをスケールアウトする
  3. Deploymentをロールアウトする
  4. Deploymentをロールバックする
  5. Deploymentを削除する

これを画面と照らし合わせると、おおよそこのように対応したイベントが起きているはずです。

それぞれのアクションでこのようなアクションが行われたことがわかります。

  • Deployment をスケール → DeploymentがPatchされる → deployment-controllerがReplicaSetのreplica数を変更する
  • Deploymentをロールアウト → deployment-controllerが新しいReplicaSetを作成 → deployment-controllerが元のReplicaSetのレプリカ数を減らす
  • Deploymentをロールバック → deployment-controlleが新しいReplicaSetのレプリカ数を減らして、元のReplicaSetのレプリカ数が増やす

さらに、ReplicaSetのタイムラインをクリックしてHistory Viewを見てみると、ReplicaSetへの変更は kube-system:deployment-controller が行っていることがわかります。

このようにKHIを利用することで「リソースがいつどこで誰によって変更されたのか」が一目でわかるようになっています。

ReplicaSetを眺める

改めてReplicaSetのタイムラインを見てみましょう。ReplicaSetのレプリカ数を3→8にスケールアウトした際のPodをクリックしてLog Viewを見ていると「すぐにスケジュールされたPod」と「スケジュールされるのに時間がかかったPod」を観測できる場合があります。この違いはなぜでしょうか。

これはGKE Autopilotでよく見られる挙動で、Podが作成されたもののPodをアサインできる Node がクラスタ内に存在しない時に発生します。GKE Autopilot には Node の数を自動で調整するクラスタオートスケーラーがデフォルトで有効となっています。そのためクラスタ内にPodをアサインできる Node が不足すると、オートスケーラーによって自動的に適切なNodeが作成され、Pod が Node にアサインできるようになります。

例えば今回のパターンでは、「Pod をアサインできる Node がない」ことを示す Kubernetes の Warning ログ "FailedScheduling" が出力されています。これにクラスタオートスケーラーが反応して "Scaling up nodepools by..." と Nodepool のサイズを増やすリクエストをしています。

該当の Nodepool と Node を KHI の中で探すと、その時間にちょうどオートスケーラーによって Nodepool のサイズが 0→2 に変更されており、新しい Node が増えていることが確認できます。

リソースへジャンプ

リソースに関連したリソースを調べるには、Log view の "Related resources" をクリックするとそのリソースのタイムラインまでジャンプできます。

監査ログを追加する

GKEには監査ログの設定ができます。監査ポリシー | Google Kubernetes Engine(GKE)
この監査ポリシーを DATA_WRITE と設定すると細かいパッチリクエストを追うことができるようになるため、PodやNodeの .status の変更差分を確認できるようになります。コンテナの詳細なステータスの履歴を見ることができるようになるため、必要に応じて設定しておくことを推奨します。

KHI ファイルを共有する

実は KHI にはエクスポート機能があります。エクスポートされた.khiファイルを保存し、別のKHIインスタンスに読み込ませることで全く同じタイムラインを再現することができます。

サンプルとして、本記事を作成するために使った KHI ファイルをこちらに置いておきます。MyInspection.khi - Google Drive

この KHI ファイルをダウンロードし "Open .khi file" ボタンをクリックすると、この記事と全く同じ環境を再現できます。

まとめ

Deployment の挙動を追いながら Kubernetes History Inspector(KHI) の使い方をざっくりと解説しました。今回見たのは「障害が起きていない」「デプロイされているリソースの少ない」「綺麗な」GKE クラスタの内容でした。
ぜひ、皆さんの管理している GKE クラスタを KHI で調査してみてください。普段から正常な環境を見慣れておくことで、障害や問題が起きた時に「どこらへんに問題がありそうか」をなるべく早く理解できるようになると思います。

  • 普段から KHI を使って「綺麗な環境」に見慣れておく
    • 思わぬデプロイエラーを見つけられることも……?
  • 障害が起きた際、.khi ファイルを取得してチームメンバーに配布しておく
    • 後から参加したメンバーも状況把握が速やかにできます
  • アプリケーションのロールアウトの .khi ファイルを配布して教育資料にする

などなど、便利な使い方がたくさんあります。pullしてたくさん使ってもらえると幸いです。

コントリビューションもお待ちしております💪

https://github.com/GoogleCloudPlatform/khi

Google Cloud Japan

Discussion