내용으로 건너뛰기

EKS 클러스터에 NodeLocalDNS를 설치하고 문제를 해결하려면 어떻게 해야 합니까?

7분 분량
0

Amazon Elastic Kubernetes Service(Amazon EKS) 클러스터에 NodeLocalDNS를 설치하고 문제를 해결하고 싶습니다.

해결 방법

사전 요구 사항:

NodeLocalDNS 설치

NodeLocalDNS는 링크-로컬 IP 주소를 사용하여 각 노드에 DNS 캐싱을 제공합니다. 링크-로컬 주소는 네트워크 세그먼트 내에서만 유효한 169.254.0.0/16 범위의 IP 주소입니다.

참고: NodeLocalDNS의 표준 링크-로컬 IP 주소는 169.254.20.10입니다. 환경에 특정 충돌이 발생하지 않는 한 이 값을 변경하지 마십시오.

Amazon EKS 클러스터에 NodeLocalDNS를 설치하려면 다음 단계를 완료하십시오.

  1. 다음 curl 명령을 실행하여 Kubernetes 리포지토리에서 NodeLocalDNS 매니페스트를 다운로드합니다.

    curl -Lo nodelocaldns.yaml.template https://raw.githubusercontent.com/kubernetes/kubernetes/master/cluster/addons/dns/nodelocaldns/nodelocaldns.yaml
  2. 클러스터의 kube-dns 서비스 IP 주소를 검색하려면 다음 명령을 실행합니다.

    kubectl get svc kube-dns -n kube-system -o jsonpath='{.spec.clusterIP}'

    참고: 출력의 IP 주소를 기록해 둡니다.

  3. 클러스터의 도메인을 검색하려면 다음 명령을 실행합니다.

    kubectl get configmap coredns -n kube-system -o yaml | grep 'kubernetes'

    출력에 클러스터 도메인이 표시됩니다.

  4. kube-proxy 모드를 확인하려면 다음 명령을 실행합니다.

    kubectl get configmap kube-proxy-config -n kube-system -o yaml | grep mode

    출력에 iptables 또는 ipvs가 모드 값으로 표시됩니다.

  5. kube-proxy 모드를 기반으로 NodeLocalDNS 매니페스트를 편집합니다.

    iptables 모드의 경우 다음 명령을 사용하여 매니페스트를 편집합니다.

    # Set environment variables for node-local-dns
    kubedns=$(kubectl get svc kube-dns -n kube-system -o jsonpath={.spec.clusterIP})
    domain=cluster.local
    localdns=`169.254.20.10`
    
    # Update the manifest with your cluster's specific values:
    sed "s/__PILLAR__LOCAL__DNS__/$localdns/g; s/__PILLAR__DNS__DOMAIN__/$domain/g; s/__PILLAR__DNS__SERVER__/$kubedns/g" nodelocaldns.yaml.template > nodelocaldns.yaml

    참고: 클러스터가 다른 도메인을 사용하는 경우 cluster.local을 3단계의 클러스터 도메인으로 바꾸십시오. 169.254.20.10을 클러스터의 링크-로컬 IP 주소로 바꾸십시오(다른 경우).

    IPVS 모드의 경우 다음 명령을 사용하여 매니페스트를 편집합니다.

    # Set environment variables for node-local-dns
    kubedns=$(kubectl get svc kube-dns -n kube-system -o jsonpath={.spec.clusterIP})
    domain=cluster.local
    localdns=169.254.20.10
    
    # Update the manifest with your cluster's specific values:
    sed "s/__PILLAR__LOCAL__DNS__/$localdns/g; s/__PILLAR__DNS__DOMAIN__/$domain/g; s/,__PILLAR__DNS__SERVER__//g; s/__PILLAR__CLUSTER__DNS__/$kubedns/g" nodelocaldns.yaml.template > nodelocaldns.yaml

    참고: 클러스터가 다른 도메인을 사용하는 경우 cluster.local을 3단계의 클러스터 도메인으로 바꾸십시오. 169.254.20.10을 클러스터의 링크-로컬 IP 주소로 바꾸십시오(다른 경우). IPVS 모드에서는 NodeLocalDNS를 사용하도록 포드를 구성해야 합니다. "NodeLocalDNS를 사용하도록 포드 구성(IPVS 모드 전용)" 섹션을 참조하십시오.

  6. NodeLocalDNS 매니페스트를 적용하려면 다음 명령을 실행합니다.

    kubectl apply -f nodelocaldns.yaml
  7. NodeLocalDNS 포드가 실행 중 상태인지 확인하려면 다음 명령을 실행합니다.

    kubectl get pods -n kube-system -l k8s-app=node-local-dns

NodeLocalDNS를 사용하도록 포드 구성(IPVS 모드 전용)

중요: 이 섹션은 클러스터가 kube-proxy에 IPVS 모드를 사용하는 경우에만 적용됩니다. 클러스터가 iptables 모드를 사용하는 경우 DNS 트래픽은 자동으로 NodeLocalDNS로 리디렉션됩니다.

