CoreDNS@ネットワーク系¶
はじめに¶
本サイトにつきまして、以下をご認識のほど宜しくお願いいたします。
01. CoreDNS (新kube-dns)¶
CoreDNSとは¶
Node内の権威DNSサーバーとして、Kubernetesリソースの名前解決を実行する。
01-02. マニフェスト¶
マニフェストの種類¶
CoreDNSは、Deployment (CoreDNS) 、Service (kube-dns) 、ConfigMap (coredns-configmap) などのマニフェストから構成される。
$ kubectl get pod -n kube-system
NAME READY STATUS RESTARTS AGE
coredns-558bd4d5db-hg75t 1/1 Running 0 1m0s
coredns-558bd4d5db-ltbxt 1/1 Running 0 1m0s
...
$ kubectl get service -n kube-system
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
kube-dns ClusterIP 10.96.0.10 <none> 53/UDP,53/TCP,9153/TCP 1m0s
...
Deployment¶
▼ CoreDNS¶
Podからの問い合わせに対して、名前解決を実行する。
Service¶
▼ kube-dns¶
CoreDNSに対する問い合わせを受信し、CoreDNSへルーティングする。
ConfigMap¶
▼ coredns-configmap¶
ConfigMapの.Corefile
キーに、Corefile
ファイルの設定値を定義する。
*実装例*
apiVersion: v1
kind: ConfigMap
metadata:
name: coredns-configmap
namespace: kube-system
data:
Corefile: |
.:53 {
...
}
02. Serviceの名前解決¶
Serviceの名前解決の仕組み¶
▼ アーキテクチャ¶
CoreDNSは、kube-apiserverから必要なKubernetesリソース (Service、Endpoints) を取得する。
Podのスケジューリング時に、kubeletはPod内のコンテナの/etc/resolv.conf
ファイルに 権威DNSサーバー (CoreDNSのService) のIPアドレスを設定する。
Pod内のコンテナは、自身の/etc/resolv.conf
ファイルを使用して、CoreDNSのServiceにリクエストを送信する。
また、CoreDNSから、宛先のPodに紐づくServiceのIPアドレスを正引きする。
このServiceのIPアドレスを指定し、Podにリクエストを送信する。
▼ 確認方法¶
# Pod内のコンテナに接続する。
$ kubectl exec -it <Pod名> -c <コンテナ名> -- bash
# コンテナのresolv.confファイルの中身を確認する
[root@<Pod名>] $ cat /etc/resolv.conf
# 権威DNSサーバーのIPアドレス (ここではCoreDNSのServiceのIPアドレス)
nameserver 10.96.0.10
search default.svc.cluster.local svc.cluster.local cluster.local
# 名前解決時のローカルドメインの優先度
options ndots:5
# CoreDNSを権威DNSサーバーとして使用している場合
$ kubectl get service -n kube-system
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
kube-dns ClusterIP 10.96.0.10 <none> 53/UDP,53/TCP,9153/TCP 1m0s
DNSレコードタイプ別の完全修飾ドメイン名¶
▼ DNSレコードタイプ別の完全修飾ドメイン名とは¶
Clusterネットワーク内の全てのServiceに完全修飾ドメイン名が割り当てられている。
DNSレコードタイプごとに、完全修飾ドメイン名が異なる。
▼ A/AAAA
レコードの場合¶
対応する完全修飾ドメイン名は、『<Service名>.<Namespace名>.svc.cluster.local
』である。
通常のServiceの名前解決ではCluster-IPが返却される。
一方でHeadless Serviceの名前解決では、PodのIPアドレスが返却される。
『svc.cluster.local
』は省略でき、『<Service名>.<Namespace名>
』のみを指定しても名前解決できる。
また、同じNamespace内でパケットを送受信する場合は、さらに『<Namespace名>
』も省略でき、『<Service名>
』のみで名前解決できる。
▼ SRV
レコードの場合¶
対応する完全修飾ドメイン名は、『_<ポート名>._<プロトコル>.<Service名>.<Namespace名>.svc.cluster.local
』である。
Serviceの.spec.ports.name
キー数だけ、完全修飾ドメイン名が作成される。
名前解決の仕組み¶
▼ Pod内からServiceに対する正引き名前解決¶
Pod内のコンテナから宛先のServiceに対して、nslookup
コマンドの正引きする。
Serviceに.metadata.name
キーが設定されている場合、Serviceの完全修飾ドメイン名は、.metadata.name
キーの値になる。
完全修飾ドメイン名の設定を要求された時は、設定ミスを防げるため、.metadata.name
キーの値よりも完全修飾ドメイン名の方が推奨である。
# Pod内のコンテナに接続する。
$ kubectl exec -it <Pod名> -c <コンテナ名> -- bash
# Pod内のコンテナから宛先のServiceに対して、正引きの名前解決を実行する
[root@<Pod名>:~] $ nslookup <Service名>
Server: 10.96.0.10
Address: 10.96.0.10#53
Name: <Serviceの完全修飾ドメイン名>
Address: 10.105.157.184
補足として、異なるNamespaceに所属するServiceの名前解決を実行する場合は、Serviceの完全修飾ドメイン名の後にNamespaceを指定する必要がある。
# Pod内のコンテナから正引きの名前解決を実行する。
[root@<Pod名>:~] $ nslookup <Serviceの完全修飾ドメイン名>
▼ Pod外からServiceに対する正引き名前解決¶
(1)
-
NginxのPodにルーティングするServiceが稼働しているとする。
$ kubectl get service
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
nginx-service ClusterIP 10.101.67.107 <none> 8080/TCP 3h34m
(2)
-
CoreDNSのPodが稼働しているとする。
ここで、CoreDNSのPodのIPアドレス (ここでは
10.244.0.2
) を確認しておく。
$ kubectl get pod -o wide -l k8s-app=kube-dns -n kube-system
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
coredns-***** 1/1 Running 0 3h53m 10.244.0.2 minikube <none> <none>
(3)
-
ここで、Node内に接続する。Serviceの完全修飾ドメイン名 (ここでは
nginx-service.default.svc.cluster.local
) をCoreDNSに正引きする。すると、ServiceのIPアドレスを取得できる。
# Node内に接続する。
$ dig nginx-service.default.svc.cluster.local +short @10.244.0.2
10.101.67.107
疎通確認¶
▼ 事前確認¶
(1)
-
Serviceがルーティング先のポート番号を確認する。
$ kubectl get service <Service名> -o yaml | grep targetPort:
(2)
-
Serviceがルーティング先のPodにて、コンテナが待ち受けるポート番号を確認する。注意点として、
.spec.containers[*].ports
キーは単なる仕様であり、記載されていなくとも、コンテナのポートが公開されている可能性がある。
# 先にmetadata.labelキーから、Serviceのルーティング先のPodを確認する
$ kubectl get pod -l <名前>=<値> -o wide
$ kubectl get pod <Pod名> -o yaml | grep containerPort:
(3)
-
両方のポート番号が一致しているかを確認する。
▼ Serviceを経由したアウトバウンド通信の送信¶
Serviceを介して、宛先のPodにHTTPSリクエストを送信する。
完全修飾ドメイン名またはIPアドレスを指定できる。
# Pod内のコンテナに接続する。
$ kubectl exec -it <Pod名> -c <コンテナ名> -- bash
[root@<Pod名>:~] $ curl -X GET https://<Serviceの完全修飾ドメイン名/IPアドレス>:<ポート番号>
03. Podの直接的な名前解決¶
Podの直接的な名前解決の仕組み¶
Serviceの名前解決を介さずに、特定のPodのインスタンスに対して直接的に名前解決することもできる。
DNSレコードタイプ別の完全修飾ドメイン名¶
▼ A/AAAA
レコードの場合¶
対応する完全修飾ドメイン名は、『<PodのIPアドレス>.<Namespace名>.pod.cluster.local
』である。
PodのIPアドレスを固定する¶
Kubernetesでは、PodのIPアドレスを固定できない。
そのため、IPアドレスを固定したアプリは、Kubernetes Cluster上で稼働させるのではなく、サーバー上でコンテナあるいはプロセスとして稼働させた方が良い。
ただし、一部のCNIを使用すれば、IPアドレスを固定することはできる。
04. サービスディスカバリー¶
CoreDNSの名前解決と、Serviceとkube-proxyによるIPアドレスとポート番号の動的な検出を組み合わせることにより、サービスディスカバリーを実装できる。