理解Kubernetes系列文章:
每个Pod 都会被分配一个IP地址,比如下面这儿pod的IP地址是 10.1.79.11.
root@kub-node-0:/home/ubuntu# kubectl get pod -o wide NAME READY STATUS RESTARTS AGE IP NODE my-nginx8-b77fdd7bc-4t2kb 1/1 Running 0 3d 10.1.79.11 172.23.100.6
该 Pod 在某个 node 上有两个容器:
root@kub-node-2:/home/ubuntu# docker ps CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES d199cb090c13 sammyliu8/nginx "nginx -g 'daemon of…" 3 days ago Up 3 days k8s_my-nginx8_my-nginx8-b77fdd7bc-4t2kb_default_cd1425fd-f48a-11e7-a605-fa163e9a22a6_0 0c647fb76c0b kubernetes/pause "/pause" 3 days ago Up 3 days k8s_POD_my-nginx8-b77fdd7bc-4t2kb_default_cd1425fd-f48a-11e7-a605-fa163e9a22a6_0
dockerd 会给 pause 容器分配一个ip,这个ip 就是 pod 的ip:
root@kub-node-2:/home/ubuntu# ip netns exec pause0b ip addr77: eth0@if78:mtu 1400 qdisc noqueue state UP group default link/ether 02:42:0a:01:4f:0b brd ff:ff:ff:ff:ff:ff link-netnsid 0 inet 10.1.79.11/24 brd 10.1.79.255 scope global eth0 valid_lft forever preferred_lft forever
而 nginx 容器是跟 pause 容器共享 network namespace 的:
root@kub-node-2:/home/ubuntu# ip netns exec nginx13 ip addr 77: eth0@if78:mtu 1400 qdisc noqueue state UP group default link/ether 02:42:0a:01:4f:0b brd ff:ff:ff:ff:ff:ff link-netnsid 0 inet 10.1.79.11/24 brd 10.1.79.255 scope global eth0 valid_lft forever preferred_lft forever
IP 所在的网段是在 dockerd 的启动参数中给的:
root 11183 1 1 2017 ? 03:04:26 /usr/bin/dockerd -g /data/docker --bip=10.1.79.1/24 --mtu=1400
(1)管理员配置 flannel 使用的 network,并将配置保存在 etcd 中
/opt/bin/etcdctl --endpoints="http://172.23.100.4:2379,http://172.23.100.5:2379,http://172.23.100.4:2379" mk /coreos.com/network/config \ '{"Network":"10.1.0.0/16", "Backend": {"Type": "vxlan"}}'
(2)在每个 minion 节点上,flannel 启动。它从 etcd 中获取 network 配置,并为本节点产生一个 subnet,也保存在 etcd 中。并且产生 /run/flannel/subnet.env 文件:
FLANNEL_NETWORK=10.1.0.0/16 #这是全局的 falnnel network FLANNEL_SUBNET=10.1.1.1/24 #这是本节点上 falnnel subnet FLANNEL_MTU=1400 #本节点上 flannel mtu FLANNEL_IPMASQ=true
(3)flannel deamon 还会创建 flannel.1 的 vxlan vtep 端点:
root@kub-node-1:/opt/bin# ifconfig flannel.1 flannel.1 Link encap:Ethernet HWaddr 0a:6e:a6:6f:95:04 inet addr:10.1.1.0 Bcast:0.0.0.0 Mask:255.255.255.255 root@kub-node-1:/opt/bin# ip link show dev flannel.1 3: flannel.1:mtu 1400 qdisc noqueue state UNKNOWN mode DEFAULT group default link/ether 0a:6e:a6:6f:95:04 brd ff:ff:ff:ff:ff:ff
其 mtu 正好是 1400. 该端点会负责接收和发送 vxlan 数据包。
(3)使用 subnet.env 中的变量,启动 dockerd 进程,它的 bip 对应 FLANNEL_SUBNET,mtu 对应 FLANNEL_MTU。
/usr/bin/dockerd -g /data/docker --bip=10.1.1.1/24 --mtu=1400
(4)dockerd deamon 会创建 docker0 网桥
root@kub-node-1:/opt/bin# ifconfig docker0 docker0 Link encap:Ethernet HWaddr 02:42:30:ef:ef:18 inet addr:10.1.1.1 Bcast:10.1.1.255 Mask:255.255.255.0
本节点上的容器都会使用一个 veth 设备挂接在该网桥上比如:
root@kub-node-1:/opt/bin# brctl show docker0 bridge name bridge id STP enabled interfaces docker0 8000.024230efef18 no veth295ded4 veth5459316
(5)对每一个被调度到本节点上的 POD,kubelet 都会创建一个 pause 容器,该容器会通过一个 veth 设备挂接到 docker0 上;同时,POD 中的其他容器会共享 pause 容器的 network namespace。
首先看下本节点上的路由表:
root@kub-node-1:/opt/bin# route -n Kernel IP routing table Destination Gateway Genmask Flags Metric Ref Use Iface 0.0.0.0 172.23.100.1 0.0.0.0 UG 0 0 0 ens3 10.1.0.0 0.0.0.0 255.255.0.0 U 0 0 0 flannel.1 #flannel 网络内跨节点的通信会交给 flannel.1 处理 10.1.1.0 0.0.0.0 255.255.255.0 U 0 0 0 docker0 #flannel 网络内节点内的通信会走 docker0 169.254.169.254 172.23.100.1 255.255.255.255 UGH 0 0 0 ens3 172.23.100.0 0.0.0.0 255.255.255.0 U 0 0 0 ens3
如果是同一个 deployment 的位于同一个 minon 上的两个 POD 之间通信,那实际上是同一个 subnet 间通信,此时经过 docker0 网桥即可;
如果是同一个 deployment 的位于两个 minon 上的两个 POD 之间通信,另一个POD 的IP 在 10.1.79.0 子网上,那么首先到 flannel.1, flannel 查询 etcd 获取对方容器所在的节点的IP地址,然后封装为 vxlan 的 udp 包,发到 ens3,走物理机网络达到对方节点。此时,完整的路径是:
containerA --> docker0 --> flannel.1 --> NodeA --> (IP Address) --> NodeB --> flannel.1 --> docker0 --> containerB
根据subnet 从 etcd 中获取 node ip:
root@kub-node-0:/home/ubuntu/kub# /opt/bin/etcdctl --endpoints="http://172.23.100.4:2379,http://172.23.100.5:2379,http://172.23.100.4:2379" get /coreos.com/network/subnets/10.1.79.0-24 {"PublicIP":"172.23.100.6","BackendType":"vxlan","BackendData":{"VtepMAC":"6e:10:b3:53:1e:f4"}}
POD 的 IP 地址是 docker 分配的,在 falnnel 网络范围内,也就是 K8S 集群范围内,都可以使用 POD 的 IP 访问 POD 中的应用。比如:
root@kub-node-0:/home/ubuntu/kub# kubectl get pods -o wide NAME READY STATUS RESTARTS AGE IP NODE my-nginx8-b77fdd7bc-4t2kb 1/1 Running 0 4d 10.1.79.11 172.23.100.6 root@kub-node-0:/home/ubuntu/kub# curl 10.1.79.11:80Welcome to nginx!
If you see this page, the nginx web server is successfully installed and working. Further configuration is required.
For online documentation and support please refer to "http://nginx.org/">nginx.org.
Commercial support is available at "http://nginx.com/">nginx.com.Thank you for using nginx.