Amazon EKS에서 Pod 상태 문제를 해결하려면 어떻게 해야 합니까?

최종 업데이트 날짜: 2020년 2월 13일

Amazon Elastic Compute Cloud(Amazon EC2) 인스턴스 또는 관리형 노드 그룹에서 실행 중인 Amazon Elastic Kubernetes Service(Amazon EKS) Pod가 멈춰 있습니다. Pod를 Running(실행 중) 상태로 가져오려면 어떻게 해야 합니까?

해결 방법

중요: 다음 단계는 Amazon EC2 인스턴스 또는 관리형 노드 그룹에서 시작된 Pod에만 적용됩니다. 이 단계는 AWS Fargate에서 시작된 Pod에는 적용되지 않습니다.

Pod의 상태 확인

1.    Pod의 이벤트 기록에서 정보를 가져오려면 다음 명령을 실행합니다.

$ kubectl describe pod YOUR_POD_NAME

참고: 다음 단계에서 다루는 예제 명령은 기본 네임스페이스에 있습니다. 다른 네임스페이스의 경우 명령을 -n YOURNAMESPACE와 연결합니다.

2.    Pod의 상태에 따라 다음 섹션 중 하나의 단계를 완료합니다. Pod가 [Pending(보류 중)] 상태에 있음, Pod가 [Waiting(대기 중)] 상태에 있음 또는Pod가 [CrashLoopBackOff] 상태에 있음

Pod가 [Pending(보류 중)] 상태에 있음

[Pending(보류 중)] 상태의 Pod를 노드에 예약할 수 없습니다.

사용 가능한 작업자 노드에 리소스가 부족하거나 Pod에서 사용 중인 hostPort를 정의했기 때문에 Pod가 [Pending(보류 중)] 상태일 수 있습니다.

사용 가능한 작업자 노드에 리소스가 부족한 경우 불필요한 Pod를 삭제하거나 작업자 노드를 추가합니다. 예를 들어 작업자 노드에 CPU와 메모리가 부족할 수 있습니다. 이 문제가 반복되는 경우 클러스터의 리소스가 부족할 때 Kubernetes Cluster Autoscaler를 사용하여 작업자 노드 그룹을 자동으로 조정할 수 있습니다.

Pod에 대해 hostPort를 정의하는 경우 다음을 고려하십시오.

(A) Pod를 hostPort에 바인딩할 때 Pod를 예약할 수 있는 위치의 개수가 제한되어 있습니다.
(B) hostIP, hostPort프로토콜 조합이 고유해야 하므로 필요한 경우가 아니라면hostPort를 지정하지 마십시오.
(C) hostPort를 지정해야 하는 경우 작업자 노드와 동일한 수의 Pod를 예약합니다.

다음 예제에서는 [Pending(보류 중)] 상태인 my-nginx-12345abc6d-7e8fg에 대한 describe 명령의 출력을 보여 줍니다. 리소스 제약 때문에 Pod가 예약되지 않았습니다.

$ kubectl describe pod my-nginx-86459cfc9f-2j5bq

Name:               my-nginx-12345abc6d-7e8fg
Namespace:          default
Priority:           0
PriorityClassName:  
Node:               
Labels:             pod-template-hash=86459cfc9f
                    run=my-nginx
Annotations:        kubernetes.io/psp: eks.privileged
Status:             Pending
...
Events:
  Type     Reason            Age                 From               Message
  ----     ------            ----                ----               -------
  Warning  FailedScheduling  7s (x6 over 5m58s)  default-scheduler  0/2 nodes are available: 1 Insufficient pods, 1 node(s) had taints that the pod didn't tolerate.

이전 단계를 시도한 후에도 Pod가 [Pending(보류 중)] 상태인 경우 추가 문제 해결 섹션의 단계를 완료합니다.

Pod가 [Waiting(대기 중)] 상태에 있음

[Waiting(대기 중)] 상태의 Pod는 작업자 노드(예: Amazon EC2 인스턴스)에서 예약되지만 해당 노드에서는 실행할 수 없습니다.

