【解決】 Kubernetes FailedScheduling の解決方法と原因 | Kubernetes トラブルシューティング

Kubernetes環境で「FailedScheduling」というエラーに直面しましたか?ご安心ください、これは多くのKubernetesユーザーが経験する一般的な問題の一つです。このエラーは、PodがKubernetesクラスタ内のどのノードにも適切に配置(スケジューリング)できなかったことを意味します。ですが、ほとんどの場合、適切な手順を踏めば速やかに解決できます。

この記事では、Windowsユーザーの方向けに、この厄介なエラーの原因を特定し、最も迅速に解決するための具体的な手順をPowerShell/Cmdコマンドを交えて解説します。結論から申し上げると、ほとんどの場合、リソース不足かTaint/Tolerationの設定ミスが原因です。焦らず、以下の手順を試してみてください。

1. Kubernetes FailedScheduling とは?(概要と緊急度)

FailedSchedulingは、KubernetesがPodをクラスタ内の利用可能なノードに配置しようとしたものの、何らかの理由でその試みが失敗したことを示すステータスです。

具体的には、Podが要求するCPU、メモリ、その他のリソースがどのノードにも不足している場合や、ノードに設定された特定の制約(Taint)とPodが許容する制約(Toleration)が一致しない場合などに発生します。このエラーが発生すると、対象のPodは「Pending」状態のままで起動せず、そのPodが提供するサービスは利用できません。

サービスによっては緊急度が高い問題となりますが、多くの場合、原因は比較的単純であり、適切な対処をすれば短時間で解決可能です。まずは落ち着いて、次に示す「最速の解決策」を試してみましょう。

2. 【最速】今すぐ試すべき解決策

FailedSchedulingエラーが発生したPodを特定し、そのPodのイベントログを確認することが、原因を特定し解決への道を切り開く最も速い方法です。まずは、以下のコマンドでエラーの詳細を確認しましょう。

解決策1:Podのイベントログから原因メッセージを確認する

エラーが発生しているPodの名前がわかっている場合、以下のkubectl describeコマンドを実行して、Podのイベントログを確認します。これにより、スケジューリングに失敗した具体的な理由が示されます。

kubectl describe pod <Pod名> -n <Namespace名>

実行例:

kubectl describe pod my-nginx-pod-xxxxxx -n default

このコマンドの出力の「Events」セクションに注目してください。FailedSchedulingイベントの後に、スケジューラがPodを配置できなかった具体的な理由が示されます。よくあるメッセージの例は以下の通りです。

  • リソース不足の場合:
    0/3 nodes are available: 3 Insufficient cpu, 3 Insufficient memory.
    (3つのノード全てでCPUまたはメモリが不足していることを示します。)
  • Taint/Tolerationの不一致の場合:
    0/3 nodes are available: 3 node(s) had untolerated taint {key: "dedicated", value: "test", effect: "NoSchedule"}.
    (特定のTaintを持つノードがあり、PodがそのTaintを許容するTolerationを持っていないことを示します。)

このメッセージに基づき、以下の簡単な対処を試みてください。

もし「Insufficient cpu」や「Insufficient memory」と表示されたら:

これは、クラスタ内のどのノードも、Podが要求するCPUやメモリのリソースを満たせないことを意味します。最も手軽な一時的な解決策は、そのPodのリソース要求を緩和するか、クラスタ内の別のPodを削除してリソースを解放することです。

  • Podのリソース要求を一時的に減らす(推奨はしませんが緊急時には有効):
    PodのYAMLファイルを編集し、resources.requestscpumemoryの値を減らします。その後、Podを再作成します。

    kubectl edit pod <Pod名> -n <Namespace名>

    注意: kubectl editは一時的な対処であり、DeploymentなどのコントローラによってPodが再作成されると元の設定に戻ります。恒久的な変更には、Deployment等のYAMLファイルを直接編集してください。

  • 他の不要なPodを削除してリソースを解放する:
    クラスタ内で現在動作しているが重要度の低い他のPodがあれば、それらを一時的に削除してリソースを解放し、問題のPodがスケジューリングされるスペースを作ります。

    kubectl get pods -A # 全てのnamespaceのPodを確認
    kubectl delete pod <削除したいPod名> -n <Namespace名>
  • ノードの現在のリソース使用状況を確認する:
    どのノードがどれくらいリソースを使用しているかを確認し、特定のノードに余裕がないか調べます。

    kubectl top node

    このコマンドは、ノードごとのCPUとメモリの使用率を表示します。リソースに余裕のあるノードがない場合、ノードの増強を検討する必要があります。

もし「node(s) had untolerated taint」と表示されたら:

これは、特定のノードに設定されたTaint(Podの配置を制限するマーカー)を、Podが許容するToleration(Taintを許容する設定)を持っていないためにスケジューリングできなかったことを意味します。

  • PodにTolerationを追加する:
    問題のPodのYAMLファイル(通常はDeploymentなどのコントローラのYAML)に、該当するTaintを許容するTolerationを追加します。

    # PodのYAMLファイル(例: Deployment)に以下を追加
    apiVersion: apps/v1
    kind: Deployment
    metadata:
      name: my-app
    spec:
      template:
        spec:
          tolerations:
          - key: "dedicated"
            operator: "Equal"
            value: "test"
            effect: "NoSchedule"
          # ...他のPod設定...
    

    YAMLファイルを編集したら、kubectl apply -f <ファイル名.yaml>で適用し、Podの再作成を待ちます。

  • ノードからTaintを一時的に削除する(緊急時またはテスト時):
    これはクラスタ全体に影響を与える可能性があるため、注意して行ってください。特定のノードからTaintを削除することで、そのノードにPodがスケジューリングされるようになります。

    kubectl taint nodes <ノード名> <Taintキー>=<Taint値>:<Effect>-

    実行例:

    kubectl taint nodes my-node-1 dedicated=test:NoSchedule-

    末尾の-はTaintを削除する指示です。

