OpenShift 内部 DNS の詳細な分析
この記事は、テスト用に OpenShift 3.11、Kubernetes 1.11 に基づいています。
OpenShift クラスターには、DNS が必要な場所が少なくとも 3 か所あります。
- 1 つは、ポッド内のアプリケーションがドメイン名を介して外部ネットワークにアクセスする場合、外部ネットワークのドメイン名を解決するために DNS が必要であるということです。
- 2 つ目は、クラスター内 (ポッドまたはホスト マシン上) のサービスのドメイン名を介してクラスター内のサービスにアクセスする場合です。これは一般にサービス検出機能とも呼ばれ、最初に検出する必要があります (取得する)。サービスを使用する前に、サービスのドメイン名を通じてその IP アドレス)
- 3 番目に、クラスターの外部からドメイン名を介して OpenShift ポッドにデプロイされたサービスにアクセスする場合、DNS はサービスの外部ネットワーク ドメイン名を解決する必要があります。
OpenShift での DNS 関連のコンポーネントとその構成
1.1 ポッドの DNS 設定
Linux システムでは、アプリケーションがドメイン名を介してリモート ホストに接続すると、システム コールを通じて DNS 解決が実行されます。たとえば、getaddrinfo()。
他の Linux オペレーティング システムと同様に、ポッドの DNS は resolv.conf ファイルで定義されます。例は次のとおりです。
sh-4.2$ cat /etc/resolv.conf
nameserver 172.16.60.83
search dev.svc.cluster.local svc.cluster.local cluster.local exampleos.com
options ndots:5
の、
- nameserverフィールドは、ポッドが配置されているホストのメイン NIC の IP アドレスです。つまり、ポッドで開始されたすべての DNS クエリ要求は、ホストのポート 53 で実行されている DNS サーバーに転送されます。
- 検索フィールドでは、非 FQDN ドメイン名を解決するときに追加される検索ドメインのリストを指定します。それは次のように説明されています。
ドメイン名(ドメイン名)は 2 種類に分けられ、1 つは絶対ドメイン名(絶対ドメイン名、完全修飾ドメイン名とも呼ばれ、FQDN とも呼ばれます)、もう 1 つは相対ドメイン名(相対ドメイン名、別名 FQDN とも呼ばれます)です。部分修飾ドメイン名、PQDN と呼ばれます)。FQDN は、DNS 名前空間内のレコードを一意に識別する完全修飾ドメイン名です。たとえば、最上位のドメイン名 A にサブドメイン名 B が含まれており、そのサブドメイン名 B にはサブドメイン名 C も含まれている場合、FQDN は CBA ( cs.widgetopia.eduなど) になります。場合によっては、不完全で曖昧な PQDN を使用することもあります。
FQDN は DNS ネーム サーバーで直接クエリできますが、PQDN は最初に FQDN に変換してからクエリする必要があります。これは、検索ドメインを PQDN に追加して FQDN を生成することによって行われます。ドメインネームシステムでは、ドメイン名が「.」で終わるかどうかでFQDNとPQDNを区別します。たとえば、apple.com . は Apple FQDN を表しますが、 apple は PQDN を表し、その FQDN はapple.cs.widgetopia.eduである可能性があります。; apple.com は依然として PQDN であり、その FQDN はapple.com. cs である可能性があります。 .widgetopia.edu ..
- オプションのドット:5
デフォルトでは、多くの DNS リゾルバーは、解決中のドメイン名にドット (.) が見つかった場合は FQDN として扱います。ドメイン名にドットがない場合は、それを PQDN として扱い、システムを追加します。ドメイン名と最後のドットで FQDN を形成します。デフォルトのドメイン名が (ドメイン フィールドで) 指定されていない場合、またはクエリが失敗した場合、検索フィールドの最初の値がデフォルトのドメイン名として使用されます。解析が失敗した場合は、1 つが成功するかすべてが失敗するまで、順番に試行してください。 。
この動作はオプション ndots で指定され、デフォルト値は 1 です。これは、解決されたドメイン名にドット (.) が存在する限り、追加の検索ドメインなしで FQDN とみなされ、問い合わせに直接使用することを意味します。 。OpenShift 環境では、この値は 5 に設定されます。これは、解決されたドメイン名に含まれるドットが 5 つ以下である限り、ドメイン名は PQDN とみなされ、検索ドメインを 1 つずつ使用して DNS クエリ用の FQDN を組み立てることを意味します。他のすべてが失敗した場合は、FQDN として直接解決しようとします。
したがって、シナリオによっては、ポッドでの DNS ルックアップの速度によってアプリケーションのパフォーマンスが低下する可能性があります。主な解決策は 2 つあり、FQDN を直接使用するか、ndot の値を減らすかのいずれかです。詳細については、Kubernetes と DNS の関連ドキュメントを参照してください。
1.2 ポッドが存在するホスト上の DNS 構成とサービス
1.2.1 resolv.conf ファイル
[root@node2 cloud-user]# cat /etc/resolv.conf
# nameserver updated by /etc/NetworkManager/dispatcher.d/99-origin-dns.sh
# Generated by NetworkManager
search cluster.local exampleos.com
nameserver 172.16.60.83
環境をデプロイするとき、/etc/NetworkManager/dispatcher.d/99-origin-dns.sh ファイルが各ノードにデプロイされます。このファイルは、ノード上の NetworkManager サービスが開始されるたびに実行されます。そのタスクには以下が含まれます。
-
dnsmasq 構成ファイルを作成します。
- node-dnsmasq.conf (このファイルは私のバージョン 3.11 環境では作成されませんでした。以下の分析を参照してください)
- オリジン-dns.conf
- 起点-アップストリーム-dns.conf
-
NetworkManager サービスの開始時に dnsmasq サービスを開始します
-
ホストのすべてのデフォルトのルーティング IP を Dnsmasq のリスニング IP に設定します。
-
/etc/resolv.conf を変更し、検索ドメインを設定し、ホストのデフォルト IP をネームサーバーとして使用します。
-
/etc/origin/node/resolv.conf を作成します
つまり、ホスト マシン上の DNS 要求もマシンのポート 53 に送信されます。
DNS設定
OpenShift をデプロイするときは、すべてのノードに Dnsmasq (ポート 53 でリッスン) をインストールします。
$ cat /etc/resolv.conf
# nameserver updated by /etc/NetworkManager/dispatcher.d/99-origin-dns.sh
search cluster.local paas.99cloud.home
nameserver 172.16.60.83
ホストの DNS は、マシン上で実行されている Dnsmasq を指します。
$ cat /etc/dnsmasq.d/origin-upstream-dns.conf
server=172.16.60.90
Dnsmasq の上流サーバーは、外部 DNS サーバー (クラスターにドメイン名解決サービスを提供する DNS サービス プロバイダーまたは CoreDNS) を指します。
$ cat /etc/origin/node/resolv.conf
nameserver 172.16.60.90
内部 SkyDNS は、デフォルトの DNS ドメイン ネーム サーバーとして外部 DNS サーバーもポイントします。
DNSクエリプロセス
OpenShift は内部でSkyDNSを使用し、データは etcd に保存されます。
まず、マスター ノードのポート 53 をリッスンしているすべてのプロセスを見てみましょう。
$ netstat -tunlp | grep 53
tcp 0 0 172.16.60.83:53 0.0.0.0:* LISTEN 33210/dnsmasq
tcp 0 0 172.17.0.1:53 0.0.0.0:* LISTEN 33210/dnsmasq
tcp 0 0 127.0.0.1:53 0.0.0.0:* LISTEN 12277/openshift
tcp 0 0 10.128.0.1:53 0.0.0.0:* LISTEN 62167/dnsmasq
tcp 0 0 0.0.0.0:8053 0.0.0.0:* LISTEN 6392/openshift
127.0.0.1:53 は実際の OpenShift 内部 DNS です。
Kubernetes クラスター内で公開されるサービスに対応するドメイン名は、ルール service_name.name_space.svc に従って連結できます。
$ curl -k https://apiserver.kube-service-catalog.svc/healthz
ok
$ oc get svc -n kube-service-catalog
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
apiserver ClusterIP 172.30.36.133 <none> 443/TCP 7h
controller-manager ClusterIP 172.30.189.41 <none> 443/TCP 7h
$ nslookup apiserver.kube-service-catalog.svc
Server: 172.16.60.83
Address: 172.16.60.83#53
Name: apiserver.kube-service-catalog.svc.cluster.local
Address: 172.30.36.133
$ nslookup apiserver.kube-service-catalog.svc 172.16.60.83
Server: 172.16.60.83
Address: 172.16.60.83#53
Name: apiserver.kube-service-catalog.svc.cluster.local
Address: 172.30.36.133
$ nslookup apiserver.kube-service-catalog.svc 127.0.0.1
Server: 127.0.0.1
Address: 127.0.0.1#53
Name: apiserver.kube-service-catalog.svc.cluster.local
Address: 172.30.36.133
フローチャートによれば、完全な DNS 解決プロセスを復元できます。
- API サーバー サービスの健全性ステータスの API にアクセスすると、まず、apiserver.kube-service-catalog.svc の (内部) ドメイン名に対応する IP アドレスがクエリされます。
- DNS クエリ要求は、最初にホストの設定された DNS サーバー、つまり Dnsmasq に届きます。
- 次に、Dnsmasq は、正しい IP アドレスが見つかるクラスター内の DNS サーバーである SkyDNS にクエリ リクエストを上向きに送信します。
OpenShift ネットワークを管理する Pod 内の apiserver.kube-service-catalog.svc.cluster.local をクエリしてみましょう
$ oc get pods -n openshift-sdn
NAME READY STATUS RESTARTS AGE
ovs-7kpnv 1/1 Running 0 11h
ovs-7p75w 1/1 Running 0 11h
ovs-m6clw 1/1 Running 0 11h
sdn-7fz45 1/1 Running 0 11h
sdn-l9cq7 1/1 Running 0 11h
sdn-rmqvd 1/1 Running 0 11h
$ oc exec -it sdn-7fz45 -n openshift-sdn /bin/bash
[root@ocp-infra-1 origin]# dig apiserver.kube-service-catalog.svc.cluster.local
; <<>> DiG 9.9.4-RedHat-9.9.4-74.el7_6.1 <<>> apiserver.kube-service-catalog.svc.cluster.local
;; global options: +cmd
;; Got answer:
;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 39256
;; flags: qr aa rd ra; QUERY: 1, ANSWER: 1, AUTHORITY: 0, ADDITIONAL: 0
;; QUESTION SECTION:
;apiserver.kube-service-catalog.svc.cluster.local. IN A
;; ANSWER SECTION:
apiserver.kube-service-catalog.svc.cluster.local. 30 IN A 172.30.36.133
;; Query time: 1 msec
;; SERVER: 172.16.60.83#53(172.16.60.83)
;; WHEN: Wed Jul 03 16:17:59 UTC 2019
;; MSG SIZE rcvd: 82
なぜ内部DNSが必要なのでしょうか?
これまで、仮想マシン内のアプリケーション間の通信に使用されるホスト マシンの IP は、通常、簡単には変更されませんでした。ただし、コンテナ環境では、コンテナの起動時に新しい IP アドレスが割り当てられます。コンテナーを調整する Kubernetes には静的 IP が必要であり、サービス IP を提供する Service オブジェクトはこの目的のために作成されます。Service オブジェクトのドメイン名は変更されません (スプライシング ルール) この内部ドメイン名のおかげで、Pod 自体の IP が変更されても、サービス間の安定した通信が実現されます。
ポッドの IP は変更されるため、アプリケーションまたは設定で IP アドレスを指定しても、ポッドが再作成されたときに IP が変更されたことがアプリケーションに能動的に通知されません。これらの理由から、通常、アプリケーションでの IP アドレスのハードコーディングを避けるためにドメイン名を使用します。OpenShift の内部 DNS は動的 DNS を使用し、ポッドが再構築されるたびに、DNS が新しいレコードで更新されます。