Kubernetes入門 第10回:オブザーバビリティ(監視・ログ)

Kubernetes入門
第10回:オブザーバビリティ(監視・ログ)


VM環境でのログ調査といえば、各サーバにSSHしてログファイルを確認する作業だ。ロードバランサー配下に10台のWebサーバがあれば、10回SSHして、10箇所の/var/logを確認することになる。

Kubernetesでは、この作業が根本的に変わる。サーバにログインしない。ログファイルのパスを覚えない。全てのログは一箇所に、同じ方法で、同じコマンドで取得できる。

本章では、「サーバに入ってログを見る」という従来の方法から、「ストリームとしてログを流し読み、メトリクスで予兆を掴む」というKubernetesネイティブな監視へのアップデートを体験する。


10.1 監視の変革:サーバに入らずに状態を知る

10.1.1 「/var/log」を捨てよう:なぜコンテナログは標準出力(stdout)で吐くべきか

VMの常識:「ログはファイルに書く」

VM環境でアプリケーションを運用してきたエンジニアにとって、ログといえばファイルだ。

  • Apacheなら /var/log/httpd/access_logerror_log
  • Tomcatなら /var/log/tomcat/catalina.out
  • 自作アプリなら /var/log/myapp/application.log

ログローテーションはlogrotateで設定し、古いログは.gzで圧縮保存。障害調査ではtail -fでリアルタイム監視、grepで絞り込み、zcatで過去ログを展開する。これが「当たり前」だった。

しかし、この「当たり前」には致命的な前提がある。

「そのサーバは、明日もそこにいる」という前提だ。

コンテナの現実:「Podは使い捨て」

Kubernetesの世界では、Podはいつでも消える可能性がある

  • Deploymentがスケールダウンすれば、Podは削除される
  • ノードが障害を起こせば、Podは別ノードで再作成される
  • ローリングアップデートでは、旧Podは新Podに置き換わる

Podが消えると、その中のファイルシステムも丸ごと消える
つまり、/var/log/myapp/application.logにログを書いていたら、Podの死と共にログも道連れになるのだ。

これが、コンテナの世界で「ログはファイルに書くな」と言われる理由である。

新しい常識:「stdout/stderrに吐けば、Kubernetesが拾ってくれる」

Kubernetesは、コンテナの標準出力(stdout)と標準エラー出力(stderr)を自動的に収集している。アプリケーションがprintfSystem.out.printlnconsole.logで出力した内容は、すべてKubernetesのログ基盤に流れ込む。

┌─────────────────────────────────────┐
│  アプリケーション                                                        │
│  ┌────────┐                                                    │
│  │ print("Hello") │──→ stdout ──→ Kubernetesが自動収集           │
│  │ log.error(...) │──→ stderr ──→ kubectl logs で参照可能        │
│  └────────┘                                                    │
└─────────────────────────────────────┘

この仕組みにより、以下のメリットが生まれる。

観点VM(ファイルログ)K8s(stdout/stderr)
ログの場所アプリごとに異なる全て同じ方法で取得
VM/Podが消えた後ファイルも消失一定期間保持される
複数VM/Pod横断各サーバにSSH1コマンドで全Pod
ログローテート自分で設定自動管理

VMエンジニアへのメッセージ:
「ログファイルのパスを覚える」という作業は、もう不要です。kubectl logs <Pod名> だけ覚えてください。


10.1.2 ログの集約:全Podのログを一箇所で把握する「kubectl logs」の威力

10台のWebサーバ、10回のSSH → 1コマンドへ

冒頭の悪夢を思い出してほしい。ロードバランサー配下の10台のWebサーバでログを追いかける地獄を。

Kubernetesでは、この問題をラベル(Label)kubectl logsの組み合わせで解決する。

┌────────────────────────────────────────┐
│  従来のVM環境                                                                  │
│                                                                                │
│  ┌───┐ ┌───┐ ┌───┐ ┌───┐ ┌───┐                        │
│  │Web01 │ │Web02 │ │Web03 │ │Web04 │ │Web05 │  ...×10台             │
│  └─┬─┘ └─┬─┘ └─┬─┘ └─┬─┘ └─┬─┘                        │
│      │SSH      │SSH      │SSH      │SSH      │SSH                         │
│      ↓         ↓         ↓         ↓         ↓                            │
│             10個のターミナル、10個のtail -f                                    │
└────────────────────────────────────────┘

