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

Amazon EKS で DNS の障害をトラブルシューティングする方法を教えてください。

所要時間5分
0

Amazon Elastic Kubernetes Service (Amazon EKS) クラスターで CoreDNS を使用しているアプリケーションまたはポッドが、内部または外部の DNS 名前解決に失敗しています。

簡単な説明

Amazon EKS クラスター内で実行するポッドは、CoreDNS クラスター IP アドレスをネームサーバーとして使用し、内部および外部 DNS レコードをクエリします。CoreDNS ポッド、サービス設定、または接続に問題がある場合、アプリケーションは DNS 解決に失敗することがあります。

kube-dns サービスオブジェクトは CoreDNS ポッドを抽象化します。CoreDNS ポッドの問題をトラブルシューティングするには、サービスエンドポイントオプションや iptables ルールなど、kube-dns サービスのすべてのコンポーネントが機能していることを確認します。

解決策

注: 次の解決方法では、CoreDNS ClusterIP 値は 10.100.0.10 です。

DNS 設定を確認するには、次の手順を実行します。

  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. セキュリティグループとネットワークアクセスコントロールリスト (ネットワーク ACL) が CoreDNS と通信するときにポッドをブロックしていないことを確認します。

詳細については、「私のポッドが Amazon EKS の他のポッドに接続できない理由は何ですか?」を参照してください。

kube-proxy ポッドが機能していることを確認する

ログでコントロールプレーンに対するタイムアウトエラーをチェックして、kube-proxy ポッドがクラスターの API サーバーにアクセスできることを確認します。また、403 不正エラーがないことを確認します。

kube-proxy ログを取得するには、次のコマンドを実行します。

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

注: kube-proxy は、コントロールプレーンからエンドポイントを取得し、各ノードで iptables ルールを作成します。

問題が発生した時点の CoreDNS ポッドの CPU 使用率を確認する

Amazon EKS CoreDNS アドオンは CoreDNS ポッドのメモリに 170 MiB クォータのみを追加します。CoreDNS ポッドは CPU クォータを定義していないため、コンテナは実行中のノードで使用可能なすべての CPU リソースを使用できます。ノードの CPU 使用率が 100% の場合、Amazon EKS アプリケーションログに DNS タイムアウトエラーが発生する可能性があります。これは、CoreDNS ポッドにすべての DNS クエリを管理するのに十分な CPU リソースがないためです。

CoreDNS ポッドの現在の CPU とメモリの使用状況を確認するには、次のコマンドを実行します。

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

Amazon EKS クラスターノードの現在の CPU とメモリの使用状況を確認するには、次のコマンドを実行します。

kubectl top nodes

アプリケーションポッドに接続して DNS の問題をトラブルシューティングする

次の手順を実行します。

  1. アプリケーションポッド内でコマンドを実行するには、次のコマンドを実行します。

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

    注: your-pod-name は、実際のポッド名に置き換えます。
    上記のコマンドでは、実行中のポッド内のシェルにアクセスできます。アプリケーションポッドに利用可能なシェルバイナリがない場合、次の例のようなエラーが表示されます。
    "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"
    この問題を解決するには、pod-manifest.yaml マニフェストファイルで使用するイメージを別のイメージで更新します。イメージの例としては、Docker のウェブサイトの 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

    注: ポッドの DNS 設定は、ポッド仕様の dnsPolicy フィールドで管理できます。このフィールドに値を入力しない場合、Amazon EKS はデフォルトで ClusterFirst DNS ポリシーを使用します。ClusterFirst DNS ポリシーの詳細については、Kubernetes のウェブサイトの「Pod's DNS policy (ポッドの DNS ポリシー)」を参照してください。

  3. ポッドがデフォルトの ClusterIP 値を使用して内部ドメインを解決できることを確認するには、ポッドシェルで次のコマンドを実行します。

    nslookup kubernetes.default 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. kube-dns ログを取得するには、次のコマンドを実行します。

    kubectl get endpoints kube-dns -n kube-system
  6. ポッドが CoreDNS ポッドの IP アドレスを使用して直接解決できることを確認するには、ポッドシェルで次のコマンドを実行します。

    nslookup kubernetes COREDNS_POD_IP
    nslookup amazon.com COREDNS_POD_IP

    注: COREDNS_POD_IPkube-dns エンドポイントの IP アドレスに置き換えてください。

CoreDNS ポッドからより詳細なログを取得して、さらなる問題をデバッグする

