壊してから直す
目標
実際の現場で最もよく出会う5つの障害を、自分で作って、自分で直しながら、症状から原因へ下りていく順序を、体に刻みます。
なぜ重要なのか
トラブルシューティングは、CKAの配点の30%で、最も大きなドメインです。しかし、直したものだけを見ても、学べることはありません。そのため、このラボは、壊れた状態を受講生が作り、症状をファイルに残し、そのあとに直す順序で設計しました。各ステップの採点は、直った結果だけでなく、壊れていたという証拠もあわせて見ます。
症状を残す習慣そのものが、実務の技術です。障害が終われば、証拠は消えます。原因をあとで説明するには、その瞬間のイベントと状態を残しておく必要があります。
前のステップで作ったクラスターの状態(cordonされたノード、テイントされたノード)は、あとのステップにもそのまま残ります。最後の問題は、その状態を正確に覚えていてはじめて解けます。
ステップ
- ネームスペース
cka-brokenを作成し、Deploymentweb(レプリカ2)を、イメージnginx:1.99-nonexistentで作成してください。その誤ったイメージタグが見える出力を/root/cka-broken/bad-image.txtに保存したあと、イメージをnginx:1.27に入れ替えて、2/2 Readyにしてください。Deploymentは削除せず、イメージだけを直してください。 - Pod
heavy(イメージnginx:1.27)を、requestscpu: 500、memory: 2000Giで作成してください。Pendingになることを確認して、その理由が含まれた出力を/root/cka-broken/pending.txtに保存してください。heavyは削除せずに残したまま、Deploymentheavy-fixed(レプリカ1、イメージnginx:1.27、requestscpu: 500m、memory: 2000Mi)を作成して、1/1 Readyにしてください。 - サービス
api-svc(セレクターapp=api、port 80)を作成し、Deploymentapiを、Podラベルとセレクターをapp=api-v2と間違えて作成してください。api-svcのエンドポイントが空であることを/root/cka-broken/svc-before.txtに保存したあと、apiをラベルapp=apiに正して、レプリカ2をReadyにしてください。サービスのセレクターはapp=apiのままにしてください。 - ネームスペース
cka-broken-quotaを作成し、ResourceQuotacka-quotaをpods: "2"、requests.cpu: "1"で作成してください。Deploymentq-app(レプリカ4、イメージnginx:1.27、requestscpu: 200m)を作成すると、一部だけが起動します。exceeded quotaが見えるイベントを/root/cka-broken/quota.txtに保存したあと、クォータのpodsを5に上げて、4/4 Readyにしてください。 cka-brokenにDeploymentcritical(レプリカ2、イメージnginx:1.27、Podラベルapp=critical)とPDBcritical-pdb(セレクターapp=critical、minAvailable: 2)を作成してください。lab-node-2をdrainしてみて、塞がれるメッセージを/root/cka-broken/pdb.txtに保存したあと、minAvailableを1に下げて、lab-node-2をcordon + drainして完全に空にしてください。lab-node-0に、ラベルdisktype=ssdとテイントmaintenance=true:NoScheduleを設定してください。Podneeds-toleration(イメージnginx:1.27、nodeSelectordisktype=ssd、トレラレーションなし)を作成してPendingを確認し、理由を/root/cka-broken/taint.txtに保存してください。needs-tolerationは残したまま、Podneeds-toleration-fixedを、同じnodeSelectorにトレラレーションまで付けて作成し、lab-node-0に配置してください。- Pod
data-app(イメージnginx:1.27)が、PVCapp-dataを/dataにマウントするように作成してください。PVCがまだなく、起動できない理由を/root/cka-broken/pvc.txtに保存したあと、PVcka-fix-pv(1Gi、RWO、storageClassNamecka-fix、hostPath/mnt/cka-fix)とPVCapp-data(1Gi、RWO、cka-fix)を作成してBoundさせ、data-appがRunningになるようにしてください。 - Deployment
recovered(レプリカ4、イメージnginx:1.27、Podラベルapp=recovered)をcka-brokenに作成してください。requestsはcpu: 100m、memory: 128Mi、maintenance=true:NoScheduleのトレラレーション、topologySpreadConstraintsはmaxSkew 1 / topologyKeykubernetes.io/hostname/ whenUnsatisfiableScheduleAnyway/ labelSelectorapp=recoveredです。4/4 Readyにして、直した5つの問題を/root/cka-broken/summary.mdにまとめてください。このファイルには、image、taint、selector、quota、pdbの5つの語がすべて入っている必要があります。
参考
- スケジュールの失敗理由は、
kubectl describe pod <이름> -n cka-brokenのEventsの節にあります(プレースホルダーはPod名です)。 - クォータの超過は、Podではなく、
kubectl describe rsやkubectl get events -n cka-broken-quotaで見えます。 - drainは、
--ignore-daemonsets --delete-emptydir-data --force --timeout=60sを付けると、進行が楽になります。 - よくあるミス1: 証拠ファイルを残す前に、先に直してしまうことです。順序がそのまま採点項目です。
- よくあるミス2: ステップ8で、トレラレーションを忘れることです。
lab-node-2はcordon、lab-node-0はテイントの状態なので、使えるノードが1つしか残っていません。
誤ったイメージタグ
ネームスペースcka-brokenを作成し、Deploymentweb(レプリカ2)を、イメージnginx:1.99-nonexistentで作成してください。その誤ったイメージタグが見える出力を/root/cka-broken/bad-image.txtに保存したあと、イメージをnginx:1.27に入れ替えて、2/2 Readyにしてください。Deploymentは削除せず、イメージだけを直してください。
まず、誤ったタグで作成して証拠を残してから、イメージだけを入れ替えてください。Deploymentを削除して作り直すと、問題のリビジョンが消えて、採点で引っかかります。
リソース要求の単位のミス
Podheavy(イメージnginx:1.27)を、requestscpu: 500、memory: 2000Giで作成してください。Pendingになることを確認して、その理由が含まれた出力を/root/cka-broken/pending.txtに保存してください。heavyは削除せずに残したまま、Deploymentheavy-fixed(レプリカ1、イメージnginx:1.27、requestscpu: 500m、memory: 2000Mi)を作成して、1/1 Readyにしてください。
cpuの値でmを抜かすと、ミリコアではなくコアになります。describeのEventsの節に、スケジューラーがなぜ失敗したかが、そのまま出ます。
サービスとラベルがずれたDeployment
サービスapi-svc(セレクターapp=api、port 80)を作成し、Deploymentapiを、Podラベルとセレクターをapp=api-v2と間違えて作成してください。api-svcのエンドポイントが空であることを/root/cka-broken/svc-before.txtに保存したあと、apiをラベルapp=apiに正して、レプリカ2をReadyにしてください。サービスのセレクターはapp=apiのままにしてください。
Deploymentのspec.selectorは不変です。間違って作成したなら、修正ではなく作り直す必要があります。サービス側のセレクターには、触れないでください。
ResourceQuotaの超過
ネームスペースcka-broken-quotaを作成し、ResourceQuotacka-quotaをpods: "2"、requests.cpu: "1"で作成してください。Deploymentq-app(レプリカ4、イメージnginx:1.27、requestscpu: 200m)を作成すると、一部だけが起動します。exceeded quotaが見えるイベントを/root/cka-broken/quota.txtに保存したあと、クォータのpodsを5に上げて、4/4 Readyにしてください。
クォータに引っかかったPodは、Podではなく、ReplicaSetのイベントとして現れます。クォータを上げる前に、そのイベントを先に保存してください。
PDBで塞がれたdrain
cka-brokenにDeploymentcritical(レプリカ2、イメージnginx:1.27、Podラベルapp=critical)とPDBcritical-pdb(セレクターapp=critical、minAvailable: 2)を作成してください。lab-node-2をdrainしてみて、塞がれるメッセージを/root/cka-broken/pdb.txtに保存したあと、minAvailableを1に下げて、lab-node-2をcordon + drainして完全に空にしてください。
レプリカ2でminAvailable 2なら、1つも外せません。--forceで押し切る代わりに、PDBが何を守ろうとしているのかを、もう一度計算してください。
トレラレーションの欠落
lab-node-0に、ラベルdisktype=ssdとテイントmaintenance=true:NoScheduleを設定してください。Podneeds-toleration(イメージnginx:1.27、nodeSelectordisktype=ssd、トレラレーションなし)を作成してPendingを確認し、理由を/root/cka-broken/taint.txtに保存してください。needs-tolerationは残したまま、Podneeds-toleration-fixedを、同じnodeSelectorにトレラレーションまで付けて作成し、lab-node-0に配置してください。
NoScheduleテイントは、新しいPodだけを防ぎ、すでに起動しているPodには手を触れません。問題のPodは削除せず、残しておいてください。
存在しないPVC
Poddata-app(イメージnginx:1.27)が、PVCapp-dataを/dataにマウントするように作成してください。PVCがまだなく、起動できない理由を/root/cka-broken/pvc.txtに保存したあと、PVcka-fix-pv(1Gi、RWO、storageClassNamecka-fix、hostPath/mnt/cka-fix)とPVCapp-data(1Gi、RWO、cka-fix)を作成してBoundさせ、data-appがRunningになるようにしてください。
先にPodを作成して失敗を確認してから、ボリュームを作成してください。PVCが結び付くと、スケジューラーがそのPodを再び試すので、少し待てばよいです。
総合: 残ったクラスターで復旧デプロイをする
Deploymentrecovered(レプリカ4、イメージnginx:1.27、Podラベルapp=recovered)をcka-brokenに作成してください。requestsはcpu: 100m、memory: 128Mi、maintenance=true:NoScheduleのトレラレーション、topologySpreadConstraintsはmaxSkew 1 / topologyKeykubernetes.io/hostname / whenUnsatisfiableScheduleAnyway / labelSelectorapp=recoveredです。4/4 Readyにして、直した5つの問題を/root/cka-broken/summary.mdにまとめてください。このファイルには、image、taint、selector、quota、pdbの5つの語がすべて入っている必要があります。
今このクラスターには、cordonされたノードとテイントされたノードが、1つずつあります。どちらかを使うには何が必要かを計算してから、デプロイしてください。