티스토리 뷰

728x90
반응형

본 포스팅에서는 Kubernetes 구축 시 CoreDNS의 CrashLoopBackOff Status 발생 및 지속적인 Restarting 현상에 대한 해결방안에 대해 다뤄보도록 하겠습니다.

Kubernetes를 구축하다보면 정말 많은 이슈들에 직면하게 됩니다.

사실 클라우드를 도입하면 장점이 워낙 많다 보니 누구나 클라우드화에 동의하고 있지만, 도입자체가 기존 3Tier Legacy 환경만큼 간단한 것은 아닙니다.

오늘 다루게 될 이슈도 사실은 별거 아닌 이슈가 될 수도 있지만, Kubernetes의 구성 요소를 정확히 이해하지 못하고 접근하게 된다면 전혀 해결방안에 대한 실마리를 찾아 갈 수 없을 수도 있습니다.

장애 발생

- coredns가 지속적으로 restarting 되는 현상 발생

coredns는 Kubernetes CNI가 구성되기 이전에는 Pending 상태로 대기하게 되며, Calico, Weave 등의 CNI가 구성되면 Status가 변경됩니다. 이때 coredns의 status가 Running이 아닌 CrashLoopBackOff 라는 상태로 변경될 경우 아래와 같은 현상을 의심해 보아야 합니다.

- Loop Plugin

CoreDNS에는 Loop Plugin이라는 Sub Module이 존재합니다. Loop Plugin은 임의의 Probe Query를 자신에게 보내고 이를 몇번 Return을 받게 되는지 추적합니다. 이때 두 번 이상 Probe Query에 대한 Return을 받을 경우 CoreDNS가 프로세스를 중단합니다.
Loop Plugin은 최대 30 초 동안 쿼리를 보내려고 시도하며, 쿼리가 성공적으로 전송되면 루프는 자체적으로 비활성화됩니다. 
전송 된 쿼리는 HINFO 유형의<random number>.<random number>.zone입니다.

장애 진단

장애 진단 프로세스는 앞선 포스팅을 참고한 후 따라하시면 보다 효과적인 TroubleShooting이 진행될 수 있습니다.

 

[Kubernetes] 장애 발생 시 진단 Process 정의

 

최초 장애가 발생하면 다음과 같은 로그를 수집해야 합니다.


[root@nrson success_log]# kubectl get pods -o wide --all-namespaces 
NAMESPACE     NAME                                       READY   STATUS    RESTARTS   AGE   IP             NODE         NOMINATED NODE   READINESS GATES 
kube-system   calico-kube-controllers-6c954486fd-tmlnl   1/1    Running   0          25m    172.21.20.51   kubeworker
kube-system   calico-node-ksmgr                          1/1     Running   1          26m   172.21.20.51   kubeworker               
kube-system   calico-node-rr5gm                          1/1     Running   1          26m   172.21.20.50   kubemaster               
kube-system   coredns-7ff7988d-rd2l5                     0/1    CrashLoopBackOff    25          25m                               
kube-system   dns-autoscaler-748467c887-bhqxv            1/1    Running   0          25m   172.21.20.51   kubeworker
kube-system   kube-apiserver-kubemaster                  1/1     Running   0          27m   172.21.20.50   kubemaster               
kube-system   kube-controller-manager-kubemaster         1/1     Running   0          27m   172.21.20.50   kubemaster               
kube-system   kube-proxy-85csh                           1/1     Running   0          26m   172.21.20.51   kubeworker               
kube-system   kube-proxy-9p9z7                           1/1     Running   0          27m   172.21.20.50   kubemaster               
kube-system   kube-scheduler-kubemaster                  1/1     Running   0          27m   172.21.20.50   kubemaster               
kube-system   kubernetes-dashboard-76b866f6cf-xfnm7      1/1    Running   0          25m   172.21.20.51   kubeworker
kube-system   nginx-proxy-kubeworker                     1/1     Running   0          26m   172.21.20.51   kubeworker               
kube-system   nodelocaldns-kr7q5                         1/1     Running   0          25m   172.21.20.50   kubemaster               
kube-system   nodelocaldns-plh7m                         1/1     Running   0          25m   172.21.20.51   kubeworker               
[root@nrson success_log]#


