Questions?


Amazon Elastic Kubernetes Service(Amazon EKS) 작업자 노드가 NotReady 또는 Unknown 상태입니다. 작업자 노드를 다시 Ready 상태로 되돌리고 싶습니다.



Answer


원인


NotReady 또는 Unknown 상태인 노드에서는 포드를 예약할 수 없습니다. Ready 상태인 노드에서만 포드를 예약할 수 있습니다.

노드가 해당 상태인 가장 큰 원인은 주로 네트워크 및 리소스 부족 문제입니다.


메모리의 사용률이 높아져 OOM killer에 의해 프로세스들이 강제로 kill 되고 있는 상황이나 노드의 메모리 부족이 발생하는 경우 aws-node, kube-proxy 등과 같이 클러스터가 동작하기 위해 필요한 system pod에도 영향을 미칠 수 있고 kubelet, docker 등 관련 프로세스가 정상적으로 동작하지 않을 수 있습니다.





해결 방법



A. aws-node 및 kube-proxy 포드를 확인하여 노드가 NotReady 상태인 이유를 확인합니다.


NotReady 상태의 노드는 예약된 포드에 사용할 수 없습니다.


1.    aws-node 포드가 오류 상태인지 확인하려면 다음 명령을 실행합니다.


$ kubectl get pods -n kube-system -o wide



2.    aws-node 및 kube-proxy 포드의 상태를 확인하려면 다음 명령을 실행합니다.


$ kubectl get pods -n kube-system -o wide



3.    1단계의 출력을 검토하여 aws-node 및 kube-proxy 포드의 상태를 확인합니다.


노드 상태가 정상이면 aws-node 및 kube-proxy 포드가 Running 상태여야 합니다.


두 포드 중 하나가 Running 이외의 상태인 경우 다음 명령을 실행합니다.


$ kubectl describe pod yourPodName -n kube-system



4.    aws-node 및 kube-proxy 포드 로그에서 추가 정보를 가져오려면 다음 명령을 실행합니다.


$ kubectl logs yourPodName -n kube-system



설명 출력의 로그와 이벤트는 포드가 Running 상태가 아닌 이유를 보여줄 수 있습니다. 노드를 Ready 상태로 변경하려면 aws-node 및 kube-proxy 포드가 모두 해당 노드에서 Running이어야 합니다.


5.    1단계에서 명령을 실행한 후 aws-node 및 kube-proxy 포드가 나열되지 않으면 다음 명령을 실행합니다.


$ kubectl describe daemonset aws-node -n kube-system

$ kubectl describe daemonset kube-proxy -n kube-system



6.    4단계에서 실행한 명령의 출력을 검색하여 포드를 시작할 수 없는 이유를 확인합니다.


7.    AWS 가이드라인을 참고하여 aws-node와 kube-proxy의 버전이 클러스터 버전과 호환되는지 확인합니다. 예를 들어 다음의 명령을 실행하여 포드 버전을 확인할 수 있습니다.


$ kubectl describe daemonset aws-node --namespace kube-system | grep Image | cut -d "/" -f 2



$ kubectl get daemonset kube-proxy --namespace kube-system -o=jsonpath='{$.spec.template.spec.containers[:1].image}'



B. 노드와 제어 플레인 간의 네트워크 구성 확인


1.    서브넷에 Amazon EKS 제어 플레인과 작업자 노드 간의 트래픽을 차단하는 네트워크 ACL(액세스 제어 목록) 규칙이 없는지 확인합니다.


2.    제어 플레인 및 노드의 보안 그룹이 최소 인바운드 및 아웃바운드 요구 사항을 준수하는지 확인합니다.


3.    (선택 사항) 노드가 프록시를 사용하도록 구성된 경우 프록시가 API 서버 엔드포인트에 대한 트래픽을 허용하는지 확인합니다.


4.    노드가 API 서버에 액세스할 수 있는지 확인하려면 작업자 노드 안에서 다음 netcat 명령을 실행합니다.


$ nc -vz 9FCF4EA77D81408ED82517B9B7E60D52.yl4.eu-north-1.eks.amazonaws.com 443

Connection to 9FCF4EA77D81408ED82517B9B7E60D52.yl4.eu-north-1.eks.amazonaws.com 443 port [tcp/https] succeeded!


중요: 9FCF4EA77D81408ED82517B9B7E60D52.yl4.eu-north-1.eks.amazonaws.com을 API 서버 엔드포인트로 바꾸세요.