┌────────────────────────────────────────┐
│  Kubernetes環境                                                                │
│                                                                                │
│  ┌───┐  ┌───┐  ┌───┐  ┌───┐  ┌───┐                    │
│  │Pod01 │  │Pod02 │  │Pod03 │  │Pod04 │  │Pod05 │  ...×10個         │
│  └─┬─┘  └─┬─┘  └─┬─┘  └─┬─┘  └─┬─┘                    │
│      └─────┴─────┴──┬──┴─────┴────                │
│                                    ↓                                          │
│                 kubectl logs -l app=web --all-containers                       │
│                              (1コマンド)                                     │
└────────────────────────────────────────┘

「全てのWebサーバ(Pod)」という概念を、Kubernetesではラベルで表現する。app=webというラベルが付いたPodを10個デプロイしておけば、kubectl logs -l app=webという1コマンドで、10個分のログが統合されて流れてくる。

これが「オブザーバビリティ(可観測性)」の入り口だ。


10.1.3 【比較】エージェント型の旧来監視 vs K8sのネイティブ監視

旧来の監視:「エージェントを入れて、設定ファイルを書いて、ポートを開けて…」

VM環境での監視といえば、以下のような作業が「儀式」として存在した。

  1. 監視エージェントのインストール:Zabbix Agent、Datadog Agent、Mackerel Agent…
  2. 設定ファイルの編集/etc/zabbix/zabbix_agentd.confに監視サーバのIPを書く
  3. ファイアウォールの穴あけ:監視用ポート(10050番など)を開放
  4. 監視サーバ側の登録:ホスト登録、テンプレート適用、しきい値設定…

新しいサーバを1台追加するたびに、この「儀式」を繰り返す。100台のサーバがあれば、100回繰り返す(もちろんAnsible等で自動化はできるが、それでも「やるべきこと」として存在する)。

K8sのネイティブ監視:「最初から入っている」

Kubernetesでは、監視の基盤が最初から組み込まれている

機能VM環境での相当物K8sでの実現方法
ログ収集rsyslog + ログサーバstdout → kubectl logs
リソース監視Zabbix/Nagios + Agentkubectl top + Metrics Server
プロセス監視監視スクリプトLiveness Probe/Readiness Probe
死活監視ping/ポート監視Kubernetesが自動で実施

特に画期的なのは、「Pod(≒プロセス)が死んだら自動で再起動する」という機能がデフォルトで有効な点だ。

VM環境では「プロセスが死んだらアラートを飛ばし、運用者が手動で再起動する」というフローが一般的だった。Kubernetesでは、「プロセスが死んだら自動で再起動し、その事実をログに残す」という自己修復が標準動作となる。

VMエンジニアへのメッセージ:
「監視エージェントを入れる」という作業は、Kubernetesでは(基本的には)不要です。監視したい情報の多くは、最初から取得できる状態になっています。


10.2 実践:kubectl logsによるログ統合管理

いよいよ実践だ。まずは監視対象となるPodを準備しよう。

準備:ログを出力し続けるサンプルアプリケーションのデプロイ

監視の実践には、「ログを出力し続けるアプリケーション」が必要だ。以下のマニフェストで、1秒ごとにログを出力するPodを3つ起動する。

[Execution User: developer]

# ログ出力用のDeploymentを作成
cat << 'EOF' > ~/log-generator.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
  name: log-generator
  labels:
    app: log-generator
spec:
  replicas: 3
  selector:
    matchLabels:
      app: log-generator
  template:
    metadata:
      labels:
        app: log-generator
        tier: demo
    spec:
      containers:
      - name: logger
        image: busybox:1.36
        command:
        - /bin/sh
        - -c
        - |
          counter=0
          while true; do
            counter=$((counter + 1))
            timestamp=$(date '+%Y-%m-%d %H:%M:%S')
            # 10回に1回、意図的にエラーログを出力
            if [ $((counter % 10)) -eq 0 ]; then
              echo "[$timestamp] [ERROR] Something went wrong! Request #$counter failed" >&2
            else
              echo "[$timestamp] [INFO] Processing request #$counter from $(hostname)"
            fi
            sleep 1
          done
