Kubernetesの「FailedScheduling」エラーをデバッグする方法
ポッドのスケジューリングの問題は、最も一般的なKubernetesのエラーの一つです。新しいポッドがPending状態になり、理由がFailedSchedulingとなるのにはいくつかの理由があります。この状態のポッドはコンテナを起動しないため、アプリケーションを使用することができません。
スケジューリングの問題によって保留中のポッドは、通常、手動での介入なしには実行を開始しません。根本的な原因を調査し、クラスターを修正するために行動を取る必要があります。この記事では、この問題を診断し解決する方法を学び、ワークロードを立ち上げることができるようになります。
失敗したスケジューリングエラーの特定
Podは、クラスターに追加された後、短時間の間Pending状態を示すのは普通です。Kubernetesは、コンテナインスタンスをノードにスケジュールし、そのノードがレジストリからイメージをプルする必要があります。Podのスケジュール失敗の最初の兆候は、通常の起動期間が経過した後もPendingとして表示され続けるときです。ステータスを確認するには、Kubectlのコマンドを実行できます。
get podsコマンド :
kubectl get pods
NAME READY STATUS RESTARTS AGE
demo-pod 0/1 Pending 0 4m05s
demo-podは4分以上経過していますが、まだPending状態にあります。ポッドは通常、コンテナの起動にこれほど時間がかかりませんので、Kubernetesが何を待っているのか調査を始めるべき時です。
次の診断ステップは、describe podコマンドを使用してPodのイベント履歴を取得することです。
kubectl describe pod demo-pod
...
Events:
Type Reason Age From Message
---- ------ ---- ---- -------
...
Warning FailedScheduling 4m default-scheduler 0/4 nodes are available: 1 Too many pods, 3 Insufficient cpu.
イベント履歴は、FailedSchedulingエラーが長引くPending状態の理由であることを確認します。このイベントは、Kubernetesがクラスター内のワーカーノードに必要な数のPodを割り当てられないときに報告されます。
イベントのメッセージは、現在スケジュールが不可能な理由を明らかにしています:クラスターには4つのノードがありますが、いずれもPodを受け入れることができません。3つのノードはCPU容量が不足しており、もう1つのノードは受け入れられるPodの数に上限に達しています。
スケジューリング失敗エラーおよび類似の問題の理解
Kubernetesは、リソースに余裕のあるノードにのみポッドをスケジュールできます。CPUやメモリのキャパシティが尽きたノードには、これ以上ポッドを受け入れることができません。また、ポッドが明示的にノードが提供できる以上のリソースを要求すると、スケジューリングに失敗することがあります。これにより、クラスタの安定性が維持されます。
Kubernetesのコントロールプレーンは、クラスター内のノードにすでに割り当てられたPodを認識しています。この情報を使用して、新しいPodを受け取ることができるノードのセットを決定します。使用可能な候補がない場合、スケジューリングエラーが発生し、Podはキャパシティが解放されるまでPendingのままになります。
Kubernetesは他にもPodをスケジュールできない理由があります。ノードが十分なシステムリソースを持っていても、Podをホストするのに不適格と見なされる方法はいくつかあります。
- ノードは、メンテナンス作業の前に新しいポッドを受信しないように管理者によって制限された可能性があります。
- ノードはポッドのスケジューリングを妨げる効果で汚染されている可能性があります。対応する耐性がない限り、あなたのポッドはそのノードによって受け入れられません。
- あなたのPodは、ノード上ですでにバインドされている
hostPortをリクエストしている可能性があります。ノードは1回に1つのPodに対して特定のポート番号のみを提供できます。 - あなたのPodは、特定のラベルを持つノードにスケジュールする必要があることを意味する
nodeSelectorを使用している可能性があります。そのラベルがないノードは適格ではありません。 - ポッドとノードのアフィニティおよびアンチアフィニティが満たされない可能性があり、新しいポッドを受け入れることを妨げるスケジューリングの競合が発生することがあります。
- Podには特定のノードをスケジュールするための
nodeNameフィールドがあるかもしれません。そのノードがオフラインまたはスケジュール不可能な場合、Podは保留状態のままとなります。
Kubernetesスケジューラーであるkube-schedulerの責任は、これらの条件を検討し、新しいPodを受け入れることができるノードのセットを特定することです。ノードのいずれも基準を満たさない場合、FailedSchedulingイベントが発生します。
失敗したスケジューリング状態の解決
FailedScheduling イベントの横に表示されるメッセージは、クラスタ内の各ノードがポッドを受け取れなかった理由を示しています。この情報を使用して、問題に対処することを始めることができます。上記の例では、クラスタには4つのポッドがあり、そのうち3つはCPU制限に達していて、1つはポッド数制限を超えていました。
この場合、クラスタの容量が根本的な原因です。ハードウェアの消費問題を解決するために、新しいノードを追加してクラスタをスケールアップできます。これにより、追加の柔軟性を提供するリソースが追加されますが、コストも増加するため、まずクラスタ内に冗長なポッドがないか確認する価値があります。未使用のリソースを削除することで、新しいリソースのための容量が確保されます。
各ノードで利用可能なリソースを describe node コマンドを使用して確認できます:
kubectl describe node demo-node
...
Allocated resources:
(Total limits may be over 100 percent, i.e., overcommitted.)
Resource Requests Limits
-------- -------- ------
cpu 812m (90%) 202m (22%)
memory 905Mi (57%) 715Mi (45%)
ephemeral-storage 0 (0%) 0 (0%)
hugepages-2Mi 0 (0%) 0 (0%)
このノードのポッドは、すでに利用可能なメモリの57%を要求しています。もし新しいポッドが自身のために1 Giのメモリを要求した場合、ノードはスケジューリングのリクエストを受け入れることができなくなります。各ノードのこの情報を監視することで、クラスターが過剰にプロビジョニングされているかどうかを評価するのに役立ちます。ノードの1つが不健康になり、そのワークロードを別のノードに再スケジュールしなければならない場合に備えて、余剰のキャパシティを持つことが重要です。
スケジュール可能なノードが存在しないためにスケジュールの失敗が発生した場合、FailedSchedulingイベントに次のようなメッセージが表示されます:
0/4 nodes are available: 4 node(s) were unschedulableスケジューリングが無効になっているためにスケジュールできないノードは、そのステータスフィールドにSchedulingDisabledを含みます:
kubectl get nodes
NAME STATUS ROLES AGE VERSION
node-1 Ready,SchedulingDisabled control-plane,master 26m v1.23.3
ノードの遮断を解除して、新しいPodを受け入れられるようにすることができます:
kubectl uncordon node-1
node/node-1 uncordoned
ノードがコルドンされておらず、十分なリソースがある場合、スケジューリングのエラーは通常、汚染やPodのnodeSelectorフィールドの誤りによって引き起こされます。nodeSelectorを使用している場合は、タイプミスがないこと、指定したラベルを持つPodがクラスターに存在することを確認してください。
ノードが汚染されている場合は、Podのマニフェストに対応する耐性が含まれていることを確認してください。例として、以下のようなノードが汚染されており、demo-taint: allowの耐性を持たない限りPodはスケジュールされないことを示します:
kubectl taint nodes node-1 demo-taint=allow:NoScheduleポッドマニフェストを修正して、ノードにスケジュールできるようにします:
spec:
tolerations:
- key: demo-taint
operator: Equal
value: allow
effect: NoSchedule
KubernetesのFailedScheduling状態を引き起こした問題を解決することで、保留中のPodのスケジューリングを再開することができます。コントロールプレーンがノードの変更を検出した後、彼らは自動的にすぐに実行を開始します。Podのマニフェストにおける不正確なアフィニティやnodeSelectorフィールドによる問題でない限り、手動でPodを再起動または再作成する必要はありません。
要約
FailedScheduling エラーは、Kubernetes がクラスター内のいずれのノードにも新しい Pod を配置できないときに発生します。これはしばしば、既存のノードが CPU、メモリ、ディスクなどのハードウェアリソースが不足しているためです。その場合、クラスターをスケールアップして追加のノードを含めることで問題を解決できます。
ポッドが、クラスター内で現在使用可能なノードによって満たすことができない親和性、反親和性、ノードセレクターを指定すると、スケジューリングの失敗が発生します。コーディングされ、汚染されたノードは、Kubernetesに利用可能なオプションをさらに減少させます。この種の問題は、マニフェスト内のラベルのタイプミスをチェックし、もはや必要のない制約を削除することで対処できます。
