Kubernetes Pod Pending問題を理解する

By 清水 孝郎 - APRIL 14, 2022

SHARE:

本文の内容は、2022年4月14日にCarlos Arillaが投稿したブログUnderstanding Kubernetes pod pending problems(https://sysdig.com/blog/kubernetes-pod-pending-problems/)を元に日本語に翻訳・再構成した内容となっております。

Kubernetes ポッドのPendingは、成熟度が異なっても、どのクラスターにも偏在しています。

Kubernetesを使用している任意のDevOpsエンジニアに、彼らの悪夢を苦しめる最も一般的なエラーを特定するように尋ねると、PendingのPodを持つデプロイはリストのトップに近いです(おそらくCrashLoopBackOffに次ぐものです)。

アップデートをプッシュしようとして、それが止まっているのを見ると、DevOpsは不安になります。解決策がかなり簡単な場合でも、PodがPendingになっている原因を見つけ、適用すべき変更を理解することは重要です(Kubernetesのトラブルシューティングが些細なことであることはほとんどありません)。


この記事では、この問題を引き起こすさまざまな状況に光を当て、DevOpsチームが迅速に解決策を見つけ、何よりも可能な限り回避できるようにすることを目指します。

Kubernetes Pod Pendingの意味とは?

KubernetesのPodには、いくつかの異なるフェーズで構成されるライフサイクルがあります。

  • Podが作成されると、Pendingフェーズで開始されます。
  • Podがスケジュールされ、コンテナが開始されると、PodはRunningフェーズに変更されます。
ほとんどのPodは、PendingからRunningに移行するのに数秒しかかからず、その状態のまま人生の大半を過ごすことになります。

Status of a Kubernetes Pod, Pending, Running, Started, Failed and UnknownKubernetesのPodの状態、Pending、Running、Started、Failed、Unknown

ここまでで、PodはKubernetesクラスターに受け入れられています。しかし、1つ以上のコンテナがセットアップされ、実行可能な状態にはなっていない。これには、Podがスケジュールされるのを待っている時間や、ネットワーク経由でコンテナイメージをダウンロードしている時間などが含まれます。

PodがPendingからRunningの段階に進めない場合、ライフサイクルは停止し、進行を妨げている問題が修正されるまでPodは保持されます。

kubectlでPodをリストアップすると、Kubernetes PodのPending状況を示す出力が表示されます。

$ kubectl -n troubleshooting get pods
NAME                                           READY   STATUS    RESTARTS   AGE
stress-6d6cbc8b9d-s4sbh                        0/1     Pending   0          17s

Podが動かなくなり、問題を解決しない限り実行されません。

Kubernetes Pod Pendingの一般的な原因におけるトラブルシューティング

Podが実行できなくなる原因はいくつかありますが、主な3つの問題について説明します。

  • スケジューリングに問題がある: どのノードでもPodをスケジュールできない。
  • イメージの問題:コンテナイメージのダウンロードに問題がある。
  • 依存関係の問題:ポッドを実行するには、ボリューム、シークレット、またはconfig mapが必要です。
最初のものが最も一般的で、最後のものはほとんど見られません。それぞれのケースについて詳しく説明しましょう。

スケジューリングの問題でKubernetes PodがPendingになった場合

Road from pending to Running: Focus on Scheduling problems.PendingからRunningへの道:スケジューリングの問題に注目

Podが作成されると、Kubernetesクラスターが最初に行うことは、いずれかのノードでPodを実行するようにスケジューリングしようとすることです。このプロセスは多くの場合、実に高速で、Podはそれを実行するのに十分なリソースを持つノードに迅速に割り当てられます。

スケジュールするために、クラスターはPodの有効なリクエストを使用します(詳しくはPod evictionに関するこちらの投稿をご覧ください)。通常、Podは要求されていないリソースをより多く持つノードに割り当てられ、SLOに準拠した要求への返信に満ちた、幸せで素晴らしい人生を歩みます。

しかし、このプロセスが毎回うまくいくなら、この記事を読んでいないでしょう。クラスターがPodを割り当てられないようにする要因はいくつかあります。

最も一般的なものを確認してみましょう。

どのノードにも、Podを割り当てるのに十分なリソースがない

Kubernetesはスケジューリングのリクエストを使って、Podがノードに収まるかどうかを判断しています。リソースの実際の使用量は問題ではなく、他のPodによってすでにリクエストされたリソースのみが問題です。

メモリとCPUに対するPodの有効な要求に応じるのに十分な要求可能なリソースがある場合、Podはノードにスケジューリングされます。もちろん、そのノードが実行可能なPodの最大数に達していないことが条件です。

Three kubernetes nodes, all resources have been requested, so Pods cannot be scheduled and they stay as Kubernetes Pod Pending.3つのkubernetesノードでは、すべてのリソースが要求されているため、Podをスケジュールすることはできず、Kubernetes Pod Pendingとして残ります。

Podからすべての要件を満たすノードが存在しない場合、いくつかのリソースが解放されるまでKubernetes Pod Pendingの状態で保持されます。

スケジューリング不能なノード

さまざまな問題(ノードの圧力)または人間の行動(ノードのcordoned)により、ノードはスケジュール不可能な状態に変わることがあります。これらのノードは、その状態が変化するまで、どのPodもスケジュールしません。

Three kubernetes nodes, all have integrity problems, so Pods cannot be scheduled and they stay as Kubernetes Pod Pending.3つのkubernetesノード、すべてが整合性に問題があるため、Podはスケジュールできず、Kubernetes Pod Pendingのままです。

Taintとtoleration

Taintは、異なるノードに割り当てられるPodを制限することができるKubernetesの仕組みのことです。ノードにTaintがある場合、そのノードではtolerationが一致するPodのみが実行できるようになります。

この仕組みにより、ワークロードごとに異なるタイプのノード(GPU搭載ノード、CPU/メモリ比率の異なるノードなど)を用意するなど、Kubernetesの特殊な使い方ができるようになります。

Only one kubernetes node can be scheduled, but it has taints, only Pods meeting the taints can be scheduled. The rest stay as Kubernetes Pod Pending.スケジュールできるのは1つのKubernetesノードだけですが、そのノードにはTaintがあり、Taintを満たすPodのみがスケジュール可能です。残りはKubernetes Pod Pendingとして残ります。

すべての理由を個別に説明しても、スケジューリングの問題は、これらの問題の組み合わせで発生することが多いのです。通常、あるノードが満杯で、他のノードがTaintされているためにスケジュールできない、あるいはあるノードがメモリ圧迫のためにスケジュールできない、といったところでしょうか。

スケジューリングの問題が何であるかを調べるには、スケジューラーから生成されるPodに関するイベントを確認する必要があります。イベントには、ノードを割り当てられない理由の詳細が記述されています。イベントは、例えばkubectl describeで確認することができます。
$ kubectl -n troubleshooting describe pod stress-6d6cbc8b9d-s4sbh
Name:           stress-6d6cbc8b9d-s4sbh
Namespace:      troubleshooting
Priority:       0
Node:           <none>
Labels:         app=stress
                pod-template-hash=6d6cbc8b9d
Annotations:    <none>
Status:         Pending
IP:
IPs:            <none>
Controlled By:  ReplicaSet/stress-6d6cbc8b9d
Containers:
  stress:
    Image:      progrium/stress
    Port:       <none>
    Host Port:  <none>
    Args:
      --cpu
      1
      --vm
      2
      --vm-bytes
      150M
    Limits:
      cpu:     300m
      memory:  120000Mi
    Requests:
      cpu:        200m
      memory:     100000Mi
    Environment:  <none>
    Mounts:
      /var/run/secrets/kubernetes.io/serviceaccount from kube-api-access-snrww (ro)
Conditions:
  Type           Status
  PodScheduled   False
Volumes:
  kube-api-access-snrww:
    Type:                    Projected (a volume that contains injected data from multiple sources)
    TokenExpirationSeconds:  3607
    ConfigMapName:           kube-root-ca.crt
    ConfigMapOptional:       <nil>
    DownwardAPI:             true
QoS Class:                   Burstable
Node-Selectors:              <none>
Tolerations:                 node.kubernetes.io/not-ready:NoExecute op=Exists for 300s
                             node.kubernetes.io/unreachable:NoExecute op=Exists for 300s
Events:
  Type     Reason            Age                   From               Message
  ----     ------            ----                  ----               -------
  Warning  FailedScheduling  4m17s (x41 over 34m)  default-scheduler  0/5 nodes are available: 1 node(s) had taint {node-role.kubernetes.io/master: }, that the pod didn't tolerate, 4 Insufficient memory.

出力では、メッセージにある正確な理由を見ることができます:

0/5 nodes are available: 1 node(s) had taint {node-role.kubernetes.io/master: }, that the pod didn't tolerate, 4 Insufficient memory.

  • 1つのノードがTaintされています。
  • 4つのノードは十分な要求可能なメモリを持っていません。
この問題を解決するために、2つの選択肢があります。

現在実行中のワークロードを更新する場合、もう1つ重要な考慮すべき要素があります。アップグレードポリシーです。

このポリシーにより、Kubernetesは、更新の進行中にワークロードが通常よりも多くのPodを作成することを許可し、新しいPodを作成する間、古いPodをしばらく維持することができます。これは、ワークロードがしばらくの間、予想以上のリソースを要求できることを意味します。クラスターに十分な予備のリソースがない場合、更新はブロックされ、プロセスがブロック解除されるまで(またはロールバックタイムアウトによって更新が停止されるまで)、一部のPodがPendingのままになります。

イメージの問題でPod pending

ノードにPodが割り当てられると、kubeletはPod specのすべてのコンテナを起動しようとします。そのために、イメージをダウンロードして実行しようとします。

Road from pending to Running: Focus on Image Download problems.PendingからRunnningへの道:イメージダウンロードの問題に注目

イメージのダウンロードを妨げるエラーはいくつかあります。

  • イメージの名前が間違っている。
  • イメージのtagが間違っている。
  • リポジトリが間違っている。
  • リポジトリに認証が必要である。

この問題は通常、独立した問題として扱われるため、近日中に公開予定の別の記事でさらに説明します。

Kubernetes Podが依存関係の問題でPendingになっている

Road from pending to Running: Focus on Dependency problems.PendingからRunnningへの道:依存性の問題に注目

Podが起動する前に、kubeletは他のKubernetes要素との依存関係をすべて確認しようとします。これらの依存関係のうち1つでも満たすことができない場合、依存関係が満たされるまでPodはpending状態になります。

Example of dependencies for a Pod. A required Persisten Volume is not available, so the pod will stay as pending.Podの依存関係の例:必要なPersisten Volumeが利用できないため、Podはpending状態のままとなります。

この場合、kubectlではこのようにPodが表示されます:

$ kubectl -n mysql get pods
NAME                                       READY   STATUS              RESTARTS   AGE
mysql-0                                    0/1     ContainerCreating   0          97s

そして、イベントにおいては、次のようなものが確認できます:

Events:
  Type     Reason       Age                  From               Message
  ----     ------       ----                 ----               -------
  Normal   Scheduled    3m19s                default-scheduler  Successfully assigned mysql/mysql-0 to ip-172-20-38-115.eu-west-1.compute.internal
  Warning  FailedMount  76s                  kubelet            Unable to attach or mount volumes: unmounted volumes=[config], unattached volumes=[kube-api-access-gxjf8 data config]: timed out waiting for the condition
  Warning  FailedMount  71s (x9 over 3m19s)  kubelet            MountVolume.SetUp failed for volume "config" : configmap "mysql" not found

メッセージ列には、不足している要素を特定するのに十分な情報が記載されています。通常の原因は以下の通りです。

  • config mapまたはシークレットが作成されていないか、提供された名前が正しくない。
  • ボリュームが他のノードからまだリリースされていないため、そのノードにマウントできない。マウントされるボリュームは古いポッドと同じでなければならないため、これは特にステートフルセットを更新する処理で発生します。

まとめ

Kubernetesでワークロードを安全にデプロイし、アップデートするためには、PodがPendingフェーズに留まる理由を理解することが重要です。問題を素早く特定し、デプロイを進行させることができれば、頭痛の種を減らし、ダウンタイムを短縮することができます。


Sysdigを使用すると、この情報をすぐに利用できるため、Kubernetesのトラブルシューティングがさらに簡単になります。 今すぐ無料のSysdigMonitorトライアルに登録して、業界をリードするKubernetesモニタリング製品ですぐに詳細情報を入手してください。