K8sのServiceの名前解決からkube-proxyのiptablesによってPodにロードバランシングされるまでの流れを追う
kubernetesKubernetes の Service は my-svc.my-namespace.svc.cluster-domain.example のような FQDN を持ち、これにリクエストすると selector が指す Pod に届く。これがどのように実現されているかを追う。EKS で立てた Kubernetes 1.28 クラスタで確認する。
まず Service の FQDN から ClusterIP への名前解決は、各 Pod の /etc/resolv.conf の nameserver 設定に従い kube-dns (coredns) へ問い合わせることで行われる。なお、この IP アドレス自体も kube-dns Service の ClusterIP なので以後は同様にルーティングされることになる。
$ cat /etc/resolv.conf
search testapp.svc.cluster.local svc.cluster.local cluster.local ap-northeast-1.compute.internal
nameserver 172.20.0.10
options ndots:5
Service はロードバランシングの機能を提供するが、これは iptables によって実現されている。この iptabels の設定を更新するのが Daemonset として動いている kube-proxy。その名前からプロキシサーバーのようなものをイメージしてしまうが、実際はトラフィックを受けるわけではないので cpu: 100m ととても少ないリソースで動く。kube-proxy には iptabels 以外の mode も存在しているが今回は触れない。
iptables は パケットフィルタや NAT を行う Netfilter の設定ツール。ホストで次のコマンドを実行すると nat table の設定を確認できる。KUBE-SERVICES Chain に各 Service の ClusterIP を destination とする KUBE-SVC と、KUBE-NODEPORTS が含まれ、KUBE-NODEPORTS も KUBE-EXT を介して KUBE-SVC に繋がっている。KUBE-SVC には各 Pod の IP アドレスに DNAT する KUBE-SEP が含まれ、これが確率で選ばれることでロードバランシングされる。kube-proxy は Kubernetes API を監視し Healthy/Unhealthy な Pod のルールを追加/削除する。
$ sudo iptables -t nat -L -n
Chain PREROUTING (policy ACCEPT)
target prot opt source destination
KUBE-SERVICES all -- 0.0.0.0/0 0.0.0.0/0 /* kubernetes service portals */
...
Chain KUBE-SERVICES (2 references)
target prot opt source destination
KUBE-SVC-CE6JHM1SEKP18XIF tcp -- 0.0.0.0/0 172.20.36.232 /* testapp/testapp-svc cluster IP */ tcp dpt:8080
...
KUBE-NODEPORTS all -- 0.0.0.0/0 0.0.0.0/0 /* kubernetes service nodeports; NOTE: this must be the last rule in this chain */ ADDRTYPE match dst-type LOCAL
Chain KUBE-NODEPORTS (1 references)
target prot opt source destination
KUBE-EXT-W1EMVGLJN3U6KBK2 tcp -- 0.0.0.0/0 0.0.0.0/0 /* testapp/testapp2-svc */ tcp dpt:31218
...
Chain KUBE-EXT-W1EMVGLJN3U6KBK2 (1 references)
target prot opt source destination
KUBE-MARK-MASQ all -- 0.0.0.0/0 0.0.0.0/0 /* masquerade traffic for testapp/testapp2-svc external destinations */
KUBE-SVC-W1EMVGLJN3U6KBK2 all -- 0.0.0.0/0 0.0.0.0/0
Chain KUBE-SVC-CE6JHM1SEKP18XIF (2 references)
target prot opt source destination
KUBE-SEP-F3KEHKXHH6PPCNMD all -- 0.0.0.0/0 0.0.0.0/0 /* testapp/testapp-svc -> 10.161.33.109:8080 */ statistic mode random probability 0.01351351338
KUBE-SEP-GONI7XQNZNJEEBEO all -- 0.0.0.0/0 0.0.0.0/0 /* testapp/testapp-svc -> 10.161.33.116:8080 */ statistic mode random probability 0.01369863003
KUBE-SEP-C2L3SYA5JOE66TCB all -- 0.0.0.0/0 0.0.0.0/0 /* testapp/testapp-svc -> 10.161.33.129:8080 */ statistic mode random probability 0.01388888899
...
Chain KUBE-SEP-F3KEHKXHH6PPCNMD (1 references)
target prot opt source destination
KUBE-MARK-MASQ all -- 10.161.33.109 0.0.0.0/0 /* testapp/testapp-svc */
DNAT tcp -- 0.0.0.0/0 0.0.0.0/0 /* testapp/testapp-svc */ tcp to:10.161.33.109:8080