EOF

[Execution User: developer]

# Deploymentをデプロイ
kubectl apply -f ~/log-generator.yaml

出力例:

deployment.apps/log-generator created

[Execution User: developer]

# Podが3つ起動していることを確認
kubectl get pods -l app=log-generator

出力例:

NAME                             READY   STATUS    RESTARTS   AGE
log-generator-7d4f8b6c9f-2xk8j   1/1     Running   0          15s
log-generator-7d4f8b6c9f-9m3vp   1/1     Running   0          15s
log-generator-7d4f8b6c9f-kq7wn   1/1     Running   0          15s

これで準備完了だ。3つのPodが、それぞれ1秒ごとにログを出力し続けている。


10.2.1 単体Podのログ確認から、ラベル(-l)を使った複数Podの同時監視まで

Step 1:単体Podのログを見る(基本中の基本)

まずは1つのPodのログを見てみよう。

[Execution User: developer]

# Pod名を取得(1つ目のPodを対象にする)
POD_NAME=$(kubectl get pods -l app=log-generator -o jsonpath='{.items[0].metadata.name}')
echo "対象Pod: $POD_NAME"

# ログを表示(直近10行)
kubectl logs $POD_NAME --tail=10

出力例:

対象Pod: log-generator-7d4f8b6c9f-2xk8j
[2026-01-19 10:15:31] [INFO] Processing request #42 from log-generator-7d4f8b6c9f-2xk8j
[2026-01-19 10:15:32] [INFO] Processing request #43 from log-generator-7d4f8b6c9f-2xk8j
[2026-01-19 10:15:33] [INFO] Processing request #44 from log-generator-7d4f8b6c9f-2xk8j
[2026-01-19 10:15:34] [INFO] Processing request #45 from log-generator-7d4f8b6c9f-2xk8j
[2026-01-19 10:15:35] [INFO] Processing request #46 from log-generator-7d4f8b6c9f-2xk8j
[2026-01-19 10:15:36] [INFO] Processing request #47 from log-generator-7d4f8b6c9f-2xk8j
[2026-01-19 10:15:37] [INFO] Processing request #48 from log-generator-7d4f8b6c9f-2xk8j
[2026-01-19 10:15:38] [INFO] Processing request #49 from log-generator-7d4f8b6c9f-2xk8j
[2026-01-19 10:15:39] [ERROR] Something went wrong! Request #50 failed
[2026-01-19 10:15:40] [INFO] Processing request #51 from log-generator-7d4f8b6c9f-2xk8j

これがkubectl logsの基本形だ。VMでいうところの「SSHしてtail -10 /var/log/xxx」に相当する。

Step 2:ラベルを使って複数Podを一括監視

ここからがKubernetesの真骨頂。ラベル(-lオプション)を使えば、複数のPodのログを1コマンドで取得できる。

[Execution User: developer]

# ラベル "app=log-generator" を持つ全Podのログを取得
# --prefix オプションでPod名を先頭に付ける
kubectl logs -l app=log-generator --prefix --tail=5

出力例:

[pod/log-generator-7d4f8b6c9f-2xk8j/logger] [2026-01-19 10:16:01] [INFO] Processing request #72 from log-generator-7d4f8b6c9f-2xk8j
[pod/log-generator-7d4f8b6c9f-2xk8j/logger] [2026-01-19 10:16:02] [INFO] Processing request #73 from log-generator-7d4f8b6c9f-2xk8j
[pod/log-generator-7d4f8b6c9f-9m3vp/logger] [2026-01-19 10:16:01] [INFO] Processing request #71 from log-generator-7d4f8b6c9f-9m3vp
[pod/log-generator-7d4f8b6c9f-9m3vp/logger] [2026-01-19 10:16:02] [INFO] Processing request #72 from log-generator-7d4f8b6c9f-9m3vp
[pod/log-generator-7d4f8b6c9f-kq7wn/logger] [2026-01-19 10:16:00] [ERROR] Something went wrong! Request #70 failed
[pod/log-generator-7d4f8b6c9f-kq7wn/logger] [2026-01-19 10:16:01] [INFO] Processing request #71 from log-generator-7d4f8b6c9f-kq7wn
...

