IKS で hostNetwork を使用する Pod でのDNS 遅延の解決


###### はじめに

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 設定部分のみの抜粋です。

```(抜粋)pod_deloyment_org.yml
      dnsPolicy: ClusterFirst
      hostNetwork: true
```

これをデプロイすると、Pod 内の /etc/resolv.conf は以下の内容になります。

```/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 設定部分のみの抜粋です。

```(抜粋)pod_deloyment_manual_1.yml
      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 は以下の内容で設定されます。

```/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 を設定するように記載があります。これが推奨値ですね。

<font color="LightGray">(該当のPodを作成したときには存在しておらず、時間が経って追加された推奨値と推測...)</font>

・ServiceとPodに対するDNS
https://kubernetes.io/ja/docs/concepts/services-networking/dns-pod-service/

> hostNetworkによって稼働しているPodに対しては、ユーザーは明示的にDNSポリシーを"ClusterFirstWithHostNet"とセットするべきです。


＊deployment 定義の dns 設定部分のみの抜粋です。

```(抜粋)pod_deloyment_kube_1.yml

      dnsPolicy: ClusterFirstWithHostNet

```

Pod の /etc/resolv.conf は以下の内容で設定されます。


```/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 設定部分のみの抜粋です。

```(抜粋)pod_deloyment_kube_2.yml
      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 は以下の内容で設定されます。


```/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遅延が解決してサービスが安定して稼働しますように..


以上です。