5.    인터넷 게이트웨이 또는 NAT 게이트웨이를 통해 API 서버 엔드포인트와의 통신이 허용되도록 라우팅 테이블이 올바르게 구성되었는지 확인합니다. 클러스터가 PrivateOnly 네트워킹을 사용하는 경우 VPC 엔드포인트가 올바르게 구성되었는지 확인합니다.


C. kubelet 상태 확인


1.    SSH를 사용하여 영향을 받는 작업자 노드에 연결합니다.


2.    kubelet 로그를 확인하려면 다음 명령을 실행합니다.


$ journalctl -u kubelet > kubelet.log


참고: kubelet.log 파일에는 노드 상태 문제의 근본 원인을 찾는 데 도움이 되는 kubelet 작업에 대한 정보가 포함되어 있습니다.


로그가 문제의 원인에 대한 정보를 제공하지 않는 경우 다음 명령을 실행하여 작업자 노드에서 kubelet의 상태를 확인합니다.


$ sudo systemctl status kubelet

  kubelet.service - Kubernetes Kubelet

   Loaded: loaded (/etc/systemd/system/kubelet.service; enabled; vendor preset: disabled)

  Drop-In: /etc/systemd/system/kubelet.service.d

           └─10-eksclt.al2.conf

   Active: inactive (dead) since Wed 2019-12-04 08:57:33 UTC; 40s ago


kubelet이 Running 상태가 아닌 경우 다음 명령을 실행하여 kubelet을 다시 시작합니다.


$ sudo systemctl restart kubelet




D. 작업자 노드 인스턴스 프로파일 및 ConfigMap 확인


1.    작업자 노드 인스턴스 프로파일에 권장 정책이 있는지 확인합니다.


2.    작업자 노드 인스턴스 역할이 aws-auth ConfigMap에 있는지 확인합니다. ConfigMap을 확인하려면 다음 명령을 실행하세요.


$ kubectl get cm aws-auth -n kube-system -o yaml


ConfigMap은 작업자 노드 인스턴스 AWS Identity and Access Management(IAM) 역할에 대한 항목이 있어야 합니다. 예:


apiVersion: v1

kind: ConfigMap

metadata:

  name: aws-auth

  namespace: kube-system

data:

  mapRoles: |

    - rolearn: <ARN of instance role (not instance profile)>

      username: system:node:{{EC2PrivateDNSName}}

      groups:

        - system:bootstrappers

        - system:nodes



재발 방지 방법


해당 이슈의 재발을 방지하기 위해 다음의 항목들을 확인해보시기 바랍니다.


1) 클러스터에 Auto Scaling 설정이 되어 있는지 확인해보시기 바랍니다.


Pod의 리소스 사용률이 올라갔을 때 이를 감지하고 임계치를 넘어섰을 때 해당 Pod를 Scaling하는 설정을 통해 위와 같은 이슈를 예방하실 수 있습니다. Pod의 리소스 사용률에 따라 Auto Scaling이 발생할 수 있도록 Horizontal Pod Autoscaler를 설정하고, Pod가 Scaling 되면서 기존 노드의 리소스 부족이 감지되면 Cluster Autoscaler를 통해 노드도 Auto scaling 될 수 있도록 구성하시기를 추천드립니다.


2) 배포되어 있는 Pod의 리소스 사용량 요청에 대해 request/limit 값을 확인해보시기 바랍니다.

노드의 리소스를 유연하게 사용하기 위해 soft limit의 개념으로 리소스를 요청할 수 있지만 노드의 리소스 고갈상태에서는 overcommit이 발생할 수 있습니다.


3) 각 Pod들의 리소스 사용량 모니터링이 되면 더 빠르게 리소스 사용률 증가 등을 감지하실 수 있습니다.

Container Insights 구성을 통해 각 Pod의 리소스 사용량, Node의 리소스 사용량, EKS 클러스터 모니터링 등을 수행하실 수 있으니 고려해보시기 바랍니다.


4) CPU/Memory 스펙이 더 높은 인스턴스 타입으로 교체하여 CPU/Memory 사용률이 높아질 때를 미리 대비할 수 있습니다.


유즈케이스에 맞게 충분히 고려하여 리소스 고갈로 인한 동일 이슈가 발생하지 않도록 대비하시기 바랍니다.