IPVS 모드 클러스터의 경우 NodeLocalDNS를 사용하도록 포드를 수동으로 구성해야 합니다. 포드를 NodeLocalDNS로 보내려면 kubelet을 사용하여 개별 포드를 구성하거나 클러스터를 구성하면 됩니다.

개별 포드 구성

개별 포드를 구성하려면 포드 사양에 다음 구성을 추가하십시오.

spec:
  dnsPolicy: "None"
  dnsConfig:
    nameservers:
      - [169.254.20.10]
    searches:
      - default.svc.cluster.local
      - svc.cluster.local
      - cluster.local
    options:
      - name: ndots
        value: "5"

참고: 169.254.20.10을 클러스터의 링크-로컬 IP 주소로 바꾸십시오. 클러스터가 다른 도메인을 사용하는 경우 cluster.local을 클러스터 도메인으로 바꾸십시오.

kubelet을 사용하여 클러스터 구성

IPVS 모드에서 NodeLocalDNS는 링크-로컬 주소인 169.254.20.10에서만 수신 대기합니다. 이 링크-로컬 주소를 가리키도록 kubelet 구성을 수정해야 합니다.

클러스터의 모든 포드가 NodeLocalDNS를 사용하도록 구성하고 각 노드의 kubelet 구성을 수정하려면 다음 단계를 완료하십시오.

  1. kubelet 구성 파일을 편집합니다. 다음 구성을 사용하십시오.

    {  "clusterDNS": ["169.254.20.10"],
      "clusterDomain": "cluster.local"
    }

    참고: 169.254.20.10을 클러스터의 링크-로컬 IP 주소로 바꾸십시오. 클러스터가 다른 도메인을 사용하는 경우 cluster.local을 클러스터 도메인으로 바꾸십시오.

  2. 각 노드에서 kubelet 서비스를 다시 시작하려면 다음 sudo 명령을 실행합니다.

    sudo systemctl restart kubelet
  3. kubelet 구성을 확인하려면 다음 명령을 실행합니다.

    cat /etc/kubernetes/kubelet/config.json | grep clusterDNS

    참고: 출력에 169.254.20.10이 NodeLocalDNS 링크-로컬 IP 주소로 표시됩니다.

참고: 자동 배포의 경우 시작 템플릿의 userdata 섹션에서 kubelet 구성을 수정할 수 있습니다. 자세한 내용은 AL2023 Amazon EKS 노드에서 사용자 지정 사용자 데이터를 사용하려면 어떻게 해야 합니까?를 참조하십시오.

NodeLocalDNS를 올바르게 설치했는지 확인

NodeLocalDNS가 제대로 작동하는지 확인하려면 다음 단계를 완료하십시오.

  1. 테스트 포드를 만들려면 다음 명령을 실행합니다.

    kubectl run test-dns --image=busybox:1.28 --restart=Never --rm -it -- nslookup kubernetes.default
  2. NodeLocalDNS 포드에 CrashLoopBackOff 상태가 있고 포트 53이 이미 사용 중임을 나타내는 오류가 있는 경우에는 출력을 검토하여 DNS 쿼리가 올바르게 해결되었는지 확인합니다.

  3. DNS 쿼리가 NodeLocalDNS를 사용하고 있는지 확인하려면 다음 명령을 실행합니다.

    kubectl logs -n kube-system -l k8s-app=node-local-dns --tail=50

    로그에는 NodeLocalDNS에서 처리 중인 DNS 쿼리가 표시됩니다.

    참고: 기본적으로 NodeLocalDNS에서는 로깅이 활성화되지 않습니다. 로그를 보려면 node-local-dns ConfigMap에서 로깅을 활성화하십시오.

    # kubectl edit configmaps -n kube-system node-local-dns
    apiVersion: v1
    kind: ConfigMap
    metadata:
      name: node-local-dns
      namespace: kube-system
    data:
      Corefile: |
        cluster.local:53 {
           log  # Enable logging
           errors
           cache 30
           ...
        }

NodeLocalDNS 문제 해결

참고: AWS Command Line Interface(AWS CLI) 명령을 실행할 때 오류가 발생하면 AWS CLI의 오류 해결을 참조하십시오. 또한 최신 AWS CLI 버전을 사용하고 있는지 확인하십시오.

포트 충돌로 인한 CrashLoopBackOff 오류 해결

NodeLocalDNS 포드가 포트 53 오류와 함께 CrashLoopBackOff로 전환되는 경우가 있는데, 그 이유는 Amazon EKS 자동 모드 노드가 포트 53을 예약하기 때문입니다. 이 문제를 해결하려면 다음 방법 중 하나를 선택하십시오.

방법 1: 자동 모드 노드를 제외하는 노드 선호도 규칙 추가

다음 단계를 완료하십시오.

  1. NodeLocalDNS daemonset를 편집합니다.

    kubectl edit daemonset node-local-dns -n kube-system
  2. spec.template.spec 아래에 다음과 같은 선호도 구성을 추가합니다.

    affinity:
      nodeAffinity:
        requiredDuringSchedulingIgnoredDuringExecution:
          nodeSelectorTerms:
          - matchExpressions:
            - key: eks.amazonaws.com/compute-type
              operator: NotIn
              values:
              - auto
  3. 변경 사항을 저장한 다음 포드가 성공적으로 다시 시작되는지 확인합니다.

