KubernetesのPod配置状況をNodeごとにわけて表示する方法

解決する悩み

kubectl get pod -o wide --all-namespaces を実行したとき、Podの配置状況を把握しにくいという悩みを解決します。NodeごとにどのPodが配置されているかをスムーズに確認できる方法を紹介します。

背景

私個人のWEBサイト運用環境では、GCP の Kubernetes クラスタで Spot VM を活用しています。Spot VMはコスト削減に有効ですが、時間制限付きなので再起動が頻繁に発生します。ノードが再起動(ダウン)しても、多くの場合はPodも正常に起動してくれるので殆ど問題にならないのですが、それでも数ヶ月に1回くらいは、変に詰まったりしてリカバリ作業をすることがあります。(急ぎでなければ、次のダウンタイムまで放っておくこともありますのですけどね)

このため、トラブルが起きたときにNodeごとのPod配置状況を簡単に確認する必要があります。ダラダラと表示される Pod 一覧を見ていてもいいのですが、Nodeごとに表示したいと思うこともしばしばありました。

そのため、手軽にNode単位で確認できるコマンドがあれば、運用の効率化が図れると考えました。

1. kubectl get pod だけではわかりにくい理由

Kubernetesのkubectl get podコマンドは、Podの一覧を表示するための便利なコマンドです。しかし、以下の課題があります:

  • 情報が多すぎる-o wide オプションで詳細情報を表示しても、全てのPodが一列に並び、Nodeごとにグループ化されていません。
  • Node単位の視認性が低い:トラブルシューティング時に、どのNodeにどのPodが配置されているかを瞬時に把握するのが難しい。

2. 必要な情報だけを表示するカスタムカラムの活用

kubectl には、出力をカスタマイズできる -o custom-columns オプションがあります。この機能を使うことで、必要な情報だけを抽出し、RESTARTS など不要な列を省略できます。

特にRESTARTS列は、表記の揺れ(例: 19 (92m ago) など)があり、区切り文字がズレてしまうことがあります。そのため、手っ取り早く表示するために非表示にすることにしました。

コマンド例

kubectl get pod -A -o custom-columns="NAMESPACE:.metadata.namespace,NAME:.metadata.name,READY:.status.containerStatuses[*].ready/.status.containerStatuses[*].restartCount,STATUS:.status.phase,AGE:.metadata.creationTimestamp,IP:.status.podIP,NODE:.spec.nodeName"

出力例

NAMESPACE     NAME               READY   STATUS    AGE                 IP             NODE
default       example-pod-1      1/1     Running   2024-12-12T08:00Z   10.244.0.1     node1
kube-system   kube-dns-abcdef    3/3     Running   2024-12-11T07:50Z   10.244.0.10    node2

3. NodeごとにPodをグループ化して表示する方法

情報が整理されても、全Podが一列に並んだままでは視認性が低いです。この課題を解決するために、awk を使って出力をNode単位にグループ化します。

ワンライナーでNode単位にグループ化

以下のコマンドを実行すると、NodeごとにPodがグループ化されて表示されます:

kubectl get pod -A -o custom-columns="NAMESPACE:.metadata.namespace,NAME:.metadata.name,READY:.status.containerStatuses[*].ready/.status.containerStatuses[*].restartCount,STATUS:.status.phase,AGE:.metadata.creationTimestamp,IP:.status.podIP,NODE:.spec.nodeName" | awk 'NR==1 {header=$0; next} {node=$NF; pods[node]=(node in pods ? pods[node] : header "\n") $0 "\n"} END {for (node in pods) print "\n=== NODE: " node " ===\n" pods[node]}'

コマンドの構造(解説)

  • kubectl get pod 部分

    kubectl get pod -A -o custom-columns="..."
    
    **`A`**: すべての名前空間からPod情報を取得します。
    **`o custom-columns`**: 出力するカラムを指定します。ここでは以下のカラムを定義しています:
    `NAMESPACE`: Podが所属する名前空間。
    `NAME`: Podの名前。
    `READY`: 各Pod内のコンテナが稼働している数と、合計コンテナ数(例: `1/1`)。
    `STATUS`: Podのステータス(`Running`, `Pending`, など)。
    `AGE`: Podが作成された日時。
    `IP`: PodのIPアドレス。
    `NODE`: Podが配置されているノード名。
    
    �の部分だけで、指定されたカラムの一覧を取得できます。
    
  • awk 部分

awk 'NR==1 {header=$0; next} {node=$NF; pods[node]=(node in pods ? pods[node] : header "\n") $0 "\n"} END {for (node in pods) print "\n=== NODE: " node " ===\n" pods[node]}'
  • NR==1 {header=$0; next}:
    • 最初の行(ヘッダー行)をheader変数に保存し、次の行にスキップします。
    • これにより、ヘッダーを各ノードごとのデータの先頭に挿入する準備をします。
  • node=$NF:
    • $NFは現在の行の最後のフィールド(ここではNODE列)を指します。
    • node変数にノード名を格納します。
  • pods[node]=(node in pods ? pods[node] : header "\n") $0 "\n":
    • ノードごとにデータをグループ化します。
    • 初めてのノードの場合はheader(ヘッダー行)を追加し、すでに存在するノードにはPod情報を追加します。
  • END {for (node in pods) print "\n=== NODE: " node " ===\n" pods[node]}:
    • 最後にpods配列をループして、ノード名とそのノードに属するPod情報を出力します。

出力例

=== NODE: node1 ===
NAMESPACE     NAME               READY   STATUS    AGE                 IP             NODE
default       example-pod-1      1/1     Running   2024-12-12T08:00Z   10.244.0.1     node1

=== NODE: node2 ===
NAMESPACE     NAME               READY   STATUS    AGE                 IP             NODE
kube-system   kube-dns-abcdef    3/3     Running   2024-12-11T07:50Z   10.244.0.10    node2

4. 再利用のために .zshrc に登録する方法

このコマンドを毎回入力するのは面倒なので、.zshrc に関数として登録することで再利用性を高めます。

.zshrc に関数を追加

以下の内容を .zshrc に追記してください:

bash
コードをコピーする
# ノードごとにPodをグループ化して表示する関数
group_pods_by_node() {
  kubectl get pod -A -o custom-columns="NAMESPACE:.metadata.namespace,NAME:.metadata.name,READY:.status.containerStatuses[*].ready/.status.containerStatuses[*].restartCount,STATUS:.status.phase,AGE:.metadata.creationTimestamp,IP:.status.podIP,NODE:.spec.nodeName" | awk 'NR==1 {header=$0; next} {node=$NF; pods[node]=(node in pods ? pods[node] : header "\n") $0 "\n"} END {for (node in pods) print "\n=== NODE: " node " ===\n" pods[node]}'
}

設定を反映

ターミナルで以下を実行して .zshrc を反映します:

source ~/.zshrc

使い方

登録後、以下のコマンドで簡単にNodeごとのPod配置状況を確認できます:

group_pods_by_node

5. Kubernetesトラブル対応時の活用例

Node再起動やトラブル発生時に、このコマンドを使うと以下のような利点があります:

  • 停止したNodeの確認:停止中のNodeに配置されていたPodを特定可能。
  • Podの再配置確認:別のNodeに再スケジュールされたPodの状態を迅速に確認。

まとめ

kubectl コマンドの基本的な使い方に加え、NodeごとにPod配置状況を整理する手法を紹介しました。ワンライナーや関数化により、日常業務での利便性が向上します。トラブル対応や運用効率化のために、ぜひ活用してみてください!