注目してほしい。3つのPodのログが、1つのストリームに統合されて出力されている。各行の先頭には[pod/Pod名/コンテナ名]というプレフィックスが付き、どのPodからのログかが一目瞭然だ。

これが「10台のサーバに10回SSH」からの解放だ。

VMエンジニアへのメッセージ:
kubectl logs -l <ラベル> は、「このラベルが付いた全てのPodのログを見せてくれ」という意味です。Webサーバ10台なら app=web、バッチサーバ5台なら app=batch というように、ラベル設計さえしておけば、どんな規模でも1コマンドです。

複数ラベルの組み合わせ

ラベルは複数指定できる。例えば「本番環境のWebサーバだけ」を見たい場合:

[Execution User: developer]

# app=log-generator かつ tier=demo のPodのみ
kubectl logs -l app=log-generator,tier=demo --prefix --tail=3

これはAND条件として機能する。複雑な環境でも、ラベルの組み合わせで柔軟にフィルタリングできる。


10.2.2 ストリーミング表示(-f)と過去ログ(–previous)の使い分け

リアルタイム監視:-f(follow)オプション

障害対応で最も重要なのは「今、何が起きているか」をリアルタイムで把握すること。-fオプションを使えば、ログをストリーミング表示できる。

[Execution User: developer]

# リアルタイムでログを追跡(Ctrl+Cで終了)
kubectl logs -l app=log-generator --prefix -f

出力例(リアルタイムで流れ続ける):

[pod/log-generator-7d4f8b6c9f-2xk8j/logger] [2026-01-19 10:20:15] [INFO] Processing request #324 from log-generator-7d4f8b6c9f-2xk8j
[pod/log-generator-7d4f8b6c9f-9m3vp/logger] [2026-01-19 10:20:15] [INFO] Processing request #323 from log-generator-7d4f8b6c9f-9m3vp
[pod/log-generator-7d4f8b6c9f-kq7wn/logger] [2026-01-19 10:20:15] [INFO] Processing request #322 from log-generator-7d4f8b6c9f-kq7wn
[pod/log-generator-7d4f8b6c9f-2xk8j/logger] [2026-01-19 10:20:16] [INFO] Processing request #325 from log-generator-7d4f8b6c9f-2xk8j
...(リアルタイムで更新され続ける)

VMでいうところのtail -fと同じ感覚だが、複数Pod分が1画面に集約されるのがポイントだ。

Ctrl+Cで終了する。

過去のログ:–previous オプション(クラッシュしたコンテナのログ)

Podが再起動した場合、「再起動前のログ」を見たいことがある。--previousオプションは、直前に終了したコンテナのログを表示する。

これを試すために、意図的にクラッシュするPodを作成してみよう。

[Execution User: developer]

# 5秒後にクラッシュするPodを作成
cat << 'EOF' > ~/crash-demo.yaml
apiVersion: v1
kind: Pod
metadata:
  name: crash-demo
spec:
  containers:
  - name: crasher
    image: busybox:1.36
    command:
    - /bin/sh
    - -c
    - |
      echo "[INFO] Container starting..."
      echo "[INFO] Doing some important work..."
      sleep 5
      echo "[ERROR] Fatal error occurred!"
      exit 1
EOF

[Execution User: developer]

kubectl apply -f ~/crash-demo.yaml

[Execution User: developer]

# Podの状態を確認(数秒待つとRESTARTSが増えていく)
sleep 10
kubectl get pod crash-demo

出力例:

NAME         READY   STATUS    RESTARTS      AGE
crash-demo   0/1     Running   1 (2s ago)    12s

RESTARTSが1以上になっていれば、コンテナが再起動している。この状態で--previousオプションを使うと、クラッシュ直前のログを確認できる。

