はじめに
IKS (IBM Kubernetes Service) で hostNetwork を使用した Pod で時々 DNS 遅延が発生していた事象の解決方法を確認しました。
hostNetwork を使用する Pod は多くないと思いますが参考まで記載します。
環境
・IKS (IBM Kubernetes service) 1.20 (Ubuntu 18 base)
・hostNetwork を使用する Pod
deployment の dns policy 元の設定
*deployment 定義の DNS 設定部分のみの抜粋です。
dnsPolicy: ClusterFirst
hostNetwork: true
これをデプロイすると、Pod 内の /etc/resolv.conf は以下の内容になります。
nameserver xx.x.xx.xx #<=DNSサーバー1のIPアドレス
nameserver xx.x.xx.xx #<=DNSサーバー2のIPアドレス
Host OS の定義がコピーされて、kubernetes の kube-dns を使用せず直接DNSサーバーにクエリーする設定が反映されています。
この設定で稼働していると、他サービスへの接続が、dns_lookup で時間がかかっていることが判明しました。
色々調べていると、Linux OS の事象として、glibc のバージョンによっては、/etc/resolv.conf の nameserverが複数ある場合で、並列処理ができずにDNS遅延が発生する事象がネット上でいくつか見かけました。
Ubuntu のマニュアルでオプションの意味を確認すると、ハードウェアによっては応答が1つしか返せないものがあることが記載されています。
・Ubuntu マニュアル : resolv.conf
http://manpages.ubuntu.com/manpages/bionic/ja/man5/resolv.conf.5.html
single-request-reopen (glibc 2.9 以降)
リゾルバは同じソケットを使って A レコードと AAAA レコードの検索要求を行う。
いくつかのハードウェアは実装が間違っており、応答を一つしか返さない。 この状況になると、クライアントシステムは 2 番目の応答を待ち続けてしまう。 このオプションを有効にすると、この動作が変更され、 同じポートからの 2 つの検索要求が正しく処理されなかった場合、 2 番目の検索要求を送信する前にソケットをクローズし 新しいソケットをオープンするようになる。
色々試し、以下の方法で遅延が解決できたことを確認しました。
・[解決方法①] /etc/resolv.conf にsingle-request-reopenを設定する。
・[解決方法②] kube-dnsを使用するパターン1
・[解決方法③] kube-dnsを使用するパターン2
[解決方法①] /etc/resolv.conf にsingle-request-reopenを設定する。
*deployment 定義の dns 設定部分のみの抜粋です。
dnsPolicy: None
dnsConfig:
nameservers:
- xx.x.xx.xx #<=DNSサーバー1のIPアドレス
- xx.x.xx.xx #<=DNSサーバー2のIPアドレス
options:
- name: single-request-reopen
hostNetwork: true
Pod の /etc/resolv.conf は以下の内容で設定されます。
nameserver xx.x.xx.xx
nameserver xx.x.xx.xx
options single-request-reopen
[解決方法②] kube-dnsを使用するパターン1
Kubernetes のマニュアルでは、hostNetwork : true を使う場合は、dnsPolicy: ClusterFirstWithHostNet を設定するように記載があります。これが推奨値ですね。
(該当のPodを作成したときには存在しておらず、時間が経って追加された推奨値と推測...)
・ServiceとPodに対するDNS
https://kubernetes.io/ja/docs/concepts/services-networking/dns-pod-service/
hostNetworkによって稼働しているPodに対しては、ユーザーは明示的にDNSポリシーを"ClusterFirstWithHostNet"とセットするべきです。
*deployment 定義の dns 設定部分のみの抜粋です。
dnsPolicy: ClusterFirstWithHostNet
Pod の /etc/resolv.conf は以下の内容で設定されます。
search default.svc.cluster.local svc.cluster.local cluster.local
nameserver xxx.xx.x.xxx
options ndots:5
[解決方法③] kube-dnsを使用するパターン2
パターン1と同じ内容になりますが、こちらは手動で定義を入力している内容です。
*deployment 定義の dns 設定部分のみの抜粋です。
dnsPolicy: ClusterFirst
dnsConfig:
nameservers:
- xxx.xx.x.xxx #<=Kube DNS Service のIPアドレス
searches:
- default.svc.cluster.local svc.cluster.local cluster.local
options:
- name: ndots
- value: "5"
hostNetwork: true
Pod の /etc/resolv.conf は以下の内容で設定されます。
search default.svc.cluster.local svc.cluster.local cluster.local
nameserver xxx.xx.x.xxx
options ndots:5
おわりに
以下の事象のように環境によっては「single-request-reopen」を使わない方がよいこともあります。
・resolv.conf : single-request-reopen leads to resolution failure
https://access.redhat.com/solutions/1137653
DNS遅延が解決してサービスが安定して稼働しますように..
以上です。