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网络架构图:

flannel网络架构(图片来自openshift)

注意:以上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的规则。

参考

最后更新于