Amazon EKS でポッドのステータスをトラブルシューティングする方法を教えてください。

最終更新日: 2021 年 12 月 8 日

Amazon Elastic Compute Cloud (Amazon EC2) インスタンスまたはマネージドノードグループで実行されている Amazon Elastic Kubernetes Service (Amazon EKS) ポッドがスタックしています。Running 状態のポッドを取得したいと考えています。

解決方法

重要: 次の手順は、Amazon EC2 インスタンスまたはマネージドノードグループで起動したポッドにのみ適用されます。これらの手順は、AWS Fargate で起動したポッドには適用されません。

ポッドのステータスを確認する

1.    Pod のステータスを取得するには、以下のコマンドを実行します。

$ kubectl get pod

2.    ポッドのイベント履歴から情報を取得するには、次のコマンドを実行します。

$ kubectl describe pod YOUR_POD_NAME

注: 以下の手順で説明するコマンドの例は、デフォルトの名前空間にあります。他の名前空間については、コマンドに -n YOURNAMESPACE を付けます。

3.    ポッドが Pending 状態ポッドが Waiting 状態、または ポッドが CrashLoopBackOff 状態 といったポッドのステータスに基づいて、以下のいずれかのセクションの手順を実行します。

ポッドが Pending 状態にある場合

Pending状態のポッドは、ノードにスケジュールできません。これは、リソースの不足、または hostPort の使用が原因で発生する可能性があります。詳細については、Kubernetes ドキュメントポッドのフェーズを参照してください。

ワーカーノードで利用可能なリソースが不足している場合は、不要なポッドを削除することを検討してください。また、ワーカーノードにリソースを追加することもできます。Kubernetes Cluster Autoscalerを使用すると、クラスター内のリソースが不足しているときにワーカーノードグループを自動的にスケーリングできます。

CPU 不足:

$ kubectl describe pod frontend-cpu                               
Name:         frontend-cpu
Namespace:    default
Priority:     0
Node:         <none>
Labels:       <none>
Annotations:  kubernetes.io/psp: eks.privileged
Status:       Pending
...
Events:
  Type     Reason            Age                 From               Message
  ----     ------            ----                ----               -------
  Warning  FailedScheduling  22s (x14 over 13m)  default-scheduler  0/3 nodes are available: 3 Insufficient cpu.

メモリ不足:

$ kubectl describe pod frontend-memory
Name:         frontend-memory
Namespace:    default
Priority:     0
Node:         <none>
Labels:       <none>
Annotations:  kubernetes.io/psp: eks.privileged
Status:       Pending
...
Events:
  Type     Reason            Age                 From               Message
  ----     ------            ----                ----               -------
  Warning  FailedScheduling  80s (x14 over 15m)  default-scheduler  0/3 nodes are available: 3 Insufficient memory.

Pod に hostPort を定義している場合は、次のベストプラクティスに従ってください。

  • (B) hostIPhostPortprotocol の組み合わせは一意でなければならないため、必要でない限り、hostPort を指定しないでください。
  • (C) hostPort を指定する場合は、ワーカーノードと同じ数のポッドをスケジュールします。

注:Pod を hostPort にバインドするときに Pod をスケジュールできる場所の数は限られています。

次の例は、Pending 状態にある frontend-port-77f67cff67-2bv7w の describe コマンドの出力を示しています。要求されたホストポートはクラスター内のワーカーノードで使用できないため、Pod はスケジュール外です。

ポート使用不可:

$ kubectl describe pod frontend-port-77f67cff67-2bv7w                                            
Name:           frontend-port-77f67cff67-2bv7w
Namespace:      default
Priority:       0
Node:           <none>
Labels:         app=frontend-port
                pod-template-hash=77f67cff67
Annotations:    kubernetes.io/psp: eks.privileged
Status:         Pending
IP:             
IPs:            <none>
Controlled By:  ReplicaSet/frontend-port-77f67cff67
Containers:
  app:
    Image:      nginx
    Port:       80/TCP
    Host Port:  80/TCP
...
Events:
  Type     Reason            Age                  From               Message
  ----     ------            ----                 ----               -------
  Warning  FailedScheduling  11s (x7 over 6m22s)  default-scheduler  0/3 nodes are available: 3 node(s) didn't have free ports for the requested pod ports.

Pod が許可できないテイントがノードにあるために Pod がスケジュールできない場合、出力例は次のようになります。

$ kubectl describe pod nginx                                                  
Name:         nginx
Namespace:    default
Priority:     0
Node:         <none>
Labels:       run=nginx
Annotations:  kubernetes.io/psp: eks.privileged
Status:       Pending
...
Events:
  Type     Reason            Age                  From               Message
  ----     ------            ----                 ----               -------
  Warning  FailedScheduling  8s (x10 over 9m22s)  default-scheduler  0/3 nodes are available: 3 node(s) had taint {key1: value1}, that the pod didn't tolerate.

