转载大佬博文:https://mp.weixin.qq.com/s/IxhJp16RbBsDlNrh1uTtdw
docker的四种网络类型
(1)bridge:这是Docker默认的网络驱动,此模式会为每一个容器分配NetworkNamespace和设置IP等,并将容器连接到一个虚拟网桥上,如果未指定网络驱动,就默认使用此驱动。
(2)host:此网络驱动直接使用宿主机的网络。
(3)none:此驱动不构造网络环境,如果采用了none网络驱动,那么就只能使用loopback网络设备,容器只能使用127.0.0.1的本机网络。
(4)overlay:可以实现容器跨主机通信
Bridge网络介绍
1.网络模型图
2.Bridge网络的构建过程,对上图的各个网络名称做解释说明
(1)安装Docker时,创建一个名为docke0的虚拟网桥,虚拟网桥使用“10.0.0.0-10.255.255.255 “、”172.16.0.0-172.31.255.255″和“192.168.0.0——192.168.255.255”这三个私有网络的地址范围。
通过 ifconfig命令可以查看docker0网桥的信息:
通过 docker network inspect bridge 可以查看网桥的子网网络范围和网关:
(2)运行容器时,会在宿主机上创建虚拟网卡vethpair设备,vethpair设备是成对出现的,从而组成一个数据通道,数据从一个设备进入,就会从另一个设备出来。将vethpair设备的一端放在新创建的容器中,命名为eth0;另一端放在宿主机的docker0中,以veth为前缀的名字命名。通过brctlshow 命令查看放在docker0中的veth pair设备
ifconfig
brctl show
3.外部访问
bridge的docker0是虚拟出来的网桥,因此无法被外部的网络访问。因此需要在运行容器时通过-p和-P参数将容器的端口映射到宿主机上相应的端口。实际上Docker是采用NAT的方式,将容器内部的服务监听端口与宿主机的某一个端口port 进行绑定,使得宿主机外部可以将网络报文发送至容器。
1)通过-P参数,将容器的端口映射到宿主机的随机端口:
docker run -P {images}
2)通过-p参数,将容器的端口映射到宿主机的制定端口:
docker run -p {hostPort}:{containerPort} {images}
kubernetes常见的网络通信方式
1.pod内部容器间的通信:同一个pod内的多个容器间的通信
2.pod和pod之间的通信:从一个pod Ip到另一个pod Ip
3.pod与service通信:pod ip到serviceip
(1)pod内部容器之间通信
pod内部的容器是共享网络名称空间的,所以容器直接可以使用localhost访问其他容器;k8s在启动容器的时候会先启动一个Pause容器,这个容器就是实现这个功能的。
pause:
每个Pod里运行着一个特殊的被称之为Pause的容器,其他容器则为业务容器,这些业务容器共享Pause容器的网络栈和Volume存储卷,因此他们之间通信和数据交换更为高效,在设计时我们可以充分利用这一特性将一组密切相关的服务进程放入同一个Pod中。
(2)pod与pod之间的通信
此种类型又分为两种情况:
两个pod在同一台节点上:此时是利用docker默认的网桥bridge方式互连容器的。
两个pod在不同节点上:这种情况k8s官方推荐的是使用flannel网络,pod的ip分配由flannel统一分配,通讯过程也是走flannel的网桥方式。
(3)pod与service服务之间的通信
通过暴露主机IP和端口的形式进行通讯
要解决上面的几种通信问题,需要靠CNI网络插件实现
要解决上面四种通信的问题,需要靠CNI插件接口:
kubernetes中的网络插件
Kubernetes中常见的网络插件有哪些?
1.flannel:能提供ip地址,但不支持网络策略
2.calico:既提供ip地址,又支持网络策略
3.canal:flannel和calico结合,通过flannel提供ip地址,calico提供网络策略
什么叫做网络策略?
网络策略:可以达到多租户网络隔离,可以控制入网和出网流量,入网和出网ip访问的一种策略
flannel
一、flannel介绍
Flannel是CoreOS团队针对Kubernetes设计的一个网络服务,它的功能是让集群中的不同节点创建的Docker容器都具有全集群唯一的虚拟IP地址,Flannel的设计目的就是为集群中的所有节点重新规划IP地址,从而使得不同节点上的容器能够获得“同属一个内网”且”不重复的”IP地址,并让属于不同节点上的容器能够直接通过内网IP通信,Flannel实质上是一种“覆盖网络(overlaynetwork)”,也就是将TCP数据包装在另一种网络包里面进行路由转发和通信,目前已经支持udp、vxlan、host-gw、aws-vpc、gce路由等数据转发方式。
二、flannel支持的路由转发方式
1.vxlan,包含以下两种模式
(1) vxlan:叠加网络模式,利用内核级别的VXLAN来封装host之间传送的包;
(2) Directrouting:直接路由模式,当主机位于同一子网时,启用直接路由(类似host-gw),通过宿主机的物理网卡通信;
2.host-gw:直接路由模式,要求所有pod在同一个网段中,host-gw性能好,依赖少,并且易于设置
3.UDP: 不可用于生产环境,仅在内核或网络无法使用VXLAN或 host-gw时,用 UDP 进行调试
三、flannel网络原理图
原理图解释说明
1.网卡和组件说明
安装flannel时会创建一个名为flannel0的网桥,这个网桥的一端连接docker0的网桥,另一端连接一个名为flanneld的服务进程。
Flanneld守护进程:它需要连etcd,利用etcd来管理可分配的IP资源,同时监控etcd中每个Pod的实际地址,将docker0发给它的数据包装起来,利用物理网络的连接将数据包投递到目标flanneld上,从而完成pod到pod之间的通信
2.ping包走向
(1)数据从源容器中发出后,经由所在主机的docker0虚拟网卡转发到flannel0虚拟网卡,flanneld服务监听在网卡的另外一端。
(2)源主机的flanneld服务将原本的数据内容封装成一个数据包,然后根据自己的路由表投递给目的节点的flanneld服务,数据到达以后被解包,然后直接进入目的节点的flannel0虚拟网卡,然后被转发到目的主机的docker0虚拟网卡,最后就像本机容器通信一样由docker0路由到达目标容器。
注:
flannel通过Etcd分配了每个节点可用的IP地址段后,可以保证每个结点上容器分配的地址不冲突。
四、flannel的原理
flannel旨在解决不同节点上的容器网络互联问题,大致原理是为每个 host 分配一个子网,容器从此子网中分配IP,这些 IP可以在 host间路由,容器间无需 NAT 转发就可以跨主机通信,为了在各个主机间共享信息,flannel 用 etcd(如果是k8s集群会直接调用k8s api)存放网络配置、已分配的子网、主机ip等信息。
通过具体例子解释容器跨节点通信时数据包走向
假设容器1是nginx,容器2是tomcat
(1)在发送端的node1节点上,数据请求从nginx容器(10.0.46.2:2379)发出后,首先经由所在主机的docker0虚拟网卡(10.0.46.1)转发到flannel0虚拟网卡(10.0.46.0)。
(2)接着flannel服务将原本的数据内容UDP封装后根据自己的路由表投递给目的节点的flanneld服务。在此包中,包含有router-ip(宿主机源ip:192.168.8.227 ;宿主机目的ip:192.168.8.228),还有容器ip(source:10.0.46.2:2379dest:10.0.90.2:8080)等数据信息。
(3)然后在接收端node2节点上,数据到达以后被解包,直接进入目的节点的flannel0虚拟网卡中(10.0.90.0),且被转发到目的主机的docker0虚拟网卡(10.0.90.1),最后就像本机容器通信一样由docker0路由到达目标 tomcat 容器(10.0.90.2:8080)。
五、flannel部署及参数配置
1.部署
kubectl apply -f https://raw.githubusercontent.com/coreos/flannel/master/Documentation/kube-flannel.yml
kubectl get pods -n kube-system -o wide 显示如下:
kubectl get configmap -n kube-system 显示如下:
这个kube-flannel-cfg用来设置上面看到的flannel是怎么运行的,它可以把相关的变量注入到flannel的pod中。
kubectl get configmap kube-flannel-cfg -n kube-system -o yaml可显示configmap的yaml文件内容,具体内容在备注列出
net-conf.json: | { "Network": "10.244.0.0/16", "Backend": { "Type": "vxlan" } } 上面可以看到使用的后端网络模型是vxlan,为pod分配的网段是10.244.0.0/16
2.把flannel后端的通信类型修改成Directrouting
重新修改flannel的yaml文件
cd/root/manifests/
mkdir flannel
cd flannel
修改kube-flannel.yml文件
kube-flannel.yaml这个文件里在net-conf.json字段增加了”Directrouting”: true,表示是使用直接路由模式,如果没有这个字段就表示使用的是vxlan这种叠加网络模式通信。
kubectl delete -f kube-flannel.yml
等到上面关于flannel的pod都删除之后再重新执行:
kubectl apply -f kube-flannel.yml
kubectl get pods -n kube-system 显示如下,说明重新生成了flannel这个pod,这时后端通信类型使用的就是directrouting了
验证是否是通过Directrouting(直接路由模式)通信
cd /root/manifests
kubectl apply -f deploy-myapp.yaml
cat deploy-myapp.yaml
apiVersion: apps/v1 kind: Deployment metadata: name: myapp-deploy namespace: default spec: replicas: 3 selector: matchLabels: app: myapp release: canary template: metadata: labels: app: myapp release: canary spec: containers: - name: myapp image: ikubernetes/myapp:v1 ports: - name: http containerPort: 80
kubectl get pods -o wide 显示如下,说明pod创建成功:
窗口1:
kubectl exec -itmyapp-deploy-69b47bc96d-7s7zs -- /bin/sh
窗口2:
kubectl exec -itmyapp-deploy-69b47bc96d-lm4m4 -- /bin/sh
ping10.244.0.6
窗口3:抓包
tcpdump -i ens160 -nnhost 172.21.0.100 显示如下:
上面可以看到两个pod之间的通信是通过ens160,而不是overlay(覆盖网络),这样就提高了网络传输性能;如果两个节点是跨网段的,那么就会降级到vxlan(叠加网络)模式,否则就可以使用直接路由模式。
3.把flannel的后端通信方式改成host-gw
修改kube-flannel.yml文件的如下部分
net-conf.json: | { "Network":"10.244.0.0/16", "Backend":{ "Type":"host-gw" } }
注:上面修改flannel的网络模式,一般在刚开始安装flannel的时候修改,不要在线上直接修改
4.flannel中vxlan和host-gw的区别
vxlan模式下的的vxlan是一种覆盖网络;host-gw是直接路由模式,将主机作为网关,依赖于纯三层的ip转发。
不同网络模型的性能分析
1.vxlan的Directrouting模式和host-gw模式性能一样,都是通过宿主机的物理网络进行通信,效率高于vxlan的vxlan模式,但是不能实现跨网段通信; 2.如果要跨网段通信vxlan的Directrouting模式会自动降级到vxlan的vxlan这种叠加网络模式
5.Flannel网络优点:
1)集群中的不同Node主机创建的Docker容器都具有全集群唯一的虚拟IP地址。
2)etcd保证了所有node上flanned所看到的配置是一致的,同时每个node上的flanned监听etcd上的数据变化,实时感知集群中node的变化
6.Flannel网络缺点:
不支持pod之间的网络隔离,不支持网路策略