Kubernetes 中的网络解析 —— 以 flannel 为例
我们当初使用kubernetes-vagrant-centos-cluster安装了拥有三个节点的kubernetes集群,节点的状态如下所述。
[root@node1 ~]# kubectl get nodes -o wide
NAME STATUS ROLES AGE VERSION EXTERNAL-IP OS-IMAGE KERNEL-VERSION CONTAINER-RUNTIME
node1 Ready <none> 2d v1.9.1 <none> CentOS Linux 7 (Core) 3.10.0-693.11.6.el7.x86_64 docker://1.12.6
node2 Ready <none> 2d v1.9.1 <none> CentOS Linux 7 (Core) 3.10.0-693.11.6.el7.x86_64 docker://1.12.6
node3 Ready <none> 2d v1.9.1 <none> CentOS Linux 7 (Core) 3.10.0-693.11.6.el7.x86_64 docker://1.12.6当前Kubernetes集群中运行的所有Pod信息:
[root@node1 ~]# kubectl get pods --all-namespaces -o wide
NAMESPACE NAME READY STATUS RESTARTS AGE IP NODE
kube-system coredns-5984fb8cbb-sjqv9 1/1 Running 0 1h 172.33.68.2 node1
kube-system coredns-5984fb8cbb-tkfrc 1/1 Running 1 1h 172.33.96.3 node3
kube-system heapster-v1.5.0-684c7f9488-z6sdz 4/4 Running 0 1h 172.33.31.3 node2
kube-system kubernetes-dashboard-6b66b8b96c-mnm2c 1/1 Running 0 1h 172.33.31.2 node2
kube-system monitoring-influxdb-grafana-v4-54b7854697-tw9cd 2/2 Running 2 1h 172.33.96.2 node3当前etcd中的注册的宿主机的pod地址网段信息:
[root@node1 ~]# etcdctl ls /kube-centos/network/subnets
/kube-centos/network/subnets/172.33.68.0-24
/kube-centos/network/subnets/172.33.31.0-24
/kube-centos/network/subnets/172.33.96.0-24而每个node上的Pod子网是根据我们在安装flannel时配置来划分的,在etcd中查看该配置:
我们知道Kubernetes集群内部存在三类IP,分别是:
Node IP:宿主机的IP地址
Pod IP:使用网络插件创建的IP(如flannel),使跨主机的Pod可以互通
Cluster IP:虚拟IP,通过iptables规则访问服务
在安装node节点的时候,节点上的进程是按照flannel -> docker -> kubelet -> kube-proxy的顺序启动的,我们下面也会按照该顺序来讲解,flannel的网络划分和如何与docker交互,如何通过iptables访问service。
Flannel
Flannel是作为一个二进制文件的方式部署在每个node上,主要实现两个功能:
为每个node分配subnet,容器将自动从该子网中获取IP地址
当有node加入到网络中时,为每个node增加路由配置
下面是使用host-gw backend的flannel网络架构图:

注意:以上IP非本示例中的IP,但是不影响读者理解。
Node1上的flannel配置如下:
其中有两个环境变量文件的配置如下:
上面的配置文件仅供flanneld使用。
还有一个ExecStartPost=/usr/libexec/flannel/mk-docker-opts.sh -k DOCKER_NETWORK_OPTIONS -d /run/flannel/docker,其中的/usr/libexec/flannel/mk-docker-opts.sh脚本是在flanneld启动后运行,将会生成两个环境变量配置文件:
/run/flannel/docker
/run/flannel/subnet.env
我们再来看下/run/flannel/docker的配置。
如果你使用systemctl命令先启动flannel后启动docker的话,docker将会读取以上环境变量。
我们再来看下/run/flannel/subnet.env的配置。
以上环境变量是flannel向etcd中注册的。
Docker
Node1的docker配置如下:
查看Node1上的docker启动参数:
我们可以看到在docker在启动时有如下参数:--bip=172.33.68.1/24 --ip-masq=true --mtu=1500。上述参数flannel启动时运行的脚本生成的,通过环境变量传递过来的。
我们查看下node1宿主机上的网络接口:
我们分类来解释下该虚拟机中的网络接口。
lo:回环网络,127.0.0.1
eth0:NAT网络,虚拟机创建时自动分配,仅可以在几台虚拟机之间访问
eth1:bridge网络,使用vagrant分配给虚拟机的地址,虚拟机之间和本地电脑都可以访问
eth2:bridge网络,使用DHCP分配,用于访问互联网的网卡
docker0:bridge网络,docker默认使用的网卡,作为该节点上所有容器的虚拟交换机
veth295bef2@if6:veth pair,连接docker0和Pod中的容器。veth pair可以理解为使用网线连接好的两个接口,把两个端口放到两个namespace中,那么这两个namespace就能打通。参考linux 网络虚拟化: network namespace 简介。
我们再看下该节点的docker上有哪些网络。
再检查下bridge网络940bb75e653b的信息。
我们可以看到该网络中的Config与docker的启动配置相符。
Node1上运行的容器:
我们可以看到当前已经有2个容器在运行。
Node1上的路由信息:
以上路由信息是由flannel添加的,当有新的节点加入到Kubernetes集群中后,每个节点上的路由表都将增加。
我们在node上来traceroute下node3上的coredns-5984fb8cbb-tkfrc容器,其IP地址是172.33.96.3,看看其路由信息。
我们看到路由直接经过node3的公网IP后就到达了node3节点上的Pod。
Node1的iptables信息:
从上面的iptables中可以看到注入了很多Kuberentes service的规则。
参考
最后更新于