Amazon EKS 관련 DNS 오류를 해결하려면 어떻게 해야 합니까?

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

Amazon Elastic Kubernetes Service(Amazon EKS) 클러스터에서 CoreDNS를 사용하는 애플리케이션 또는 포드가 내부 또는 외부 DNS 이름 확인에 실패합니다.

간략한 설명

Amazon EKS 클러스터 내에서 실행 중인 포드가 CoreDNS 서비스의 클러스터 IP를 내부 및 외부 DNS 레코드를 쿼리하기 위한 기본 이름 서버로 사용합니다. CoreDNS 포드, 서비스 구성 또는 연결에 문제가 있는 경우 애플리케이션이 DNS 확인에 실패할 수 있습니다.

CoreDNS 포드가 kube-dns라는 서비스 객체에 의해 추상화됩니다. CoreDNS 포드 관련 문제를 해결하려면 kube-dns 서비스의 모든 구성 요소가 작동하는지 확인해야 합니다. 이러한 구성 요소에는 서비스 엔드포인트 옵션과 iptables 규칙이 포함되지만 이에 국한되지는 않습니다.

해결 방법

다음 해결 방법은 CoreDNS ClusterIP 10.100.0.10에 적용됩니다.

1.    CoreDNS 서비스의 ClusterIP를 가져오려면 다음 명령을 실행합니다.

kubectl get service kube-dns -n kube-system

2.    DNS 엔드포인트가 노출되고 CoreDNS 포드를 가리키는지 확인하려면 다음 명령을 실행합니다.

kubectl -n kube-system get endpoints kube-dns

다음과 유사한 출력이 표시됩니다.

NAME       ENDPOINTS                                                        AGE
kube-dns   192.168.2.218:53,192.168.3.117:53,192.168.2.218:53 + 1 more...   90d

참고: 엔드포인트 목록이 비어 있는 경우 CoreDNS 포드의 포드 상태를 확인하십시오.

3.    CoreDNS와 통신할 때 보안 그룹 또는 네트워크 ACL(액세스 제어 목록)에 의해 포드가 차단되지 않았는지 확인합니다.

자세한 내용은 Amazon EKS의 다른 포드에 내 포드가 연결되지 않는 이유는 무엇입니까?를 참조하십시오.

kube-proxy 포드가 작동하는지 확인

kube-proxy 포드가 EKS 클러스터의 API 서버에 액세스할 수 있는지 확인하려면 로그를 점검하여 제어 영역에 대한 제한 시간 오류 또는 403 권한 없음 오류가 있는지 확인할 수 있습니다.

kube-proxy 로그를 가져오려면 다음 명령을 실행합니다.

kubectl logs -n kube-system --selector 'k8s-app=kube-proxy'

참고: kube-proxy는 제어 영역에서 엔드포인트를 가져오고 모든 작업자 노드에서 iptables 규칙을 생성합니다.

애플리케이션 포드에 연결하여 DNS 문제 해결

1.    애플리케이션 포드 내에서 명령을 실행하려면 다음 명령을 실행하여 실행 중인 포드 내의 셸에 액세스합니다.

$ kubectl exec -it your-pod-name -- sh

다음과 유사한 오류가 발생할 경우 애플리케이션 포드에 사용 가능한 셸 바이너리가 없을 수 있습니다.

OCI runtime exec failed: exec failed: container_linux.go:348: starting container process caused "exec: \"sh\": executable file not found in $PATH": unknown
command terminated with exit code 126

디버깅하려면 매니페스트 파일에 사용된 이미지를 업데이트하여 다른 이미지(예: busybox 이미지)를 사용할 수 있습니다.

2.    kube-dns 서비스의 클러스터 IP가 포드의 /etc/resolv.conf에 있는지 확인하려면 포드 내부의 셸에서 다음 명령을 실행합니다.

cat /etc/resolv.conf

다음 예제 resolv.conf는 DNS 요청에 대해 10.100.0.10을 가리키도록 구성된 포드를 보여 줍니다. IP는 kube-dns 서비스의 ClusterIP와 일치해야 합니다.

nameserver 10.100.0.10
search default.svc.cluster.local svc.cluster.local cluster.local ec2.internal
options ndots:5

참고: 포드 사양에서 dnsPolicy 필드를 사용하여 포드의 DNS 구성을 관리할 수 있습니다. 이 필드가 채워지지 않으면 기본적으로 ClusterFirst DNS 정책이 사용됩니다.

3.    포드가 기본 clusterIP를 사용하여 내부 도메인을 확인할 수 있는지 확인하려면 포드 내부의 셸에서 다음 명령을 실행합니다.

nslookup kubernetes 10.100.0.10

다음과 유사한 출력이 표시됩니다.

Server:     10.100.0.10
Address:    10.100.0.10#53
Name:       kubernetes.default.svc.cluster.local
Address:    10.100.0.1

4.    포드가 기본 clusterIP를 사용하여 외부 도메인을 확인할 수 있는지 확인하려면 포드 내부의 셸에서 다음 명령을 실행합니다.

nslookup amazon.com 10.100.0.10

다음과 유사한 출력이 표시됩니다.

Server:     10.100.0.10
Address:    10.100.0.10#53
Non-authoritative answer:
Name:   amazon.com
Address: 176.32.98.166
Name:    amazon.com
Address: 205.251.242.103
Name:    amazon.com
Address: 176.32.103.205