Docker 이미지 또는 리포지토리 이름이 잘못되었거나 권한이 없거나 이미지가 존재하지 않기 때문에 Docker가 [Waiting(대기 중)] 상태일 수 있습니다.

잘못된 Docker 이미지 또는 리포지토리 이름이 있는 경우 다음을 완료하십시오.

1.    Docker Hub, Amazon Elastic Container Registry(Amazon ECR) 또는 다른 컨테이너 이미지 리포지토리에 로그인하여 이미지와 리포지토리 이름이 올바른지 확인합니다.

2.    리포지토리 또는 리포지토리의 이미지를 Pod 사양에 지정된 리포지토리 또는 이미지 이름과 비교합니다.

이미지가 없거나 권한이 없는 경우 다음을 완료하십시오.

1.    지정된 이미지를 리포지토리에서 사용할 수 있는지, 이미지를 가져올 수 있도록 올바른 권한이 구성되어 있는지 확인합니다.

2.    이미지 가져오기가 가능한지 확인하고 일반적인 네트워킹 및 리포지토리 권한 문제를 배제하려면 Docker를 사용하여 Amazon EKS 작업자 노드에서 이미지를 수동으로 가져옵니다.

$ docker pull yourImageURI:yourImageTag

3.    이미지가 존재하는지 확인하려면 Docker Hub 또는 Amazon ECR에 이미지와 태그가 모두 있는지 확인합니다.

참고: Amazon ECR을 사용하는 경우 리포지토리 정책이 NodeInstanceRole에 대한 이미지 가져오기를 허용하는지 확인하십시오. 또는 AmazonEC2ContainerRegistryReadOnly 역할이 정책에 연결되어 있는지 확인합니다.

다음 예제에서는 이미지 풀 오류로 인해 [Waiting(대기 중)] 상태인 컨테이너와 [Pending(보류 중)] 상태인 Pod를 보여 줍니다.

$ 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 Jan 2020 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

이전 단계를 시도한 후에도 Pod가 여전히 [Waiting(대기 중)] 상태인 경우 추가 문제 해결 섹션의 단계를 완료합니다.

Pod가 [CrashLoopBackOff] 상태에 있음

[CrashLoopBackOff]에서 멈춘 Pod가 시작, 충돌, 다시 시작되고 반복적으로 다시 충돌합니다.

"Back-Off restarting failed container" 출력 메시지를 수신하는 경우 Kubernetes가 컨테이너를 시작한 직후에 컨테이너가 종료되었을 수 있습니다.

현재 Pod의 로그에서 오류를 찾으려면 다음 명령을 실행합니다.

$ kubectl logs YOUR_POD_NAME

충돌한 이전 Pod의 로그에서 오류를 찾으려면 다음 명령을 실행합니다.

$ kubectl logs --previous YOUR-POD_NAME

참고: 다중 컨테이너 Pod의 경우 컨테이너 이름을 끝에 추가할 수 있습니다. 예를 들면 다음과 같습니다.

$ kubectl logs POD_NAME CONTAINER_NAME

Liveness 프로브가 성공 상태를 반환하지 않는 경우 애플리케이션에 대해 Liveness 프로브가 올바르게 구성되어 있는지 확인합니다. 자세한 내용은 프로브 구성을 참조하십시오.

다음 예제는 애플리케이션이 시작 후 종료되기 때문에 [CrashLoopBackOff] 상태의 Pod를 보여줍니다.

$ kubectl describe po crash-app-6847947bf8-28rq6

Name:               crash-app-6847947bf8-28rq6
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 Jan 2020 08:42:20 +0200
Labels:             pod-template-hash=6847947bf8
                    run=crash-app
Annotations:        kubernetes.io/psp: eks.privileged
Status:             Running
IP:                 192.168.29.73
Controlled By:      ReplicaSet/crash-app-6847947bf8
Containers:
  main:
    Container ID:  docker://6aecdce22adf08de2dbcd48f5d3d8d4f00f8e86bddca03384e482e71b3c20442
    Image:         alpine
    Image ID:      docker-pullable://alpine@sha256:ab00606a42621fb68f2ed6ad3c88be54397f981a7b70a79db3d1172b11c4367d
    Port:          80/TCP
    Host Port:     0/TCP
    Command:
      /bin/sleep
      1
    State:          Waiting
      Reason:       CrashLoopBackOff
