Kubernetes のネットワークがどの様に実現されているか知りたかったので調べてメモしました。ここに書いているのは...
- コンテナ (POD) のIPアドレスがどのようにルーティングされるか
- SERVICE の Cluster-IP が、複数いる POD の IPアドレスにどうルーティングされるか
- コンテナ (POD) 内のDNS名前解決はどうされるか
普通の Docker のネットワークについては こちら
Kubernetes ネットワークの仕組み (GKE) は こちら 。ほぼ同じです。
検証環境
Azure Container Service です。GKE ではありません。
2台の Agent Node と、1台の Master Node。
# kubectl get nodes
NAME STATUS AGE VERSION
k8s-agent-XXXXXXXX-0 Ready 4h v1.7.7
k8s-agent-XXXXXXXX-1 Ready 4h v1.7.7
k8s-master-XXXXXXXX-0 Ready 4h v1.7.7
特に何も追加でデプロイはしませんでした。Kubernetes 標準の POD kube-dns
が、いい感じに2台いて SERVICE で分散されているので、これを題材にします。
# kubectl get pods --namespace=kube-system
NAME READY STATUS RESTARTS AGE
kube-dns-v20-3003781527-lc299 3/3 Running 0 4h
kube-dns-v20-3003781527-njvzk 3/3 Running 0 4h
...
# kubectl get services --namespace=kube-system
NAME CLUSTER-IP EXTERNAL-IP PORT(S) AGE
kube-dns 10.0.0.10 <none> 53/UDP,53/TCP 4h
...
まとめ
まずはまとめから。↓は Azure Container Service の場合で GKE はまたちょっと違うと思います。
Agent Node のみ。Master Node は省略。
主要な3つのネットワーク範囲があります。
- 物理ホストのネットワークが
10.240.0.0/16
- それぞれの物理ホスト上に、コンテナのネットワーク
10.244.X.0/24
がある- Agent Node #0 には
10.244.0.0/24
- Agent Node #1 には
10.244.1.0/24
- Agent Node #0 には
-
SERVICE の Cluster-IP は
10.0.0.0/16
の範囲で振られる
コンテナのネットワーク。別々のホスト上にいるコンテナはこう↓ルーティングされます。
- Destination=
10.244.0.0/16
へのアクセスは Default Gateway10.240.0.1
へ送信されます - 物理ゲートウェイのルートテーブルで物理ホストのIPアドレスへルーティングされます
- 例えば、Destination=
10.244.1.0/24
→ Next Hop=10.240.0.5
- 例えば、Destination=
- 物理ホストに到達すると、ホストOSのルートテーブルで仮想NIC
cbr0
に送信 - 仮想NIC
cbr0
の先に、宛先のコンテナのNICがあります
SERVICE の Cluster-IP 宛に送信すると...
-
10.0.0.0/16
は全て ホストOSの iptables で解決されます (このアドレス範囲に該当する NIC はない) - 宛先
10.0.0.0/16
は DNAT で宛先10.244.X.0/24
(コンテナIP) に書き換えられます - コンテナ (POD) が複数いる時は
random probability 0...
でランダムに選択されます
また、コンテナ内の /etc/resolv.conf
を見ると nameserver は固定で 10.0.0.10
です。
これは kube-dns
SERVICE の Cluster-IP です。
実際に追ってみた編
書いてあるIPとかは 今回たまたまこうだった です。
Gateway (10.240.0.1) のルートテーブル
コンテナネットワーク 10.244.X.0/24
へのアクセスが、そのネットワークが存在する物理ホスト宛にルーティングされています。
NAME | ADDRESS PREFIX | NEXT HOP |
---|---|---|
k8s-agent-154d19d7-0 | 10.244.0.0/24 | 10.240.0.4 |
k8s-agent-154d19d7-1 | 10.244.1.0/24 | 10.240.0.5 |
k8s-master-154d19d7-0 | 10.244.2.0/24 | 10.240.255.5 |
ホスト (Agent Node) のネットワーク
ifconfig の結果。
- cbr0 ... この仮想NICの先にコンテナのNICがあります
- docker0 ... Docker 標準のNICだけど Kubernetes 環境では使われていない?
- eth0 ... ホストOSの物理NICです
- vethXXXX ... ホストNIC→コンテナNIC間の仮想Ethernetケーブル
# ifconfig
cbr0 Link encap:Ethernet HWaddr 0a:58:0a:f4:00:01
inet addr:10.244.0.1 Bcast:0.0.0.0 Mask:255.255.255.0
inet6 addr: fe80::808c:97ff:feb1:3bd5/64 Scope:Link
UP BROADCAST RUNNING PROMISC MULTICAST MTU:1500 Metric:1
RX packets:187644 errors:0 dropped:0 overruns:0 frame:0
TX packets:228056 errors:0 dropped:0 overruns:0 carrier:0
collisions:0 txqueuelen:1000
RX bytes:17175759 (17.1 MB) TX bytes:150372583 (150.3 MB)
docker0 Link encap:Ethernet HWaddr 02:42:bf:91:4b:33
inet addr:172.17.0.1 Bcast:0.0.0.0 Mask:255.255.0.0
inet6 addr: fe80::42:bfff:fe91:4b33/64 Scope:Link
UP BROADCAST MULTICAST MTU:1500 Metric:1
RX packets:6 errors:0 dropped:0 overruns:0 frame:0
TX packets:6 errors:0 dropped:0 overruns:0 carrier:0
collisions:0 txqueuelen:0
RX bytes:424 (424.0 B) TX bytes:508 (508.0 B)
eth0 Link encap:Ethernet HWaddr 00:0d:3a:51:da:e1
inet addr:10.240.0.4 Bcast:10.240.255.255 Mask:255.255.0.0
inet6 addr: fe80::20d:3aff:fe51:dae1/64 Scope:Link
UP BROADCAST RUNNING MULTICAST MTU:1500 Metric:1
RX packets:853884 errors:0 dropped:0 overruns:0 frame:0
TX packets:568944 errors:0 dropped:0 overruns:0 carrier:0
collisions:0 txqueuelen:1000
RX bytes:891926509 (891.9 MB) TX bytes:78778540 (78.7 MB)
lo Link encap:Local Loopback
inet addr:127.0.0.1 Mask:255.0.0.0
inet6 addr: ::1/128 Scope:Host
UP LOOPBACK RUNNING MTU:65536 Metric:1
RX packets:164 errors:0 dropped:0 overruns:0 frame:0
TX packets:164 errors:0 dropped:0 overruns:0 carrier:0
collisions:0 txqueuelen:1
RX bytes:12040 (12.0 KB) TX bytes:12040 (12.0 KB)
veth16050088 Link encap:Ethernet HWaddr be:b7:5f:05:e5:8e
inet6 addr: fe80::bcb7:5fff:fe05:e58e/64 Scope:Link
UP BROADCAST RUNNING MULTICAST MTU:1500 Metric:1
RX packets:6741 errors:0 dropped:0 overruns:0 frame:0
TX packets:12518 errors:0 dropped:0 overruns:0 carrier:0
collisions:0 txqueuelen:0
RX bytes:400888 (400.8 KB) TX bytes:939070 (939.0 KB)
...
ルートテーブル。
- 外部への通信は Default Gateway
10.240.0.1
へ - 物理ホストへの通信は
eth0
NIC に投げる - このホスト上にあるコンテナへの通信は
cbr0
NIC に投げる - 別のホスト上にあるコンテナへの通信は Default Gateway
10.240.0.1
へ
# route -n
Kernel IP routing table
Destination Gateway Genmask Flags Metric Ref Use Iface
0.0.0.0 10.240.0.1 0.0.0.0 UG 0 0 0 eth0
10.240.0.0 0.0.0.0 255.255.0.0 U 0 0 0 eth0
10.244.0.0 0.0.0.0 255.255.255.0 U 0 0 0 cbr0
...
コンテナのネットワーク
ubuntu ベースのコンテナで試したので、ネットワークコマンドは apt-get install net-tools
で入れました
ifconfig の結果。
- eth0 ... コンテナのIPアドレスが振られている仮想NICです。この先にホストOSの
cbr0
仮想NICがあります
# ifconfig
eth0 Link encap:Ethernet HWaddr 0a:58:0a:f4:00:06
inet addr:10.244.0.6 Bcast:0.0.0.0 Mask:255.255.255.0
inet6 addr: fe80::c41c:2dff:fe41:4752/64 Scope:Link
UP BROADCAST RUNNING MULTICAST MTU:1500 Metric:1
RX packets:12441 errors:0 dropped:0 overruns:0 frame:0
TX packets:6701 errors:0 dropped:0 overruns:0 carrier:0
collisions:0 txqueuelen:0
RX bytes:934720 (912.8 KiB) TX bytes:398536 (389.1 KiB)
lo Link encap:Local Loopback
inet addr:127.0.0.1 Mask:255.0.0.0
inet6 addr: ::1/128 Scope:Host
UP LOOPBACK RUNNING MTU:65536 Metric:1
RX packets:0 errors:0 dropped:0 overruns:0 frame:0
TX packets:0 errors:0 dropped:0 overruns:0 carrier:0
collisions:0 txqueuelen:1
RX bytes:0 (0.0 B) TX bytes:0 (0.0 B)
コンテナのIPは
10.244.{ホスト毎の連番}.{ホスト上のコンテナ毎の連番}
になります
ルートテーブル。
- 外部への通信は Gateway
10.244.0.1
へ - 同じホスト上のコンテナへの通信は
eth0
NIC へ - 違うホスト上のコンテナへの通信は Gateway
10.244.0.1
へ
# route -n
Kernel IP routing table
Destination Gateway Genmask Flags Metric Ref Use Iface
0.0.0.0 10.244.0.1 0.0.0.0 UG 0 0 0 eth0
10.244.0.0 0.0.0.0 255.255.255.0 U 0 0 0 eth0
SERVICE の Cluster-IP
題材として kube-dns
SERVICE の Cluster-IP 10.0.0.10
に着目しました。ホストOSの iptables
を見てみます。
# iptables -t nat -L -n -v
...
Chain KUBE-SERVICES (2 references)
pkts bytes target prot opt in out source destination
...
0 0 KUBE-MARK-MASQ tcp -- * * !10.244.0.0/16 10.0.0.10 tcp dpt:53
0 0 KUBE-SVC-ERIFXISQEP7F7OF4 tcp -- * * 0.0.0.0/0 10.0.0.10 tcp dpt:53
Chain KUBE-SVC-ERIFXISQEP7F7OF4
. ランダムで別々のルールに転送される様になっています。今回は kube-dns
POD は2台だったので、それぞれ 50% の確率が割り当てられていますね。
# iptables -t nat -L -n -v
...
Chain KUBE-SVC-ERIFXISQEP7F7OF4 (1 references)
pkts bytes target prot opt in out source destination
...
0 0 KUBE-SEP-IT2ZTR26TO4XFPTO all -- * * 0.0.0.0/0 0.0.0.0/0 statistic mode random probability 0.50000000000
0 0 KUBE-SEP-BWHGELGX6BITPZVO all -- * * 0.0.0.0/0 0.0.0.0/0
確率50% その1 --> Chain KUBE-SEP-IT2ZTR26TO4XFPTO
. DNAT で宛先をコンテナ (POD) のIPアドレスに書き換え。
# iptables -t nat -L -n -v
...
Chain KUBE-SEP-IT2ZTR26TO4XFPTO (1 references)
pkts bytes target prot opt in out source destination
0 0 KUBE-MARK-MASQ all -- * * 10.244.0.2 0.0.0.0/0
0 0 DNAT tcp -- * * 0.0.0.0/0 0.0.0.0/0 tcp to:10.244.0.2:53
確率50% その2 --> Chain KUBE-SEP-BWHGELGX6BITPZVO
. これは その1 とは異なる物理ホスト上のコンテナIPを示しています。
# iptables -t nat -L -n -v
...
Chain KUBE-SEP-BWHGELGX6BITPZVO (1 references)
pkts bytes target prot opt in out source destination
0 0 KUBE-MARK-MASQ all -- * * 10.244.1.2 0.0.0.0/0
0 0 DNAT tcp -- * * 0.0.0.0/0 0.0.0.0/0 tcp to:10.244.1.2:53
コンテナの DNS Nameserver
コンテナに入って /etc/resolv.conf
を確認。
# cat /etc/resolv.conf
nameserver 10.0.0.10
search default.svc.cluster.local svc.cluster.local cluster.local tbshyrd11cuundvieskktqf3ib.lx.internal.cloudapp.net
options ndots:5
この 10.0.0.10
は前述の通り kube-dns
SERVICE の Cluster-IP なので、2台の kube-dns
POD のうちどちらかで名前解決されることになります。