5.    포드가 CoreDNS 포드의 IP 주소를 직접 사용하여 확인할 수 있는지 확인하려면 포드 내부의 셸에서 다음 명령을 실행합니다.

nslookup kubernetes COREDNS_POD_IP
nslookup amazon.com COREDNS_POD_IP

참고: COREDNS_POD_IPkubectl get 엔드포인트의 엔드포인트 IP 중 하나로 바꾸십시오.

디버깅을 위해 coreDNS 포드에서 더 자세한 로그 가져오기

1.    CoreDNS 포드의 디버그 로그를 활성화하고 CoreDNS ConfigMap에 로그 플러그인을 추가하려면 다음 명령을 실행합니다.

kubectl -n kube-system edit configmap coredns

2.    출력에 나타나는 편집기 화면에서 로그 문자열을 추가합니다. 다음 예제를 참조하십시오.

kind: ConfigMap
apiVersion: v1
data:
  Corefile: |
    .:53 {
        log    # Enabling CoreDNS Logging
        errors
        health
        kubernetes cluster.local in-addr.arpa ip6.arpa {
          pods insecure
          upstream
          fallthrough in-addr.arpa ip6.arpa
        }
        ...
...

참고: CoreDNS가 구성을 다시 로드하는 데 몇 분 정도 걸릴 수 있습니다. 창을 하나씩 다시 시작하여 변경 사항을 즉시 적용할 수 있습니다.

3.    CoreDNS 로그가 실패하거나 애플리케이션 포드에서 적중이 발생하는지 확인하려면 다음 명령을 실행합니다.

kubectl logs --follow -n kube-system --selector 'k8s-app=kube-dns'

검색 및 ndots 조합

DNS는 이름 확인을 위해 nameserver를 사용합니다(일반적으로 kube-dns 서비스의 클러스터 IP). DNS는 정규화된 도메인 이름에 대한 쿼리 이름을 작성하기 위해 검색을 사용합니다. workerNode에 대한 검색 도메인이 포함됩니다. ndots 값은 초기 절대 쿼리가 수행되기 전에 쿼리를 해결하기 위해 이름에 표시되어야 하는 점의 수입니다.

예를 들어 정규화되지 않은 도메인 이름에서 ndots 옵션을 기본값 5로 설정할 수 있습니다. 그러면 내부 도메인 cluster.local에 속하지 않는 모든 외부 도메인이 쿼리 전에 검색 도메인에 추가됩니다.

애플리케이션 포드의 /etc/resolv.conf 설정과 함께 다음 예제를 참조하십시오.

nameserver 10.100.0.10
search default.svc.cluster.local svc.cluster.local cluster.local ec2.internal
options ndots:5

CoreDNS는 쿼리되는 도메인에서 점 5개를 찾습니다. 포드가 amazon.com에 대한 DNS 확인을 호출하는 경우 로그가 다음과 같이 표시됩니다.

[INFO] 192.168.3.71:33238 - 36534 "A IN amazon.com.default.svc.cluster.local. udp 54 false 512" NXDOMAIN qr,aa,rd 147 0.000473434s
[INFO] 192.168.3.71:57098 - 43241 "A IN amazon.com.svc.cluster.local. udp 46 false 512" NXDOMAIN qr,aa,rd 139 0.000066171s
[INFO] 192.168.3.71:51937 - 15588 "A IN amazon.com.cluster.local. udp 42 false 512" NXDOMAIN qr,aa,rd 135 0.000137489s
[INFO] 192.168.3.71:52618 - 14916 "A IN amazon.com.ec2.internal. udp 41 false 512" NXDOMAIN qr,rd,ra 41 0.001248388s
[INFO] 192.168.3.71:51298 - 65181 "A IN amazon.com. udp 28 false 512" NOERROR qr,rd,ra 106 0.001711104s

참고: NXDOMAIN은 도메인 레코드를 찾을 수 없음을 의미하고, NOERROR는 도메인 레코드를 찾았음을 의미합니다.

마지막에 절대 도메인에서 최종 호출이 이루어지기 전에 모든 검색 도메인 앞에 amazon.com이 추가됩니다. 최종 도메인 이름 끝에 점(.)이 추가되어 정규화된 도메인 이름이 됩니다. 즉, 모든 외부 도메인 이름 쿼리에 대해 4~5개의 추가 호출이 있을 수 있으며, 이는 CoreDNS 포드에 과부하를 야기할 수 있습니다.

이 문제를 해결하려면 ndot1(하나의 점만 찾음)로 변경하거나 쿼리되거나 사용되는 도메인의 끝에 점(.)을 추가하십시오.

nslookup example.com.

VPC 해석기(AmazonProvidedDNS) 제한에 유의

VPC 해석기는 네트워크 인터페이스 하나에 초당 1,024개의 패킷의 최대 하드 제한만 허용할 수 있습니다. 동일한 작업자 노드에 두 개 이상의 CoreDNS 포드가 있으면 외부 도메인 쿼리의 경우 이 제한에 도달할 확률이 더 높습니다.

PodAntiAffinity 규칙을 사용하여 별도의 인스턴스에서 CoreDNS 포드를 예약하려면 CoreDNS 배포에 다음 옵션을 추가하십시오.

spec:
  affinity:
    podAntiAffinity:
      preferredDuringSchedulingIgnoredDuringExecution:
      - labelSelector:
          matchExpressions:
          - key: k8s-app
            operator: In
            values:
            - kube-dns
        topologyKey: kubernetes.io/hostname

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

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


도움이 필요하십니까?