症状を読むのは反射神経だ
一言でいうと
問題解決は、文章では身につきません。kubectl get podに表示された文字を見て、3秒以内に次に見る場所が思い浮かぶ必要がありますが、それは自分で障害を作ってみてはじめて、体に残ります。
なぜ本物の障害でなければならないのか
CKAは、問題解決が配点の大きな部分を占めます。ところが、前のモジュールが動いている偽のクラスターには、kubeletもコンテナランタイムもないので、障害そのものを作れませんでした。
| 症状 | 偽のクラスターでは |
|---|---|
ImagePullBackOff |
イメージを取得しないので発生しません |
CrashLoopBackOff |
プロセスがないので、死ぬこともありません |
OOMKilled |
メモリを使わないので、超過することがありません |
| プローブ失敗による再起動 | プローブを実行しません |
PVCBound |
プロビジョナーがないので、永遠にPendingです |
そのため、「この症状は何を意味するのか」を、文章だけで学ぶしかありませんでした。問題解決は、そのようには身につきません。kubectl get podに表示された文字を見て、3秒以内に次に見る場所が思い浮かぶ必要がありますが、それは自分で作ってみてはじめて、体に残ります。
似ているのに原因が違うもの
PendingとContainerCreating: 前者はスケジューラー、後者はkubeletの問題です。kubectl get pod -o wideのNODE列が埋まっているかどうかで分かれます。livenessの失敗とreadinessの失敗: 前者は再起動、後者はトラフィックからだけ除外します。- 存在しないConfigMapを
envで参照するとCreateContainerConfigError、同じものをボリュームとして参照するとPendingです。
3つだけ覚えておけばよい
describeのEventsを先に見ます。状態名は、どこで詰まったかだけを教えてくれます。何がないのかは、常にイベントにあります。logsが空なら--previousです。CrashLoopBackOffのPodの現在のコンテナは、まだ何も出力していません。- NODE列を見ます。空ならスケジューラー、埋まっていればkubeletです。この1行で、調査の範囲が半分になります。
症状ごとに次に見る場所
状態名を原因に直接結び付けず、次にどこを見るかに結び付けると、調査がはるかに速くなります。以下は、その対応表です。
| 状態 | 次に見る場所 | よくある原因 |
|---|---|---|
Pending、NODEが空 |
describe podのEvents |
requestsがノードの余裕より大きい、テイント、ノードセレクターがどのノードとも合わない |
Pending、ボリューム関連 |
PVCの状態とStorageClass | プロビジョナーがない、またはアクセスモードが合わない |
ContainerCreatingが長い |
そのノードのkubelet | イメージが大きい、ボリュームのマウントが終わらない、Secretがない |
ImagePullBackOff |
Eventsのpull失敗の行 | タグのタイプミス、プライベートレジストリの資格情報がない、ネットワークの遮断 |
CrashLoopBackOff |
logs --previous |
設定がなくてすぐに終了する、依存サービスに届かない |
OOMKilled |
describeのLast State |
limitsが実際の使用量より小さい |
CreateContainerConfigError |
参照したConfigMap・Secret | 名前のタイプミス、またはまだ作成されていない |
Runningなのにトラフィックがない |
エンドポイントとreadiness | セレクターがラベルと合わない、またはreadinessが失敗し続けている |
最後の行は、特によく人を引っかけます。PodはRunningでログも正常なのに、リクエストが1つも入ってこない状況です。このとき見るべきなのは、Podではなくサービスのエンドポイントです。空なら、2つのうちどちらかです。サービスのセレクターがPodのラベルと合わないか、readinessプローブが失敗して、Podが一覧から外れているかです。2つの場合を分ける方法は簡単です。PodにReady 0/1と表示されていればプローブの問題で、Ready 1/1なのにエンドポイントが空なら、セレクターの問題です。
ノード自体が問題のときも、Podの症状として最初に現れます。ノードがNotReadyになると、その上のPodはしばらくRunningのまま残り、一定時間が過ぎてはじめて片付けられます。そのため、「PodはRunningなのに応答がない」という状況では、Podだけを見ずに、kubectl get nodesを一度実行する習慣が必要です。この1行が、数十分を節約してくれます。
実務で本当に大切なこと
状態名ではなく、Eventsを先に読みます。状態は、どこで詰まったかだけを教えてくれて、何がないのかは、常にイベントにあります。試験でも実務でも、この順序を入れ替えると、時間を2倍使います。
NODE列1つで、調査の範囲が半分になります。空ならスケジューラー、埋まっていればkubeletです。kubectl get pod -o wideを習慣にすれば、この分岐が無料でついてきます。
CrashLoopBackOffでは、--previousなしにログを見ません。現在のコンテナは、作り直されたばかりで、まだ何も出力していません。空のログを見て「ログがない」と判断するのが、最もよくある無駄足です。
次の2つのラボで、これらを自分で作ってみます。