...
Events:
  Type     Reason     Age                From                                                 Message
  ----     ------     ----               ----                                                 -------
  Normal   Scheduled  47s                default-scheduler                                    Successfully assigned default/crash-app-6847947bf8-28rq6 to ip-192-168-6-51.us-east-2.compute.internal
  Normal   Pulling    28s (x3 over 46s)  kubelet, ip-192-168-6-51.us-east-2.compute.internal  Pulling image "alpine"
  Normal   Pulled     28s (x3 over 46s)  kubelet, ip-192-168-6-51.us-east-2.compute.internal  Successfully pulled image "alpine"
  Normal   Created    28s (x3 over 45s)  kubelet, ip-192-168-6-51.us-east-2.compute.internal  Created container main
  Normal   Started    28s (x3 over 45s)  kubelet, ip-192-168-6-51.us-east-2.compute.internal  Started container main
  Warning  BackOff    12s (x4 over 42s)  kubelet, ip-192-168-6-51.us-east-2.compute.internal  Back-off restarting failed container

이전 단계를 시도한 후에도 Pod가 여전히 [CrashLoopBackOff] 상태에 있는 경우 추가 문제 해결 섹션의 단계를 완료합니다.

추가 문제 해결

이전 섹션의 단계를 완료한 후에도 Pod가 멈춘 경우 다음 단계를 수행해 보십시오.

1.    작업자 노드가 클러스터에 존재하고 [Ready(준비 완료)] 상태(Pod를 예약할 수 있음)인지 확인하려면 다음 명령을 실행합니다.

$ kubectl get nodes

출력은 다음과 비슷해야 합니다.

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

노드가 클러스터에 없는 경우 작업자 노드를 추가합니다.

노드가 [NotReady]이거나 클러스터에 조인할 수 없는 경우 노드 상태를 NotReady 또는 Unknown 상태에서 Ready 상태로 변경하려면 어떻게 해야 합니까?를 참조하십시오.

2.    Kubernetes 클러스터의 버전을 확인하려면 다음 명령을 실행합니다.

$ kubectl version --short

출력은 다음과 비슷해야 합니다.

Client Version: v1.14.6-eks-5047ed
Server Version: v1.14.9-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.14.6-eks-5047ed
ip-192-168-86-33.us-east-2.compute.internal   v1.14.6-eks-5047ed

4.    2단계 및 3단계의 출력을 기반으로 클러스터의 Kubernetes 서버 버전이 허용 가능한 버전 스큐 내의 작업자 노드 버전과 일치하는지 확인합니다.

중요: 패치 버전은 다를 수 있습니다(예: 클러스터의 경우 v1.14.x, 작업자 노드의 경우 v1.14.y).

클러스터 및 작업자 노드 버전이 호환되지 않는 경우, eksctl(eksctl 탭 참조) 또는 AWS CloudFormation(자체 관리형 노드 탭 참조)을 사용하여 새 노드 그룹을 생성합니다.

--또는--

호환되는 Kubernetes 버전을 사용하여 새 관리형 노드 그룹(Kubernetes: v1.14, 플랫폼: eks.3 이상)을 생성합니다. 그런 다음 호환되지 않는 Kubernetes 버전이 있는 노드 그룹을 삭제합니다.

5.    Kubernetes 제어 플레인이 작업자 노드와 통신할 수 있는지 확인하려면 Amazon EKS 보안 그룹 고려 사항의 권장 규칙과 비교하여 방화벽 규칙을 확인한 다음 노드가 [Ready(준비 완료)] 상태인지 확인합니다.


이 문서가 도움이 되었습니까?

AWS에서 개선해야 할 부분이 있습니까?


도움이 필요하십니까?