以下のコマンドでノードのテイントを確認することができます。

$ kubectl get nodes -o custom-columns=NAME:.metadata.name,TAINTS:.spec.taints             
NAME                                                TAINTS
ip-192-168-4-78.ap-southeast-2.compute.internal     [map[effect:NoSchedule key:key1 value:value1]]
ip-192-168-56-162.ap-southeast-2.compute.internal   [map[effect:NoSchedule key:key1 value:value1]]
ip-192-168-91-249.ap-southeast-2.compute.internal   [map[effect:NoSchedule key:key1 value:value1]]

ノードテイントを保持したい場合は、 PodSpec でポッドの許容範囲を指定できます。詳細については、 Kubernetes ドキュメントの「コンセプト」セクションを参照してください

- または -

taint 値の最後に- を追加して、ノード taint を削除します。

$ kubectl taint nodes NODE_Name key1=value1:NoSchedule-

前の手順を試してもポッドがまだ Pending 状態にある場合は、追加のトラブルシューティングセクションの手順を実行してください。

コンテナは待機中状態です。

Waiting 状態のコンテナはワーカーノード (EC2 インスタンスなど) でスケジュールされていますが、そのノードでは実行できません。

Docker イメージが正しくないか、リポジトリ名が間違っているため、コンテナが Waiting 状態にある可能性があります。または、イメージが存在しないか、アクセス許可がないため、ポッドが Waiting 状態にある可能性があります。

Docker イメージまたはリポジトリ名が正しくない場合は、次の手順を実行してください。

1.    Docker Hub、Amazon Elastic Container Registry (Amazon ECR)、または別のコンテナイメージリポジトリにログインして、イメージ名とリポジトリ名が正しいことを確認します。

2.    リポジトリからのリポジトリまたはイメージを、ポッド仕様で指定されたリポジトリ名またはイメージ名と比較します。

イメージが存在しない場合、またはアクセス許可が不足している場合は、以下の手順を実行します。

1.    指定されたイメージがリポジトリで使用可能であり、イメージをプルできるように正しいアクセス許可が設定されていることを確認します。

2.    イメージのプルが可能であることを確認し、一般的なネットワークとリポジトリのアクセス許可の問題を防ぐには、手動でイメージをプルします。Docker を使用して Amazon EKS ワーカーノードからイメージをプルする必要があります。以下はその例です。

$ docker pull yourImageURI:yourImageTag

3.    イメージが存在することを確認するには、Docker Hub または Amazon ECR にイメージとタグの両方が存在することを確認します。

注: Amazon ECR を使用している場合、リポジトリポリシーで NodeInstanceRole のイメージプルが許可されていることを確認します。または、AmazonEC2ContainerRegistryReadOnly ロールがポリシーにアタッチされていることを確認します。

次の例は、イメージプルエラーのため、ポッドが Pending 状態、そしてコンテナが Waiting 状態にあることを示しています。

$ kubectl describe po web-test

