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_log、error_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)を自動的に収集している。アプリケーションがprintfやSystem.out.printlnやconsole.logで出力した内容は、すべてKubernetesのログ基盤に流れ込む。
┌─────────────────────────────────────┐
│ アプリケーション │
│ ┌────────┐ │
│ │ print("Hello") │──→ stdout ──→ Kubernetesが自動収集 │
│ │ log.error(...) │──→ stderr ──→ kubectl logs で参照可能 │
│ └────────┘ │
└─────────────────────────────────────┘
この仕組みにより、以下のメリットが生まれる。
| 観点 | VM(ファイルログ) | K8s(stdout/stderr) |
|---|---|---|
| ログの場所 | アプリごとに異なる | 全て同じ方法で取得 |
| VM/Podが消えた後 | ファイルも消失 | 一定期間保持される |
| 複数VM/Pod横断 | 各サーバにSSH | 1コマンドで全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環境での監視といえば、以下のような作業が「儀式」として存在した。
- 監視エージェントのインストール:Zabbix Agent、Datadog Agent、Mackerel Agent…
- 設定ファイルの編集:
/etc/zabbix/zabbix_agentd.confに監視サーバのIPを書く - ファイアウォールの穴あけ:監視用ポート(10050番など)を開放
- 監視サーバ側の登録:ホスト登録、テンプレート適用、しきい値設定…
新しいサーバを1台追加するたびに、この「儀式」を繰り返す。100台のサーバがあれば、100回繰り返す(もちろんAnsible等で自動化はできるが、それでも「やるべきこと」として存在する)。
K8sのネイティブ監視:「最初から入っている」
Kubernetesでは、監視の基盤が最初から組み込まれている。
| 機能 | VM環境での相当物 | K8sでの実現方法 |
|---|---|---|
| ログ収集 | rsyslog + ログサーバ | stdout → kubectl logs |
| リソース監視 | Zabbix/Nagios + Agent | kubectl 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程度で動作 |
| 標準API | kubectl 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 logsとkubectl 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
CrashLoopBackOffやError状態であれば、コンテナ自体が起動に失敗している。その場合は--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
