Amazon EKS에서 포드 상태 문제를 해결하려면 어떻게 해야 하나요?

8분 분량
0

Amazon Elastic Compute Cloud(Amazon EC2) 인스턴스 또는 관리형 노드 그룹에서 실행 중인 Amazon Elastic Kubernetes Service(Amazon EKS) 포드가 멈췄습니다. 내 포드를 "Running" 또는 "Terminated" 상태로 바꾸려고 합니다.

해결 방법

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

포드 상태 찾기

Amazon EKS에서 포드 상태 문제를 해결하려면, 다음 단계를 완료하세요.

  1. 포드의 상태를 확인하려면 다음 명령어를 실행합니다.

    $ kubectl get pod
  2. 포드의 이벤트 기록에서 정보를 가져오려면, 다음 명령어를 실행합니다.

    $ kubectl describe pod YOUR_POD_NAME
  3. 포드 상태에 따라 다음 섹션의 단계를 완료하세요.

포드가 Pending 상태입니다.

참고: 다음 단계의 예제 명령은 기본 네임스페이스에 있습니다. 다른 네임스페이스의 경우, 명령에 -n YOURNAMESPACE를 추가합니다.

리소스가 부족하거나 hostPort를 정의했기 때문에 포드가 Pending 상태로 멈출 수 있습니다. 자세한 내용을 보려면 Kubernetes 웹사이트의 포드 단계를 참조하세요.

워커 노드의 리소스가 충분하지 않은 경우 불필요한 포드를 삭제하세요. 워커 노드에 리소스를 더 추가할 수도 있습니다. 클러스터에 리소스가 충분하지 않은 경우, Kubernetes 클러스터 오토스케일러를 사용하여 워커 노드 그룹을 자동으로 확장합니다.

CPU 부족 예제:

$ kubectl describe pod frontend-cpu
Name:         frontend-cpu
...
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
...
Status:       Pending
...
Events:
  Type     Reason            Age                 From               Message
  ----     ------            ----                ----               -------
  Warning  FailedScheduling  80s (x14 over 15m)  default-scheduler  0/3 nodes are available: 3 Insufficient memory.

포드에 hostPort를 정의한 경우, 다음 모범 사례를 따르세요.

  • hostIP, hostPortprotocol 조합은 고유해야 하므로 필요한 경우에만 hostPort를 지정하세요.
  • hostPort를 지정하는 경우, 워커 노드와 동일한 수의 포드를 스케줄링합니다.

참고: 포드를 hostPort에 바인딩할 때, 포드를 예약할 수 있는 위치의 수가 제한되어 있습니다.

다음 예시는 frontend-port-77f67cff67-2bv7w라는 Pending 상태인 포드에 대한 describe 명령의 출력을 보여줍니다. 요청된 호스트 포트를 클러스터의 워커 노드에 사용할 수 없기 때문에 포드가 스케줄링되지 않았습니다.

$ kubectl describe pod frontend-port-77f67cff67-2bv7w
Name:           frontend-port-77f67cff67-2bv7w
...
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.

노드에 포드가 허용하지 않는 테인트가 있어서 포드를 스케줄링할 수 없는 경우, 예제 출력은 다음과 비슷합니다.

$ kubectl describe pod nginx
Name:         nginx
...
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

노드 테인트를 유지하려면, PodSpec에서 포드에 대한 톨러레이션을 지정해야 합니다. 자세한 내용을 보려면 Kubernetes 웹사이트의 개념을 참조하세요. 또는 테인트 값 끝에 **-**를 추가하여 노드 테인트를 제거합니다.

$ kubectl taint nodes NODE_Name key1=value1:NoSchedule-

포드가 아직 Pending 상태인 경우, 추가 문제 해결 섹션의 단계를 완료하세요.

컨테이너가 Waiting 상태입니다.

Docker 이미지가 잘못되었거나 저장소 이름이 잘못되어 컨테이너가 Waiting 상태일 수 있습니다. 또는 이미지가 존재하지 않거나 권한이 없기 때문에 포드가 Waiting 상태일 수 있습니다.

이미지와 리포지토리 이름이 올바른지 확인하려면 Docker Hub, Amazon Elastic Container Registry (Amazon ECR) 또는 다른 컨테이너 이미지 리포지토리에 로그인하세요. 리포지토리 또는 리포지토리의 이미지를 포드 사양에 지정된 리포지토리 또는 이미지 이름과 비교합니다. 이미지가 존재하지 않거나 권한이 없는 경우, 다음 단계를 완료하세요.

  1. 지정한 이미지를 저장소에서 사용할 수 있고 이미지를 가져올 수 있도록 올바른 권한이 구성되어 있는지 확인합니다.

  2. 이미지를 가져올 수 있고 일반적인 네트워킹 및 리포지토리 권한 문제가 없는지 확인하려면 이미지를 수동으로 가져오세요. Amazon EKS 워커 노드에서 이미지를 가져오려면 Docker를 사용해야 합니다.

    $ docker pull yourImageURI:yourImageTag
  3. 이미지가 존재하는지 확인하려면 이미지와 태그가 모두 Docker Hub 또는 Amazon ECR에 있는지 확인하세요.

