本文档是参考了几篇博客以及极客时间SpringBoot与Kubernetes云原生微服务实践之后总结的文档。
k8s他是一个强大的平台,其网络架构是十分复杂的。我们分解成四层网络抽象,建立直观易懂的概念模型,指导我们开发实践。

(1)第0层Node节点互通互连。
(2)第1层POD虚拟机互通互连。
(3)第2层Service服务发现与负载均衡。
(4)第3层外部接入网络。

2.1 Node网络


Node我们基本上可以理解为一台机器或者虚拟机。一般通过公有云,私有云等网络基础设施支撑,实现机器之间互通互联。

2.2pod网络


POD做为k8s容器调度的基本单位。一个Node上可以有多个POD。POD中有一个或者多个容器,容器共享网络栈与存储。我们执行ip addr发现好多veth开头的网络,这些网络是干啥用的那?那么POD内部怎么互通?POD与POD之间又怎么互通那?


eth0是Node节点的网卡。地址是10.100.0.2/24。节点流量出入设备以及集群互通互联的基础设备。docker0是默认情况下启动docker之后会创建网桥。veth0是支持POD内容器网络互通的虚拟设备。POD与POD以及docker0属于同一个网段。pause 和pod是一一对应的 。每个Pod里运行着一个特殊的被称之为Pause的容器,为POD与veth0建立共享网络接口。同一个Pod里的容器之间仅需通过localhost就能互相通信。
POD与POD互通可以大致分成两种方案。
(1)路由表
完成pod ip和node ip的路由匹配。找到node之后再访问对应ip的pod。
缺点:引入了额外的设备
优点:性能开销小

(2)覆盖网络
基于隧道封装包技术,PODX给PODY发送数据,将数据包封装成Node节点的数据包,然后路由到对应的节点上,再拆包,路由到对应的POD上。例如Flannel和Weavenet。
缺点:封包解包会引入额外的系统开销。
优点:性能开销小

(3)CNI,容器网络接口。
CNI屏蔽了POD网络细节,kubelet可以通过CNI接口与POD网络进行交互。


2.3Service服务发现与负载均衡


通常我们部署服务部署多个,避免单点问题,同时均摊负载。这样多个相同的POD就分散在K8S集群的各个节点中。Service通过LabelSelector将相同标签的POD组合在一起,同时对外提供负载均衡与服务发现。service对外通过clusterIP(虚拟IP即VIP)进行访问,从而屏蔽了POD的网络变化。service通过POD名字进行访问。

2.3.1 K8S的服务发现原理
(1)DNS策略:k8s引入了kube-nds来实现域名访问服务。不过建立在clusterIP和Service网络之上。
(2)服务注册中心策略:引入serviceRegistry来做服务发现。POD启动之后,将ip,端口等信息注册到服务注册中心。在k8s集群中可以通过etcd来实现服务注册中心。client通过服务注册中心来发现服务提供者信息,从而发起调用。
(3)两者结合
Kube-DNS监听K8S集群MASTER中服务名与集群ip的映射,并且自己保存一份路由匹配关系。
kube-Proxy监听K8S集群MASTER中集群ip与PODip的映射,并且自己保存一份路由匹配关系。
k8sMaster充当服务注册中心。 当消费者pod访问服务提供者pod,通过kube-proxy完成clusterIp与Pod的ip转化。

2.3.2 kube-proxy
kube-proxy 负责Pod网络代理,其有三种工作模式:(1)用户空间代理模式(基本上已经淘汰)。(2)iptables模式(中小规模k8s)。(3)IPVS模式(大规模k8s集群)。
kube-proxy默认使用的是iptables模式,通过各个node节点上的iptables规则来实现service的负载均衡,但是随着service数量的增大,iptables模式由于线性查找匹配、全量更新等特点,其性能会显著下降。从k8s的1.8版本开始,kube-proxy引入了IPVS模式,IPVS模式与iptables同样基于Netfilter,但是采用的hash表,因此当service数量达到一定规模时,hash查表的速度优势就会显现出来,从而提高service的服务性能。
问题:对于要暴露的服务,Service网路是内部网络,通过外部咋访问那?

2.4k8s对外暴露服务方案

(1)LoadBalancer暴露给外网
浏览器通过load-balancer路由到某一个node节点上,交给kube-Proxy访问Service后面的一组POD,根据负载均衡算法选择一个pod进行服务调用。缺点:在公有云部署若暴露哪个服务就需要多个SLB。

(2) NodePort 暴露外网
若我们知道所有NodePort地址,将Service直接暴露到节点网络上, K8s会在每个Worker节点上都开启对应的NodePort端口。那么通过NodePort访问集群内部也是没问题的,一般用于测试开发环境。NodePort背后是kubeProxy。kubeProxy是沟通Service网络,Pod网络以及Node网络的桥梁。
(3)Ingress
同时将多个Http服务暴露到外网,但是只需要申请一个或者少量LB,七层反向代理。
例如nginx-Ingress。通过nginx-Ingress反向代理后端服务。
(4)KubectlProxy & Port Forward

办法一,通过kubectl proxy命令,在本机上开启一个代理服务,间接访问K8s集群内的任意服务。原理即:Kubectl代理服务通过Master上的API Server间接访问K8s集群内服务,因为Master知道集群内所有服务信息。这种方式只限于7层HTTP转发。办法二,通过kubectl port-forward命令,本机上开启一个转发端口,通过TCP转发,间接转发到K8s内部的某个Pod的端口上。办法三,通过kubectl exec进入Pod容器上去执行linux命令。
三、 参考资料

1. https://blog.csdn.net/yang75108/article/details/101268208
2.https://www.cnblogs.com/kevingrace/p/6655153.html
3.