Name:               web-test
Namespace:          default
Priority:           0
PriorityClassName:  <none>
Node:               ip-192-168-6-51.us-east-2.compute.internal/192.168.6.51
Start Time:         Wed, 22 Jul 2021 08:18:16 +0200
Labels:             app=web-test
Annotations:        kubectl.kubernetes.io/last-applied-configuration:
                      {"apiVersion":"v1","kind":"Pod","metadata":{"annotations":{},"labels":{"app":"web-test"},"name":"web-test","namespace":"default"},"spec":{...
                    kubernetes.io/psp: eks.privileged
Status:             Pending
IP:                 192.168.1.143
Containers:
  web-test:
    Container ID:   
    Image:          somerandomnonexistentimage
    Image ID:       
    Port:           80/TCP
    Host Port:      0/TCP
    State:          Waiting
      Reason:       ErrImagePull
...
Events:
  Type     Reason            Age                 From                                                 Message
  ----     ------            ----                ----                                                 -------
  Normal   Scheduled         66s                 default-scheduler                                    Successfully assigned default/web-test to ip-192-168-6-51.us-east-2.compute.internal
  Normal   Pulling           14s (x3 over 65s)   kubelet, ip-192-168-6-51.us-east-2.compute.internal  Pulling image "somerandomnonexistentimage"
  Warning  Failed            14s (x3 over 55s)   kubelet, ip-192-168-6-51.us-east-2.compute.internal  Failed to pull image "somerandomnonexistentimage": rpc error: code = Unknown desc = Error response from daemon: pull access denied for somerandomnonexistentimage, repository does not exist or may require 'docker login'
  Warning  Failed            14s (x3 over 55s)   kubelet, ip-192-168-6-51.us-east-2.compute.internal  Error: ErrImagePull

前の手順を試してもポッドがまだ Waiting 状態にある場合は、追加のトラブルシューティングセクションの手順を実行します。

ポッドが CrashLoopBackOff 状態にある場合

CrashLoopBackOff でスタックした Pod が起動し、クラッシュが繰り返し発生しています。

「Back-Off restarting failed container」という出力メッセージを受け取った場合、Kubernetes がコンテナを起動した直後にコンテナが終了した可能性があります。

現在のポッドのログでエラーを探すには、次のコマンドを実行します。

$ kubectl logs YOUR_POD_NAME

クラッシュした以前のポッドのログでエラーを探すには、次のコマンドを実行します。

$ kubectl logs --previous YOUR-POD_NAME

注: マルチコンテナポッドの場合、最後にコンテナ名を追加できます。以下はその例です。

$ kubectl logs [-f] [-p] (POD | TYPE/NAME) [-c CONTAINER]

Liveness プローブが成功ステータスを返さない場合は、Liveness プローブがアプリケーションに対して正しく設定されていることを確認します。詳細については、Kubernetes ドキュメントの Probe の構成を参照してください。

以下の例は、Events (イベント) とともに、アプリケーションが起動後に終了することから CrashLoopBackOff 状態になったポッド、Notice State (通知状態)、Last State (最後の状態)、Reason (理由)、Exit Code (終了コード)、および Restart Count (再起動回数) を示しています。

$ kubectl describe pod crash-app-b9cf4587-66ftw 
Name:         crash-app-b9cf4587-66ftw
Namespace:    default
Priority:     0
Node:         ip-192-168-91-249.ap-southeast-2.compute.internal/192.168.91.249
Start Time:   Tue, 12 Oct 2021 12:24:44 +1100
Labels:       app=crash-app
              pod-template-hash=b9cf4587
Annotations:  kubernetes.io/psp: eks.privileged
Status:       Running
IP:           192.168.82.93
IPs:
  IP:           192.168.82.93
Controlled By:  ReplicaSet/crash-app-b9cf4587
Containers:
  alpine:
    Container ID:   containerd://a36709d9520db92d7f6d9ee02ab80125a384fee178f003ee0b0fcfec303c2e58
    Image:          alpine
    Image ID:       docker.io/library/alpine@sha256:e1c082e3d3c45cccac829840a25941e679c25d438cc8412c2fa221cf1a824e6a
    Port:           <none>
    Host Port:      <none>
    State:          Waiting
      Reason:       CrashLoopBackOff
    Last State:     Terminated
      Reason:       Completed
      Exit Code:    0
      Started:      Tue, 12 Oct 2021 12:26:21 +1100
      Finished:     Tue, 12 Oct 2021 12:26:21 +1100
    Ready:          False
    Restart Count:  4
    ...
Events:
  Type     Reason     Age                  From               Message
  ----     ------     ----                 ----               -------
  Normal   Scheduled  2m30s                default-scheduler  Successfully assigned default/crash-app-b9cf4587-66ftw to ip-192-168-91-249.ap-southeast-2.compute.internal
  Normal   Pulled     2m25s                kubelet            Successfully pulled image "alpine" in 5.121853269s
  Normal   Pulled     2m22s                kubelet            Successfully pulled image "alpine" in 1.894443044s
  Normal   Pulled     2m3s                 kubelet            Successfully pulled image "alpine" in 1.878057673s
  Normal   Created    97s (x4 over 2m25s)  kubelet            Created container alpine
  Normal   Started    97s (x4 over 2m25s)  kubelet            Started container alpine
  Normal   Pulled     97s                  kubelet            Successfully pulled image "alpine" in 1.872870869s
  Warning  BackOff    69s (x7 over 2m21s)  kubelet            Back-off restarting failed container
  Normal   Pulling    55s (x5 over 2m30s)  kubelet            Pulling image "alpine"
  Normal   Pulled     53s                  kubelet            Successfully pulled image "alpine" in 1.858871422s

Pod に対する liveness プローブの失敗の例:

$ kubectl describe pod nginx
Name:         nginx
Namespace:    default
Priority:     0
Node:         ip-192-168-91-249.ap-southeast-2.compute.internal/192.168.91.249
Start Time:   Tue, 12 Oct 2021 13:07:55 +1100
Labels:       app=nginx
Annotations:  kubernetes.io/psp: eks.privileged
Status:       Running
IP:           192.168.79.220
IPs:
  IP:  192.168.79.220
Containers:
  nginx:
    Container ID:   containerd://950740197c425fa281c205a527a11867301b8ec7a0f2a12f5f49d8687a0ee911
    Image:          nginx
    Image ID:       docker.io/library/nginx@sha256:06e4235e95299b1d6d595c5ef4c41a9b12641f6683136c18394b858967cd1506
    Port:           80/TCP
    Host Port:      0/TCP
    State:          Waiting
      Reason:       CrashLoopBackOff
    Last State:     Terminated
      Reason:       Completed
      Exit Code:    0
      Started:      Tue, 12 Oct 2021 13:10:06 +1100
      Finished:     Tue, 12 Oct 2021 13:10:13 +1100
    Ready:          False
    Restart Count:  5
    Liveness:       http-get http://:8080/ delay=3s timeout=1s period=2s #success=1 #failure=3
    ...
Events:
  Type     Reason     Age                    From               Message
  ----     ------     ----                   ----               -------
  Normal   Scheduled  2m47s                  default-scheduler  Successfully assigned default/nginx to ip-192-168-91-249.ap-southeast-2.compute.internal
  Normal   Pulled     2m44s                  kubelet            Successfully pulled image "nginx" in 1.891238002s
  Normal   Pulled     2m35s                  kubelet            Successfully pulled image "nginx" in 1.878230117s
  Normal   Created    2m25s (x3 over 2m44s)  kubelet            Created container nginx
  Normal   Started    2m25s (x3 over 2m44s)  kubelet            Started container nginx
  Normal   Pulled     2m25s                  kubelet            Successfully pulled image "nginx" in 1.876232575s
  Warning  Unhealthy  2m17s (x9 over 2m41s)  kubelet            Liveness probe failed: Get "http://192.168.79.220:8080/": dial tcp 192.168.79.220:8080: connect: connection refused
  Normal   Killing    2m17s (x3 over 2m37s)  kubelet            Container nginx failed liveness probe, will be restarted
  Normal   Pulling    2m17s (x4 over 2m46s)  kubelet            Pulling image "nginx"

前述の手順を試してもポッドがまだ CrashLoopBackOff 状態にある場合は、「追加のトラブルシューティング」セクションの手順を実行しまください。

追加のトラブルシューティング

前のセクションの手順を完了してもまだポッドがスタックしている場合は、以下の手順を試してください。

1.    ワーカーノードがクラスター内に存在し、Ready 状態にあることを確認するには、次のコマンドを実行します。

$ kubectl get nodes

出力例:

NAME                                          STATUS   ROLES    AGE   VERSION
ip-192-168-6-51.us-east-2.compute.internal    Ready    <none>   25d   v1.21.2-eks-5047ed
ip-192-168-86-33.us-east-2.compute.internal   Ready    <none>   25d   v1.21.2-eks-5047ed

ノードが NotReady の場合は、「ノードのステータスを NotReady または Unknown ステータスから Ready ステータスに変更するにはどうすればよいですか?」をまたは、クラスターに参加できない場合は「ワーカーノードを Amazon EKS クラスターに参加させるにはどうすればよいですか?」を参照してください。

2.    Kubernetes クラスターのバージョンを確認するには、次のコマンドを実行します。

$ kubectl version --short

出力例:

Client Version: v1.21.2-eks-5047ed
Server Version: v1.21.2-eks-c0eccc

3.    Kubernetes ワーカーノードのバージョンを確認するには、次のコマンドを実行します。

$ kubectl get node -o custom-columns=NAME:.metadata.name,VERSION:.status.nodeInfo.kubeletVersion

出力例:

NAME                                          VERSION
ip-192-168-6-51.us-east-2.compute.internal    v1.21.2-eks-5047ed
ip-192-168-86-33.us-east-2.compute.internal   v1.21.2-eks-5047ed

4.    クラスターの Kubernetes サーバーバージョンが、許容されるバージョンスキュー (Kubernetes ドキュメントからのもの) 内のワーカーノードのバージョンと一致することを確認します。この比較の基準として、前述の手順 2 と 3 からの出力を使用します。

重要: パッチのバージョンは異なる場合があります (例えば、クラスターは v1.21.x、ワーカーノードは v1.21.y といったケース)。

クラスターとワーカーノードのバージョンに互換性がない場合は、eksctl ([eksctl] タブを参照) または AWS CloudFormation ([セルフマネージドノード] タブを参照) で新しいノードグループを作成します。

- または -

互換性のある Kubernetes バージョンを使用して、新しいマネージドノードグループ (Kubernetes: v1.21、プラットフォーム: eks.1 以降) を作成します。次に、互換性のない Kubernetes バージョンのノードグループを削除します。

5.    Amazon EKS セキュリティグループの考慮事項の推奨ルールと照らし合わせてファイアウォールルールを検証し、Kubernetes コントロールプレーンがワーカーノードと通信できることを確認します。次に、ノードが Ready 状態にあることを確認します。


この記事はお役に立ちましたか?


請求に関するサポートまたは技術サポートが必要ですか?