Kubernetesの世界ではCoreDNSと呼ばれる機構があり、コンテナはこのCoreDNSに名前解決を依頼することでサービスのIPを知らなくても通信が行えます。
そんなCoreDNSですが、実はコンテナの外(Node)からも利用できます。
環境情報
Kubernetes 1.23
Red Hat Enterprise Linux Server 7.9
PodからDNSを引く
こんな感じでNginxのPodに紐づくServiceがある場合
# kubectl get service NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE backend ClusterIP 10.105.20.83 <none> 80/TCP 31h frontend ClusterIP 10.96.228.219 <none> 80/TCP 24h # kubectl get pod NAME READY STATUS RESTARTS AGE backend 1/1 Running 0 31h frontend 1/1 Running 0 31h
コンテナの中でcurlコマンドを打つとIPアドレスを入れずとも通信ができます。
# kubectl exec -it backend -- curl frontend.default.svc.cluster.local <!DOCTYPE html> <html> <head> <title>Welcome to nginx!</title> ...
NodeからDNSを引く
一方でNode上からService名を指定しても接続ができません。
# curl frontend.default.svc.cluster.local curl: (6) Could not resolve host: frontend.default.svc.cluster.local; Unknown error
というのもそもそもServiceが名前解決できるのは以下のkube-dns(CoreDNS)がServiceを検出してIPを返してくれているから。
# 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 46d
確かにコンテナの中にはCoreDNSのIPがDNSのIPとして記載されています。
# kubectl exec -it backend -- cat /etc/resolv.conf nameserver 10.96.0.10
というわけでNode上の/etc/resolv.confに同じように上記IPを追記すれば
# curl frontend.default.svc.cluster.local -v * About to connect() to frontend.default.svc.cluster.local port 80 (#0) * Trying 10.96.228.219... * Connected to frontend.default.svc.cluster.local (10.96.228.219) port 80 (#0) > GET / HTTP/1.1 > User-Agent: curl/7.29.0 > Host: frontend.default.svc.cluster.local > Accept: */* > < HTTP/1.1 200 OK ...
コンテナ同様に名前解決ができます。やったね。