참고: Amazon ECR을 사용하는 경우 리포지토리 정책이 NodeInstanceRole에 대한 이미지 풀을 허용하는지 확인하세요. 또는 AmazonEC2ContainerRegistryReadOnly 읽기 전용 역할이 정책에 연결되어 있는지 확인하세요.
다음 예제는 이미지 풀 오류로 인해 컨테이너가 Waiting 상태에 있는 Pending 상태의 포드를 보여줍니다.

$ kubectl describe po web-test

Name:               web-test
...
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 상태입니다.

“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]

활성 프로브가 Succesful 상태를 반환하지 않는 경우, 라이브니스 프로브가 애플리케이션에 맞게 올바르게 구성되었는지 확인하세요. 자세한 내용을 보려면 Kubernetes 웹사이트의 프로브 구성을 참조하세요.

다음 예제는 포드가 시작된 후 애플리케이션이 종료되기 때문에 CrashLoopBackOff 상태에 있는 포드를 보여줍니다.

$ kubectl describe pod crash-app-b9cf4587-66ftw
Name:         crash-app-b9cf4587-66ftw
...
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   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

다음은 포드에서 실패한 활성 프로브의 예입니다.

$ kubectl describe pod nginx
Name:         nginx
...
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   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 상태인 경우, 추가 문제 해결 섹션의 단계를 완료하세요.

포드가 Terminating 상태입니다.

포드가 Terminating 상태로 멈춘 경우, 해당 포드가 실행 중인 노드와 파이널라이저의 상태를 확인하세요. 파이널라이저는 포드가 Terminated로 전환되기 전에 종료 처리를 수행하는 함수입니다. 자세한 내용을 보려면 Kubernetes 웹사이트의 파이널라이저를 참조하십시오. 종료하는 포드의 파이널라이저를 확인하려면, 다음 명령을 실행합니다.

$ kubectl get po nginx -o yaml  

apiVersion: v1  
kind: Pod  
metadata:  
...  
  finalizers:  
  - sample/do-something  
...

위 예제에서는 파이널라이저 sample/do-something이 제거된 후에만 포드가 Terminated로 전환됩니다. 일반적으로 커스텀 컨트롤러는 파이널라이저를 처리한 다음 제거합니다. 그러면 포드가 Terminated 상태로 전환됩니다.

이 문제를 해결하려면, 커스텀 컨트롤러의 포드가 제대로 실행되는지 확인하세요. 컨트롤러 포드 관련 문제를 해결하고 사용자 지정 컨트롤러가 파이널라이저 프로세스를 완료하도록 합니다. 그러면 포드가 자동으로 Terminated 상태로 전환됩니다. 또는 다음 명령을 실행하여 파이널라이저를 직접 삭제합니다.

$ kubectl edit po nginx

추가 문제 해결

포드가 여전히 멈춘 경우, 다음 단계를 완료하세요.

  1. 워커 노드가 클러스터에 있고 Ready 상태인지 확인하려면 다음 명령을 실행합니다.

    $ kubectl get nodes

    노드 상태가 NotReady인 경우 노드 상태를 NotReady 또는 Unknown 상태에서 Ready 상태로 변경하려면 어떻게 해야 하나요?를 참조하세요. 노드가 클러스터에 가입할 수 없는 경우, 워커 노드를 Amazon EKS 클러스터에 참여시키려면 어떻게 해야 하나요?를 참조하세요.

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

    $ kubectl version --short
  3. Kubernetes 워커 노드의 버전을 확인하려면, 다음 명령을 실행합니다.

    $ kubectl get node -o custom-columns=NAME:.metadata.name,VERSION:.status.nodeInfo.kubeletVersion
  4. 클러스터의 Kubernetes 서버 버전이 허용 가능한 버전 차이 내에서 워커 노드의 버전과 일치하는지 확인합니다. 자세한 내용을 보려면 Kubernetes 웹사이트의 버전 스큐 정책을 참조하세요.
    중요: 패치 버전은 클러스터와 워커 노드 간에 다를 수 있습니다 (예: 클러스터의 경우 v1.21.x, 워커 노드의 경우 v1.21.y). 클러스터와 워커 노드 버전이 호환되지 않는 경우 eksctl 또는 AWS CloudFormation을 사용하여 새 노드 그룹을 생성하세요. 또는 호환되는 Kubernetes 버전을 사용하여 새로운 관리형 노드 그룹(예: Kubernetes: v1.21, 플랫폼: eks.1 이상)을 생성합니다. 그런 다음, 호환되지 않는 Kubernetes 버전이 포함된 노드 그룹을 삭제합니다.

  5. Kubernetes 컨트롤 플레인이 워커 노드와 통신할 수 있는지 확인합니다. Amazon EKS 보안 그룹 요구 사항 및 고려 사항의 필수 규칙과 비교하여 방화벽 규칙을 확인하세요. 그런 다음, 노드가 Ready 상태인지 확인합니다.

AWS 공식
AWS 공식업데이트됨 3달 전