방법 2: NodeLocalDNS ConfigMap을 수정하여 상태 확인 포트 변경

다음 단계를 완료하십시오.

  1. 현재 NodeLocalDNS ConfigMap을 보려면 다음 명령을 실행합니다.

    kubectl get configmap node-local-dns -n kube-system -o yaml
  2. ConfigMap을 편집하여 상태 확인 포트를 변경하려면 다음 명령을 실행합니다.

    kubectl edit configmap node-local-dns -n kube-system
  3. ConfigMap에서 상태 플러그인 구성을 찾아 포트를 수정합니다. ConfigMap 구조는 다음과 같습니다.

    apiVersion: v1
    kind: ConfigMap
    metadata:
      name: node-local-dns
      namespace: kube-system
    data:
      Corefile: |
        cluster.local:53 {
           errors
           cache {
              success 9984 30
              denial 9984 5
           }
           reload
           loop
           bind IP_ADDRESS
           forward. __PILLAR__CLUSTER__DNS__ {
              force_tcp
           }
           prometheus :9253
           health 169.254.20.10:8081
        }

    참고: health 줄의 포트 8081을 원하는 포트로 바꾸십시오. 169.254.20.10을 클러스터의 링크-로컬 IP 주소로 바꾸십시오(다른 경우).

  4. 변경 사항을 저장합니다.

  5. NodeLocalDNS 포드를 다시 시작하려면 다음 명령을 실행합니다.

    kubectl rollout restart daemonset node-local-dns -n kube-system
  6. daemonset 상태 확인 구성을 새 포트와 일치하도록 업데이트하려면 다음 명령을 실행합니다.

    kubectl edit daemonset node-local-dns -n kube-system
  7. livenessProbereadinessProbe 섹션을 찾아 새 상태 확인 포트와 일치하도록 포트를 업데이트합니다.

DNS 쿼리 제한 시간 오류 해결

포드에 DNS 쿼리 제한 시간 오류가 발생하는 경우 보안 그룹과 네트워크 ACL이 포트 53에서 TCP 및 UDP 트래픽을 허용하는지 확인하십시오. 이 트래픽은 포드 간 통신에 필요합니다.

다음 단계를 완료하십시오.

  1. 노드에 연결된 보안 그룹을 파악하려면 다음과 같은 describe-instances AWS CLI 명령을 실행합니다.

    aws ec2 describe-instances --filters "Name=tag:eks:cluster-name,Values=YOUR-CLUSTER-NAME" --query "Reservations[*].Instances[*].SecurityGroups[*].[GroupId,GroupName]" --output table

    참고: YOUR-CLUSTER-NAME을 Amazon EKS 클러스터 이름으로 바꾸십시오.

  2. Amazon EC2 콘솔을 엽니다.

  3. 탐색 창에서 보안 그룹을 선택합니다.

  4. 이 섹션의 1단계에서 파악한 보안 그룹을 선택합니다.

  5. 인바운드 규칙 탭을 선택합니다.

  6. 포드 CIDR 범위의 포트 53에서 TCP 및 UDP 트래픽을 허용하는 규칙이 있는지 확인합니다.
    참고: 규칙이 없는 경우 인바운드 규칙 편집을 선택합니다. 그런 다음 소스를 포드 CIDR 범위로 설정한 상태로 포트 53에 TCP 및 UDP에 대한 규칙을 추가합니다.

"Connection refused" 오류 메시지 해결

포드에서 NodeLocalDNS를 사용하려고 할 때 "Connection refused" 오류 메시지가 표시되면 CoreDNS 포드가 하나 이상 실행되고 있는지 확인하십시오.

CoreDNS 포드 상태를 확인하려면 다음 명령을 실행합니다.

kubectl get pods -n kube-system -l k8s-app=kube-dns

실행 중인 CoreDNS 포드가 없거나 포드가 실패 상태인 경우 CoreDNS 배포를 다시 시작합니다. 배포를 다시 시작하려면 다음 명령을 실행합니다.

kubectl rollout restart deployment coredns -n kube-system

CoreDNS 포드가 실행 중인지 확인하려면 다음 명령을 실행합니다.

kubectl get pods -n kube-system -l k8s-app=kube-dns -w

CoreDNS 포드가 실행된 후 NodeLocalDNS daemonset을 다시 시작하려면 다음 명령을 실행합니다.

kubectl rollout restart daemonset node-local-dns -n kube-system

관련 정보

Kubernetes 웹 사이트의 Using CoreDNS for Service Discovery

Kubernetes 웹 사이트의 Run kube-proxy in IPVS Mode

EKS 자율 모드로 클러스터 인프라 자동화

Amazon EKS 클러스터용 네트워킹 추가 기능 관리

AWS 공식업데이트됨 4달 전
댓글 없음