スキップしてコンテンツを表示

EKS クラスターに NodeLocalDNS をインストールして問題をトラブルシューティングする方法を教えてください。

所要時間4分
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 のクラスタードメインに置き換えます。クラスターのリンクローカル IP アドレスが異なる場合は、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 のクラスタードメインに置き換えます。クラスターのリンクローカル IP アドレスが異なる場合は、169.254.20.10 を実際のリンクローカル IP に置き換えてください。IPVS モードでは、NodeLocalDNS を使用するようにポッドを設定する必要があります。「NodeLocalDNS を使用するようにポッドを設定する (IPVS モードのみ)」セクションを参照してください。

  6. NodeLocalDNS マニフェストを適用するには、次のコマンドを実行します。

    kubectl apply -f nodelocaldns.yaml
  7. NodeLocalDNS ポッドが Running ステータスになっていることを確認するには、次のコマンドを実行します。

    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

    注: 出力には、NodeLocalDNS のリンクローカル IP アドレスとして 169.254.20.10 が表示されています。

注: デプロイを自動化するには、起動テンプレートの 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 コマンドラインインターフェイス (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 から目的のポートに置き換えてください。クラスターのリンクローカル IP アドレスが異なる場合は、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. livenessProbe セクションと readinessProbe セクションを見つけて、新しいヘルスチェックポートに一致するようにポートを更新してください。

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" というエラーメッセージが表示される場合は、少なくとも 1 つの 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

関連情報

Using CoreDNS for Service Discovery (サービス検出に CoreDNS を使用する)(Kubernetes ウェブサイト)

Run kube-proxy in IPVS Mode (IPVS モードで kube-proxy を実行する)(Kubernetes ウェブサイト)

EKS Auto Mode を使用してクラスターインフラストラクチャを自動化する

Amazon EKS クラスターのネットワーキングアドオンを管理する

AWS公式更新しました 4ヶ月前
コメントはありません

関連するコンテンツ