[Execution User: developer]

# 現在のコンテナのログ(再起動後)
kubectl logs crash-demo

出力例:

[INFO] Container starting...
[INFO] Doing some important work...

[Execution User: developer]

# 直前のコンテナのログ(クラッシュしたもの)
kubectl logs crash-demo --previous

出力例:

[INFO] Container starting...
[INFO] Doing some important work...
[ERROR] Fatal error occurred!

--previousを使うことで、クラッシュ直前に出力された[ERROR] Fatal error occurred!というログを確認できた。

–previousが使えるケース・使えないケース

シナリオ–previousで取得理由
コンテナがクラッシュして再起動✅ 可能同一Pod内でコンテナが入れ替わった
kubectl delete podでPod削除❌ 不可Pod自体が消えたため、ログも消失
Deploymentのローリングアップデート❌ 不可旧Podは削除され、新Podが作成される

VMエンジニアへのメッセージ:
--previousは「直前に死んだコンテナのログ」を見るオプションです。VMでいうと、「クラッシュ直前のdmesgやsyslog」に近い概念です。ただし、Pod自体が削除された場合は使えない点に注意してください。

[Execution User: developer]

# 後片付け
kubectl delete -f ~/crash-demo.yaml
rm ~/crash-demo.yaml

10.2.3 応用:ログの中に特定のキーワード(Error等)を瞬時に見つけるフィルタリング術

大量のログの中から「エラーだけ」を抽出したい場面は多い。Kubernetesには専用のフィルタ機能はないが、Linuxのパイプと組み合わせることで強力なフィルタリングが可能だ。

ERRORを含む行だけを抽出

[Execution User: developer]

# ERRORを含む行だけを表示
kubectl logs -l app=log-generator --prefix --tail=100 | grep ERROR

出力例:

[pod/log-generator-7d4f8b6c9f-9m3vp/logger] [2026-01-19 10:25:30] [ERROR] Something went wrong! Request #630 failed
[pod/log-generator-7d4f8b6c9f-kq7wn/logger] [2026-01-19 10:25:28] [ERROR] Something went wrong! Request #620 failed
[pod/log-generator-7d4f8b6c9f-xn5rt/logger] [2026-01-19 10:25:35] [ERROR] Something went wrong! Request #50 failed

リアルタイム + フィルタリング

[Execution User: developer]

# リアルタイムでERRORだけを監視(Ctrl+Cで終了)
kubectl logs -l app=log-generator --prefix -f | grep --line-buffered ERROR

出力例(ERRORが発生するたびに表示される):

[pod/log-generator-7d4f8b6c9f-9m3vp/logger] [2026-01-19 10:26:40] [ERROR] Something went wrong! Request #700 failed
[pod/log-generator-7d4f8b6c9f-kq7wn/logger] [2026-01-19 10:26:38] [ERROR] Something went wrong! Request #690 failed
...

--line-bufferedは、grepの出力をバッファリングせずに即座に表示するオプション。リアルタイム監視時には必須だ。

時間範囲を指定してログを取得

「直近5分間のログだけ見たい」という場合は、--sinceオプションを使う。

[Execution User: developer]

# 直近5分間のログを取得
kubectl logs -l app=log-generator --since=5m --prefix | head -20

--sinceには以下の形式が使える:

  • --since=5m:直近5分
  • --since=1h:直近1時間
  • --since-time=2026-01-19T10:00:00Z:特定の時刻以降

VMエンジニアへのメッセージ:
Linuxの基本コマンド(grep, head, tail, awk等)は、そのままkubectl logsと組み合わせられます。VM時代に培った「ログ調査のテクニック」は、Kubernetesでも100%活かせます。


10.3 ツール:2026年の軽量監視スタックの紹介

ログだけでなく、リソース消費(CPU・メモリ)の監視も重要だ。VMware環境でいえば、vCenterのパフォーマンスチャートや、Zabbixのグラフに相当する機能を見ていこう。

10.3.1 リソース監視の基本:kubectl top でボトルネックを特定する

Metrics Serverのインストール

kubectl topコマンドを使うには、Metrics Serverが必要だ。kind環境にインストールしよう。