해당 pod의 logs를 확인해 보면 아래와 같은 로그가 출력되는 것을 확인할 수 있을 것입니다.


...

plugin/loop: Loop (127.0.0.1:55953 -> :1053) detected for zone ".", see https://coredns.io/plugins/loop#troubleshooting. Query: "HINFO 4547991504243258144.3688648895315093531."

...


장애 해결

위와 같은 이슈가 발생하였을 경우 아래와 같은 프로세스로 문제를 해결합니다.

CoreDNS 로그에 Loop ... detected ... 메시지가 포함되어 있으면 루프 감지 플러그인이 업스트림 DNS 서버 중 하나에서 무한 전달 루프를 감지했음을 의미합니다. 무한 루프로 작동하면 호스트가 메모리를 완전히 종료 할 때까지 메모리와 CPU가 반복적으로 소비되므로 CoreDNS에서는 OOMKilled 상태에 빠지고 이는 다시 CrashLoopBackOff 상태로 변경되고 다시 Running...으로 반복 Restart가 진행됩니다.


이와 같은 현상을 유발하는 근본적인 원인은 다음과 같습니다.
1) 가장 일반적 요인으로 CoreDNS의 Query 요청을 127.0.0.1, :: 1 또는 127.0.0.53과 같은 루프백 주소를 통해 자신에게 직접 전달하는 경우입니다.

2) 다음으로 CoreDNS의 Query 요청이 업스트림 서버로 전달되고 다시 CoreDNS로 전달되는 경우입니다.

이와 같이 반복적으로 요청이 Loop를 발생 시킬 경우 CoreDNS에서 OOM 상태에 빠지게 되고 Restart를 유발하게됩니다.

 

이 문제를 해결하기 위해서는 다음 사항을 점검해야 합니다.

1) corefile에서 루프가 감지 된 영역으로 전달되는지 확인하십시오.

2) 로컬 주소나 요청을 다시 CoreDNS로 전달하는 또 다른 DNS 서버가 있는지 확인하십시오.

3) forward가 파일(예 : /etc/resolv.conf)을 사용하는 경우 파일에 로컬 주소가 포함되어 있지 않은지 확인하십시오.

 

Kubernetes에 배포 된 CoreDNS 포드가 루프를 감지하면 CoreDNS 포드가 "CrashLoopBackOff"로 시작됩니다.

이는 앞서 살펴본데로 Kubernetes가 CoreDNS가 루프를 감지하고 종료 할 때마다 포드를 다시 시작하려고하기 때문입니다.

Kubernetes 클러스터에서 루프 전달의 일반적인 원인은 루프백 주소 127.0.0.53을 네임 서버로 /etc/resolv.conf에 포함하였을 경우입니다. 기본적으로 kubelet을 통해 Kubernetes는 기본 dnsPolicy를 사용하여 이 /etc/resolv.conf 파일을 모든 포드에 전달하여 DNS 조회를 수행 할 수 없게 합니다. CoreDNS는이 /etc/resolv.conf를 업스트림 목록으로 사용하여 요청을 전달합니다. 루프백 주소가 포함되어 있기 때문에 CoreDNS는 요청을 자신에게 전달합니다.

이후 동작은 앞선 설명과 동일하게 OOMKilled & CrashLoopBackOff & Running 상태를 반복하게 됩니다.

이 문제를 해결하는 방법에는 여러 가지가 있지만 다음과 같은 경우를 따라해 보시기 바랍니다.
- kubelet yaml 파일에 resolvConf: <path-to-your-real-resolv-conf-file>를 추가하십시오. "실제" resolv.conf는 업스트림 서버의 실제 IP를 포함하고 로컬 / 루프백 주소가 없는 것입니다. 이 플래그는 kubelet에게 대체 resolv.conf를 포드에 전달하도록 지시할 수 있습니다.
- 호스트 노드에서 로컬 DNS 캐시를 비활성화하고 /etc/resolve.conf를 원본으로 복원하십시오.
- 업스트림 DNS의 IP 주소가 있는 /etc/resolv.conf를 직접 수정합니다.

 

즉 현재 Kubelet이 기동되는 서버에 구성된 DNS 정보가 자기 자신 (127.0.0.1 등)을 바라보고 있지는 않은지 검토 후 /etc/resolv.conf를 수정하여 해결하도록 조치해야 합니다.

728x90
반응형