curl と wget は aks クラスター内の内部 DNS 名を解決できませんが、nslookup、host、dig は正常に動作します。

curl と wget は aks クラスター内の内部 DNS 名を解決できませんが、nslookup、host、dig は正常に動作します。

Azure 上にマネージド Kubernetes インスタンスがあります。コア DNS が動作しており、DNS ポッドが正常であることは間違いありません。

いくつかのサービスがあります

  1. 1 つのポッドを持つ frontend-service - 静的フロントエンド ファイルを含むイメージ [nginx-alpine]。

  2. backend-service 、ポッド 1 つ - nodejs コードを含むイメージ [ubuntu:20.04]。

バックエンドのポッドから frontend-service または frontend-service.default.svc.cluster.local などの内部 DNS サービス名を解決できませんが、内部 DNS 名の nslookup、host、dig は正しいアドレスに解決されます。バックエンド ポッドは、google.com などの外部 DNS 名も解決できます。

curl http://frontend-service
curl: (6) Could not resolve host: frontend-service

curl http://frontend-service.default.svc.cluster.local
curl: (6) Could not resolve host: frontend-service.default.svc.cluster.local
wget frontend-service
--2020-08-31 23:36:43--  http://frontend-service
Resolving frontend-service (frontend-service)... failed: Name or service not known.
wget: unable to resolve host address 'frontend-service'
/etc/nsswitch.conf shows the below :

passwd:         files
group:          files
shadow:         files
gshadow:        files

hosts:          files dns
networks:       files

protocols:      db files
services:       db files
ethers:         db files
rpc:            db files

フロントエンド サービスのポッドからバックエンド サービスの内部 DNS 名を解決しようとしている間、すべて正常に動作します。

デバッグをいくつか実行し、 coredns と strace のログを確認したところ、 curl の実行中に coredns ポッドへの呼び出しは行われていないことがわかりましたが、 nslook up の実行中にエントリを確認できます。

また、/etc/resolv.conf の設定が正しいことも確認しました。

nameserver 10.3.0.10
search default.svc.cluster.local svc.cluster.local cluster.local tdghymxumodutbxfnz5m2elcog.bx.internal.cloudapp.net
options ndots:5

strace は /etc/resolv.conf を検索するためのエントリを表示しないため、 curl は /etc/resolv.conf をチェックしていません。

編集1

From the backend service pod :
dig frontend-service [It is able to resolve to the correct name server.]


; <<>> DiG 9.16.1-Ubuntu <<>> frontend-service
;; global options: +cmd
;; Got answer:
;; ->>HEADER<<- opcode: QUERY, status: NXDOMAIN, id: 13441
;; flags: qr rd ra; QUERY: 1, ANSWER: 0, AUTHORITY: 1, ADDITIONAL: 1

;; OPT PSEUDOSECTION:
; EDNS: version: 0, flags:; udp: 4096
; OPT=65436: 87 a1 ee 81 04 d8 5a 49 be 0e c4 ed 1d d8 27 41 ("......ZI......'A")
;; QUESTION SECTION:
;frontend-service.            IN      A

;; AUTHORITY SECTION:
.                       30      IN      SOA     a.root-servers.net. nstld.verisign-grs.com. 2020083101 1800 900 604800 86400

;; Query time: 20 msec
;; SERVER: 10.3.0.10#53(10.3.0.10)
;; WHEN: Tue Sep 01 10:48:00 IST 2020
;; MSG SIZE  rcvd: 142

nslookup frontend-service

Server:         10.3.0.10
Address:        10.3.0.10#53

Name:   frontend-service.default.svc.cluster.local
Address: 10.3.0.30
host frontend-service     
frontend-service.default.svc.cluster.local has address 10.3.0.30

編集2

同じ ubuntu:20.04 イメージを使用して段階的にデプロイメントをテストしたかったので、次の操作を実行しました。

アプローチ1

以下のようにクラスター内に一時的なポッドを作成しました。

kubectl run -it --rm test-ubuntu --image=ubuntu:20.04 --restart=Never

Installed curl (7.68) and ran the curl http://frontend-service – This is successful.

これには困惑したので、Dockerfile からすべてのビルド手順を削除し、以下のコマンドのみを使用しました。

アプローチ2

Dockerファイル

FROM ubuntu:20.04
 
EXPOSE 3688
CMD [ "sleep", "infinity" ]

イメージを acr にプッシュし、バックエンド ポッドを再度デプロイしました。

kubectl exec -it <pod-name> /bin/bash

I installed curl (7.68) and ran the curl http://frontend-service – Same error – unable to resolve host.

これは驚くべきことです。同じイメージ、同じ内容で、 kubectl run で実行し、 Dockerfile でデプロイすると、同じバージョン (7.68) の curl を実行すると動作が異なります。

両方のアプローチでstraceのフローを確認したいと思いました。RUNとEXECからstraceリンクを見つけてください。

一時的なポッドから curl を実行する strace。 https://pastebin.com/NthHQacW

Dockerfile を通じてデプロイされたポッドから curl を実行する strace https://pastebin.com/6LCE5NXu

実行してプローブパスを分析した後

cat strace-log | grep open

アプローチ 2 の strace ログに以下の行が欠落していることがわかりました。


2844  openat(AT_FDCWD, "/etc/nsswitch.conf", O_RDONLY|O_CLOEXEC) = 7
2844  openat(AT_FDCWD, "/etc/host.conf", O_RDONLY|O_CLOEXEC <unfinished...>
2844  <... openat resumed>)             = 7
2844  openat(AT_FDCWD, "/etc/resolv.conf", O_RDONLY|O_CLOEXEC) = 7
2844  openat(AT_FDCWD, "/etc/ld.so.cache", O_RDONLY|O_CLOEXEC) = 7
2844  openat(AT_FDCWD, "/lib/x86_64-linux-gnu/libnss_files.so.2", O_RDONLY|O_CLOEXEC) = 7
2844  openat(AT_FDCWD, "/etc/hosts", O_RDONLY|O_CLOEXEC) = 7
2844  openat(AT_FDCWD, "/etc/ld.so.cache", O_RDONLY|O_CLOEXEC <unfinished ...>
2844  <... openat resumed>)             = 7
2844  openat(AT_FDCWD, "/lib/x86_64-linux-gnu/libnss_dns.so.2", O_RDONLY|O_CLOEXEC) = 7

したがって、ポッド内の curl コマンドは /etc/resolv.conf または /etc/nsswitch.conf のどちらも参照しません。

同じクラスター内の同じイメージと同じ curl バージョンを持つ 2 つのポッド内で curl の動作が異なるのはなぜなのか、不思議に思っています。

答え1

多くのオプションを試した後、ポッドを AKS クラスターにデプロイするために使用していたデプロイ構成ファイルをデバッグしようとしました。パス「/var/run」を指しているホスト マウント ベースのボリュームがありました。

ホストマウントを削除すると、curl と wget は期待どおりに動作しました。

この動作について MS サポートと話し合った結果、ホスト マウントがパス "/var/run" を指している場合、curl と wget が DNS 解決のために /etc/resolv.conf ファイルにフォールバックしないのは、curl と wget での DNS プローブの実装方法による可能性があることがわかりました。

関連情報