3. Kubernetes FailedScheduling が発生する主要な原因(複数)

上記で確認したEventsセクションのメッセージは、FailedSchedulingの具体的な原因を示唆しています。主な原因は以下の通りです。

3.1. CPU/メモリリソースの不足

クラスタ内のどのノードも、Podがresources.requestsで指定したCPUまたはメモリを満たせない場合に発生します。

  • Insufficient CPU/Memory: ノードのキャパシティが、Podの要求するリソースに対して単純に不足している状態です。
  • Overcommitment: ノードに既に多くのPodが配置されており、見かけ上リソースがあっても、実際に利用可能なリソースが不足している場合があります。

3.2. TaintとTolerationの不一致

ノードに特定のTaintが設定されているにもかかわらず、PodがそのTaintを許容するTolerationを持っていない場合に発生します。

  • ノードの役割分離: 特定のワークロード(例: GPUを使うPod、管理者用Pod)専用のノードにTaintを設定し、一般的なPodが配置されないようにしているケース。
  • ノードのメンテナンス: ノードをメンテナンスモードにするためにTaintを設定しているケース。

3.3. NodeSelectorやNodeAffinityの不一致

PodがnodeSelectornodeAffinityを使って特定のノードのラベルを要求しているが、クラスタ内にそのラベルを持つノードが存在しない、または条件を満たすノードがない場合に発生します。

  • ラベルのタイプミス: PodのnodeSelectorで指定したラベルキーや値が、実際のノードのラベルと一致していない。
  • 適切なノードの不足: 特定の要件を持つノード(例: 特定のハードウェア、OS)がクラスタ内に存在しない。

3.4. ポート競合

PodがhostPortを使用している場合、ターゲットノードでそのポートがすでに他のPodやプロセスによって使用されているとスケジューリングできません。

3.5. クラスタの状態異常

ノードがNotReady状態であったり、ネットワークの問題でノードとマスターが適切に通信できていない場合も、Podはスケジューリングされません。

4. Kubernetesで恒久的に再発を防ぐには

一時的な解決策だけでなく、FailedSchedulingエラーの再発を防ぐための恒久的な対策を講じることが重要です。

4.1. リソース管理の最適化

  • 適切なResource Requests/Limitsの設定: PodのYAMLファイルでresources.requestsresources.limitsを正確に設定します。requestsはスケジューリング時に使用され、limitsはPodが利用できる最大リソースを制限します。これにより、ノードのリソースを適切に予約し、過剰な消費を防ぎます。
    resources:
      requests:
        cpu: "200m"  # 0.2 CPUコアを要求
        memory: "256Mi" # 256MBメモリを要求
      limits:
        cpu: "500m"  # 最大0.5 CPUコアまで
        memory: "512Mi" # 最大512MBメモリまで
    
  • クラスタオートスケーラー (Cluster Autoscaler) の導入: クラスタのリソースが不足した場合に、自動的にノードを追加する仕組みを導入することで、リソース不足によるスケジューリング失敗を防ぎます。
  • 垂直Podオートスケーラー (Vertical Pod Autoscaler: VPA) または水平Podオートスケーラー (Horizontal Pod Autoscaler: HPA) の利用:
    • VPA: Podの過去のリソース使用状況に基づいて、Podのリソース要求・制限を動的に調整します。
    • HPA: PodのCPU使用率などのメトリクスに基づいて、Podのレプリカ数を自動的に増減させます。
  • 監視とアラート: PrometheusやGrafanaなどの監視ツールを導入し、ノードやPodのリソース使用率を常に監視します。リソース枯渇の兆候を早期に検知し、アラートを設定することで、問題が顕在化する前に対応できます。

4.2. TaintとToleration戦略の見直し

  • 明確なTaintポリシーの定義: どのようなノードに、どのような目的でTaintを設定するのかを明確なポリシーとして定義します。
  • Tolerationの適切な適用: 必要なPodにのみ適切なTolerationを設定し、意図しないノードにPodが配置されないようにします。
  • Taintの定期的な確認: 不要になったTaintがノードに残っていないか定期的に確認し、クリーンアップします。

4.3. ノードの増強と健全性の維持

  • ノードのキャパシティ計画: 将来的なワークロードの増加を見越して、ノードのCPU、メモリ、ストレージのキャパシティを計画的に増強します。
  • ノードの健全性監視: ノードがReady状態であるか、ディスク容量が十分であるかなど、ノードの健全性を継続的に監視します。問題のあるノードは速やかに修復または交換します。

4.4. NodeSelector/NodeAffinityの正確な利用

  • ラベルの一貫性: ノードに適用するラベルは一貫性を持たせ、Podが要求するラベルと正確に一致するようにします。
  • Affinity/Anti-affinityの活用: 複雑なスケジューリング要件がある場合は、nodeAffinitypodAffinity/podAntiAffinityを利用して、Podの配置をより柔軟に制御します。

これらの対策を講じることで、FailedSchedulingエラーの発生を大幅に減らし、安定したKubernetesクラスタ運用が可能になります。問題が解決しない場合は、Kubernetesの公式ドキュメントやコミュニティフォーラムも参考にしてみてください。