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) hostIP、hostPort、protocol の組み合わせは一意でなければならないため、必要でない限り、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 状態にあることを確認します。