次の手順を実行します。

  1. CoreDNS ポッドのデバッグログを有効にし、ログプラグインを CoreDNS ConfigMap に追加するには、次のコマンドを実行します。
    kubectl -n kube-system edit configmap coredns
    注: 詳細については、CoreDNS のウェブサイトの「log」を参照してください。
  2. コマンド出力のエディタ画面で、次のログ文字列を追加します。
    kind: ConfigMap
    apiVersion: v1
    data:
      Corefile: |
        .:53 {
            log    # Activating CoreDNS Logging
            errors
            health
            kubernetes cluster.local in-addr.arpa ip6.arpa {
              pods insecure
              upstream
              fallthrough in-addr.arpa ip6.arpa
            }
            ...
    ...
    注: CoreDNS 設定のリロードには数分かかります。変更をすぐに適用するには、ポッドを 1 つずつ再起動します。
  3. CoreDNS ログが失敗していないか、またはアプリケーションポッドからトラフィックを取得しているかを確認するには、次のコマンドを実行します。
    kubectl logs --follow -n kube-system --selector 'k8s-app=kube-dns'

ndots 値を更新する

ndots 値は、最初の絶対クエリが行われる前にクエリを解決するためにドメイン名に表示される必要があるドットの数です。例えば、完全修飾されていないドメイン名では ndots をデフォルトの 5 に設定できます。このシナリオでは、内部ドメイン cluster.local に分類されないすべての外部ドメインが、クエリを実行する前に検索ドメインに追加されます。

次の例では、アプリケーションポッドの /etc/resolv.conf ファイル設定を使用しています。

nameserver 10.100.0.10search 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 ポッドが処理しきれない可能性があります。

この問題を解決するには、ndots1 に変更して 1 つのドットだけを探すようにします。または、クエリするまたは使用するドメインの末尾にドットを付けます。例:

nslookup example.com.

AmazonProvidedDNS VPC リゾルバークォータを確認する

Amazon Virtual Private Cloud (Amazon VPC) リゾルバーは、各 Elastic Network Interface で 1 秒間に最大 1024 パケットのクォータを受け入れることができます。同じノードに複数の CoreDNS ポッドがある場合、外部ドメインクエリでこのクォータに達する可能性があります。

PodAntiAffinity ルールを使用して、別個のインスタンスで CoreDNS ポッドをスケジュールするには、次のオプションを CoreDNS デプロイに追加します。

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

注: PodAntiAffinity の詳細については、Kubernetes のウェブサイトの「Inter-pod affinity and anti-affinity」を参照してください。

tcpdump を使用して Amazon EKS ワーカーノードから CoreDNS パケットをキャプチャする

DNS 解決の問題を診断するには、次の手順を実行して tcpdump ツールを使用してパケットキャプチャを実行します。

  1. CoreDNS ポッドが実行されているワーカーノードを検索するには、次のコマンドを実行します。

    kubectl get pod -n kube-system -l k8s-app=kube-dns -o wide
  2. SSH を使用してワーカーノードに接続し、tcpdump ツールをインストールするには、次のコマンドを実行します。

    sudo yum install tcpdump - y
  3. CoreDNS ポッドプロセス ID をワーカーノード上で検索するには、次のコマンドを実行します。

    ps ax | grep coredns
  4. ワーカーノードから、次のコマンドを実行して、UDP ポート 53 の CoreDNS ポッドネットワークトラフィックのパケットキャプチャを実行します。

    sudo nsenter -n -t PID tcpdump udp port 53
  5. 別のターミナルから、次のコマンドを実行して、CoreDNS サービスとポッド IP アドレスを取得します。

    kubectl describe svc kube-dns -n kube-system

    注: [IP] フィールドにはサービス IP アドレスを、[エンドポイント] フィールドにはポッドの IP アドレスを書き留めておきます。

  6. ポッドを起動して DNS サービスをテストします。次の例では、Ubuntu コンテナイメージを使用しています。

    kubectl run ubuntu --image=ubuntu sleep 1d
    kubectl exec -it ubuntu sh
  7. 次のコマンドを実行して nslookup ツールを使用して amazon.com ドメインに DNS クエリを実行します。

    nslookup amazon.com

    CoreDNS サービスの IP アドレスに対して同じクエリを明示的に実行するには、次のコマンドを実行します。

    nslookup amazon.com COREDNS_SERVICE_IP

    注: COREDNS_SERVICE_IP を実際の CoreDNS サービスの IP アドレスに置き換えてください。
    各 CoreDNS ポッドの IP アドレスに対してクエリを実行するには、次のコマンドを実行します。

    nslookup amazon.com COREDNS_POD_IP

    注: COREDNS_POD_IP を実際の CoreDNS ポッドの IP アドレスに置き換えてください。複数の CoreDNS ポッドを実行する場合は、複数のクエリを実行します。これにより、Amazon EKS はトラフィックをキャプチャしたポッドに少なくとも 1 つのクエリを送信します。

  8. パケットキャプチャの結果を確認します。
    CoreDNS ポッドに対する DNS クエリタイムアウトが発生し、パケットキャプチャにクエリが表示されない場合は、ネットワーク接続を確認します。ワーカーノード間のネットワーク到達可能性を確認してください。
    キャプチャしていないポッドの IP アドレスで DNS クエリのタイムアウトが発生した場合は、関連するワーカーノードで別のパケットキャプチャを実行します。
    パケットキャプチャの結果を保存するには、tcpdump コマンドに -w FILE_NAME フラグを追加します。次の例では、結果を capture.pcap ファイルに書き込みます。

    tcpdump -w capture.pcap udp port 53

関連情報

Kubernetes のウェブサイトの CoreDNS GA for Kubernetes cluster DNS

AWS公式更新しました 1年前
コメントはありません

関連するコンテンツ