(十)深入理解Kubernetes网络

(十)深入理解Kubernetes网络

K8s四层网络之Pod网络

1

Pod网络概念模型

Pod相当于是K8s云平台中的虚拟机,它是K8s的基本调度单位。

2

  • 同一节点的Pod网络

    1. 3

      网络依次进入的顺序为主机网卡eth0,docker虚拟网桥,虚拟网卡veth0。pause容器是一个特殊的容器,这个容器运行的唯一目的是为Pod建立共享的veth0网络接口。docker ps命令可以查看到这个容器的状态

    2. 4

    同样的docker0在同一个Pod下面分配了172.17.2 和 172.17.3 ,这两个网络是可以互通的

不同节点间的Pod网络

5

  • 路由方案

    6

    通过路由设备为K8s集群的Pod网络单独划分网段,并配置路由器支持Pod网络的转发。这种方案依赖于底层的网络设备,但是不引入额外性能开销。注意公有云网络不支持路由方案

  • 覆盖网络方案

    7

    覆盖网络,就是在现有网络之上再建立一个虚拟网络,实现技术有很多,例如flannel/weavenet等等,这些方案大都采用隧道封包技术。简单理解,Pod网络的数据包,在出节点之前,会先被封装成节点网络的数据包,当数据包到达目标节点,包内的Pod网络数据包会被解封出来,再转发给节点内部的Pod网络。这种方案对底层网络没有特别依赖,但是封包解包会引入额外性能开销。

  • K8s容器网络接入接口CNI

    考虑到Pod网络实现技术众多,为了简化集成,K8s支持CNI(Container Network Interface)标准,不同的Pod网络技术可以通过CNI插件形式和K8s进行集成。

Service网络(集群内部网络)

Service网络概念模型

8

  1. 服务发现(Service Discovery): Client Pod如何发现定位Account-App集群中Pod的IP?况且Account-App集群中Pod的IP是有可能会变的(英文叫ephemeral),这种变化包括预期的,比如Account-App重新发布,或者非预期的,例如Account-App集群中有Pod挂了,K8s对Account-App进行重新调度部署。

  2. 负载均衡(Load Balancing):Client Pod如何以某种负载均衡策略去访问Account-App集群中的不同Pod实例?以实现负载分摊和HA高可用。

服务发现

  • DNS域名服务

    DNS域名服务是一种较老且成熟的标准技术,实际上DNS可以认为是最早的一种服务发现技术。

9

缺点:

       1. 不同DNS客户端实现功能有差异,有些客户端每次调用都会去查询DNS服务,造成不必要的开销,而有些客户端则会缓存DNS信息,默认超时时间较长,当目标PodIP发生变化时(在容器云环境中是常态),存在缓存刷新不及时,会导致访问Pod失效。
       2. DNS客户端实现的负载均衡策略一般都比较简单,大都是RoundRobin,有些则不支持负载均衡调用。
  • Service Registry+Client

    例如Netflix开源的Eureka + Ribbon,HashiCorp开源的Consul,还有阿里新开源Nacos等,都是这个方案的典型代表。

    10

  • K8s的Service网络

    11

在K8s平台的每个Worker节点上,都部署有两个组件,一个叫Kubelet,另外一个叫Kube-Proxy,这两个组件+Master是K8s实现服务注册和发现的关键。

服务注册发现流程

  1. 在服务Pod实例发布时(可以对应K8s发布中的Kind: Deployment),Kubelet会负责启动Pod实例,启动完成后,Kubelet会把服务的PodIP列表汇报注册到Master节点。

  2. 通过服务Service的发布(对应K8s发布中的Kind: Service),K8s会为服务分配ClusterIP,相关信息也记录在Master上。

  3. 在服务发现阶段,Kube-Proxy会监听Master并发现服务ClusterIP和PodIP列表映射关系,并且修改本地的linux iptables转发规则,指示iptables在接收到目标为某个ClusterIP请求时,进行负载均衡并转发到对应的PodIP上。

  4. 当有消费者Pod需要访问某个目标服务实例的时候,它通过ClusterIP发起调用,这个ClusterIP会被本地iptables机制截获,然后通过负载均衡,转发到目标服务Pod实例上。

区别

  1. 两者都是采用客户端代理(Proxy)机制。和Ribbon一样,K8s的代理转发和负载均衡也是在客户端实现的,但Ribbon是以Lib库的形式嵌入在客户应用中的,对客户应用有侵入性,而K8s的Kube-Proxy是独立的,每个Worker节点上有一个,它对客户应用无侵入。K8s的做法类似ServiceMesh中的边车(sidecar)做法。
  2. Ribbon的代理转发是穿透的,而K8s中的代理转发是iptables转发,虽然K8s中有Kube-Proxy,但它只是负责服务发现和修改iptables(或ipvs)规则,实际请求是不穿透Kube-Proxy的。注意早期K8s中的Kube-Proxy代理是穿透的,考虑到有性能损耗和单点问题,后续的版本就改成不穿透了。
  3. Ribbon实现服务名到服务实例IP地址的映射,它只有一层映射。而K8s中有两层映射,Kube-Proxy实现ClusterIP->PodIP的映射,Kube-DNS实现ServiceName->ClusterIP的映射。

外部接入网络

LoadBalancer

12

Ingress

13

Ingress落地方案:

传统的Nginx/Haproxy可以,现代的微服务网关Zuul/SpringCloudGateway/Kong/Envoy/Traefik等等都可以。当然,谷歌别出心裁给这个东东起名叫Ingress,它还是做了一些包装,以简化对Ingress的操作。如果你理解了原理,那么完全可以用Zuul或者SpringCloudGateway,或者自己定制开发一个反向代理,来替代这个Ingress。部署的时候以普通Service部署,将type设定为LoadBalancer即可

Ingress是一个7层反向代理,如果你要暴露的是4层服务,还是需要走独立LB+IP方式

Kubectl Proxy & Port Forward

在本地开发测试环境,需要对本地部署的K8s环境中的服务或者Pod进行快速调试或测试

14