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

注: ポッドの DNS 設定は、ポッド仕様の dnsPolicy フィールドで管理できます。このフィールドにデータが入力されていない場合、デフォルトで 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_IP を、以前に使用した kubectl から取得したエンドポイント IP の 1 つに置き換えます。

デバッグ用に coreDNS ポッドからより詳細なログを取得する

1.    CoreDNS ポッドのデバッグログを有効にし、log plugin を 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 が設定を再ロードするのに数分かかる場合があります。ポッドを 1 つずつ再起動して、変更をすぐに適用できます。

3.    CoreDNS ログが失敗しているか、アプリケーションポッドからヒットを取得しているかどうかを確認するには、次のコマンドを実行します。

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

検索と ndots の組み合わせ

DNS は、名前解決に nameserver を使用します (通常は kube-dns サービスのクラスター IP)。DNS は search を使用して、クエリ名を補完して完全修飾ドメイン名にします。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 ポッドが処理しきれない可能性があります。

この問題を解決するには、ndots を (単一のドットのみを検索する) 1 に変更するか、クエリまたは使用されたドメインの末尾にドット (.) を追加します。

nslookup example.com.

VPC リゾルバー (AmazonProvidedDNS) の制限に注意する

VPC リゾルバーは、ネットワークインターフェイスごとに 1024 パケット/秒のハード制限のみを受容できます。複数の CoreDNS ポッドが同じワーカーノード上にある場合、この制限に達する可能性は、外部ドメインクエリの方が高くなります。

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

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

この記事はお役に立ちましたか?

改善できることはありますか?


さらにサポートが必要な場合