[Execution User: developer]

# Metrics Serverをインストール(kind環境用の設定を追加)
kubectl apply -f https://github.com/kubernetes-sigs/metrics-server/releases/latest/download/components.yaml

# kind環境ではTLS検証をスキップする設定が必要
kubectl patch deployment metrics-server -n kube-system --type='json' -p='[
  {
    "op": "add",
    "path": "/spec/template/spec/containers/0/args/-",
    "value": "--kubelet-insecure-tls"
  }
]'

出力例:

serviceaccount/metrics-server created
clusterrole.rbac.authorization.k8s.io/system:aggregated-metrics-reader created
clusterrole.rbac.authorization.k8s.io/system:metrics-server created
rolebinding.rbac.authorization.k8s.io/metrics-server-auth-reader created
clusterrolebinding.rbac.authorization.k8s.io/metrics-server:system:auth-delegator created
clusterrolebinding.rbac.authorization.k8s.io/system:metrics-server created
service/metrics-server created
deployment.apps/metrics-server created
apiservice.apiregistration.k8s.io/v1beta1.metrics.k8s.io created
deployment.apps/metrics-server patched

[Execution User: developer]

# Metrics Serverが起動するまで待機(1〜2分)
kubectl wait --for=condition=available --timeout=120s deployment/metrics-server -n kube-system

Podのリソース使用量を確認

[Execution User: developer]

# Podごとのリソース使用量を表示
kubectl top pods -l app=log-generator

出力例:

NAME                             CPU(cores)   MEMORY(bytes)
log-generator-7d4f8b6c9f-9m3vp   1m           2Mi
log-generator-7d4f8b6c9f-kq7wn   1m           2Mi
log-generator-7d4f8b6c9f-xn5rt   1m           1Mi

これは、VMware環境でいうところの「vCenterでVMのCPU・メモリ使用率を確認する」操作に相当する。

  • CPU(cores):1m = 0.001コア(1000m = 1コア)
  • MEMORY(bytes):使用中のメモリ量

ノードのリソース使用量を確認

[Execution User: developer]

# ノードごとのリソース使用量を表示
kubectl top nodes

出力例:

NAME                 CPU(cores)   CPU%   MEMORY(bytes)   MEMORY%
kind-control-plane   125m         6%     1024Mi          52%

これは「ESXiホストの全体的なリソース使用率」を見ているのと同じ感覚だ。

VMエンジニアへのメッセージ:
kubectl topは、vCenterのパフォーマンスモニタをコマンドラインで実現したものです。GUIに頼らず、ターミナルからリアルタイムでリソース状況を把握できます。


10.3.2 2026年のトレンド:軽量なモニタリング環境(Metrics Server / k9s 等)の紹介

Metrics Server:最小構成のリソース監視

Metrics Serverは、Kubernetesクラスタに最低限のリソース監視機能を追加するコンポーネントだ。

特徴説明
軽量メモリ数十MB程度で動作
標準APIkubectl topコマンドで利用可能
リアルタイム直近のメトリクスのみ保持(履歴なし)
用途HPA(水平Pod自動スケーリング)のトリガー、kubectl topでの確認

本番環境で「過去のメトリクスをグラフで見たい」場合は、PrometheusやGrafanaといった本格的な監視スタックが必要になるが、開発・検証環境や小規模環境ではMetrics Serverで十分なケースも多い。

k9s:ターミナルベースのKubernetes管理UI

k9sは、ターミナル上で動作するKubernetes専用の管理ツールだ。2026年現在、多くのエンジニアに愛用されている。

[Execution User: developer]

# k9sのインストール(まだインストールしていない場合)
# バイナリを直接ダウンロード
curl -sL https://github.com/derailed/k9s/releases/latest/download/k9s_Linux_amd64.tar.gz | tar xz -C /tmp
sudo mv /tmp/k9s /usr/local/bin/

[Execution User: developer]

# k9sを起動(Ctrl+Cキーで終了)
k9s

k9sの画面イメージ(テキストベースUI):

┌───────────────────────────────────┐
│ k9s - Kubernetes CLI To Manage Your Clusters In Style!               │
├───────────────────────────────────┤
│ Context: kind-kind    Cluster: kind-kind    User: kind-kind          │
├───────────────────────────────────┤
│ Pods(default)                                                        │
│ NAME                              READY  STATUS   RESTARTS  AGE      │
│ log-generator-7d4f8b6c9f-9m3vp    1/1    Running  0         15m      │
│ log-generator-7d4f8b6c9f-kq7wn    1/1    Running  0         15m      │
│ log-generator-7d4f8b6c9f-xn5rt    1/1    Running  0         5m       │
├───────────────────────────────────┤
│ <0> all <1> default <a> Attach <ctrl-d> Delete <d> Describe          │
│ <e> Edit <enter> View <esc> Back <l> Logs <p> Logs Previous          │
└───────────────────────────────────┘

k9sの主な機能:

  • l:選択したPodのログをリアルタイム表示
  • d:Podの詳細情報(describe)を表示
  • Ctrl+d:Podを削除
  • /:フィルタリング(Pod名で絞り込み)
  • :deploy:Deploymentの一覧に切り替え
  • :svc:Serviceの一覧に切り替え

VMエンジニアへのメッセージ:
k9sは「vCenterのWebクライアントをターミナルで実現したようなもの」です。GUI操作に慣れた方でも、k9sを使えば直感的にKubernetesを操作できます。

2026年の監視エコシステム概観

参考として、2026年現在のKubernetes監視エコシステムを整理しておく。

ツール/スタック用途規模感
Metrics Server最小限のリソース監視、HPA小〜中規模
k9sターミナルベースの運用UI個人〜チーム
Prometheus + Grafana本格的なメトリクス収集・可視化中〜大規模
Loki + Grafanaログの集約・検索・可視化中〜大規模
OpenTelemetry分散トレーシング、メトリクス、ログの統合大規模・マイクロサービス

本シリーズでは「まず手を動かして体験する」ことを重視しているため、本格的な監視スタックの構築は割愛する。しかし、kubectl logskubectl topで基本を押さえておけば、より高度なツールへのステップアップも容易だ。


10.3.3 【次回予告】ついに最終回。トラブルシューティングの総仕上げ

次回は、本シリーズの最終回となる。

テーマは「トラブルシューティングの総仕上げ」。これまでの連載で学んだ知識を総動員し、「Podが起動しない」「ネットワークが繋がらない」「アプリケーションがエラーを返す」といった典型的なトラブルに対処するためのフレームワークを提示する。

最終回にふさわしく、「障害発生 → 調査 → 原因特定 → 修復」という一連の流れを、実践形式で体験していただく予定だ。


10.4 トラブルシューティングのTips

ログが全く出ない(何も表示されない)ときのチェックポイント

症状:kubectl logsを実行しても何も表示されない

$ kubectl logs my-app-pod
(何も表示されない)

チェック1:アプリケーションは本当にstdout/stderrに出力しているか?

最も多い原因は、アプリケーションがファイルにログを書いているケースだ。

【NG】アプリケーションがファイルに出力
┌───────────────────┐
│  アプリケーション                    │
│  log.setOutput("/app/logs/app.log")  │  ← ファイルに書いている
│                                      │  → kubectl logsには何も流れない
└───────────────────┘

【OK】アプリケーションがstdoutに出力
┌───────────────────┐
│  アプリケーション                    │
│  log.setOutput(os.Stdout)            │  ← 標準出力に書いている
│                                      │  → kubectl logsで見られる
└───────────────────┘

対処: アプリケーションの設定を変更し、ログ出力先をstdout/stderrに変更する。多くのフレームワークには、ログ出力先を環境変数で切り替える機能がある。

チェック2:出力がバッファリングされていないか?

PythonやNode.jsなどの言語では、標準出力がバッファリングされることがある。バッファが溜まるまで出力されないため、「ログが出ない」ように見える。

対処(Pythonの場合):

# 環境変数でバッファリングを無効化
# Dockerfile内で設定
ENV PYTHONUNBUFFERED=1

対処(Node.jsの場合):

// console.logは通常バッファリングされないが、
// process.stdout.writeを使う場合は注意

チェック3:コンテナは正しく起動しているか?

Podのステータスを確認する。

[Execution User: developer]

kubectl get pod my-app-pod
kubectl describe pod my-app-pod

CrashLoopBackOffError状態であれば、コンテナ自体が起動に失敗している。その場合は--previousオプションで直前のログを確認する。


Podが消えた後でもログを追うための「ログ保存期間」の考え方

Kubernetesのログ保持の仕組み

Kubernetesは、コンテナのログをノードのローカルファイルシステムに保存している。

ノード上のログ保存場所:
/var/log/containers/<pod名>_<namespace名>_<コンテナ名>-<コンテナID>.log

このログは、Podが存在する間は保持される。しかし、Podが削除されると、一定期間(デフォルトではコンテナランタイムの設定に依存)でログも削除される。

「Podが消えたらログも消える」問題への対策

対策説明難易度
即座にログを保存障害発生時、Podが消える前にkubectl logs > /tmp/debug.logで保存★☆☆
ログの集約基盤を導入Loki, Elasticsearch等でログを外部に保存★★★
Event APIを活用kubectl get eventsでPodのライフサイクルイベントを確認★★☆

開発・検証環境では、障害発生時に素早くkubectl logsでログを取得する習慣をつけることが重要だ。

[Execution User: developer]

# 障害発生時、まずログを保存する(Podが消える前に!)
kubectl logs -l app=log-generator --prefix > /tmp/incident-$(date +%Y%m%d-%H%M%S).log
echo "ログを保存しました: /tmp/incident-$(date +%Y%m%d-%H%M%S).log"

Eventを活用する

Podが消えてしまっても、Eventには痕跡が残っていることがある。

[Execution User: developer]

# 直近のイベントを確認(Podの作成・削除・エラー等が記録されている)
kubectl get events --sort-by='.lastTimestamp' | tail -20

出力例:

LAST SEEN   TYPE      REASON              OBJECT                                MESSAGE
2m          Normal    Scheduled           pod/log-generator-7d4f8b6c9f-xn5rt    Successfully assigned default/log-generator-...
2m          Normal    Pulled              pod/log-generator-7d4f8b6c9f-xn5rt    Container image "busybox:1.36" already present
2m          Normal    Created             pod/log-generator-7d4f8b6c9f-xn5rt    Created container logger
2m          Normal    Started             pod/log-generator-7d4f8b6c9f-xn5rt    Started container logger
5m          Normal    Killing             pod/log-generator-7d4f8b6c9f-2xk8j    Stopping container logger

Eventは通常1時間程度保持される(設定により異なる)。Podが消えた直後であれば、「なぜ消えたのか」のヒントを得られることがある。

VMエンジニアへのメッセージ:
VMでいうと、Eventは「vCenterのタスクとイベント」に近い存在です。「いつ、何が起きたか」の記録として活用してください。


後片付け

実践が終わったら、作成したリソースを削除しておこう。

[Execution User: developer]

# ログ出力用のDeploymentを削除
kubectl delete -f ~/log-generator.yaml

# マニフェストファイルを削除
rm ~/log-generator.yaml

まとめ:第10回で学んだこと

本章では、Kubernetesにおけるオブザーバビリティ(可観測性)の基礎を学んだ。

VM時代 → K8s時代の変化

観点VM時代K8s時代
ログの場所/var/log/xxx(サーバごとに異なる)全てkubectl logsで統一
複数サーバのログ各サーバにSSHして確認ラベル指定で1コマンド
リアルタイム監視tail -fを複数ターミナルでkubectl logs -f -l <label>
リソース監視監視エージェントを導入kubectl topで即座に確認

押さえておくべきコマンド

# 基本のログ確認
kubectl logs <pod名>

# 複数Podのログを一括取得
kubectl logs -l <ラベル> --prefix

# リアルタイム監視
kubectl logs -l <ラベル> -f

# 直近N分のログ
kubectl logs <pod名> --since=5m

# 以前のコンテナのログ
kubectl logs <pod名> --previous

# リソース使用量
kubectl top pods
kubectl top nodes