Kubernetes 网络概念


Kubernetes网络设计有一个独特的地方:每个Pod有独立的IP地址,各个Pod可以直接互相访问,无需通过NAT。这种设计大大简化了网络层次,使得在集群内部各组件之间的连接更加自然。

Service是Kubernetes的核心概念,通过创建Service,可以为一组具有相同功能的容器应用提供一个统一的入口地址,并且将请求负载分发到后端的各个容器应用上。

一、k8s网络核心设计原则

Pod IP独立性:

在Kubernetes中,每个Pod都有一个独立的IP地址,Pod内的容器共享IP。

Pod间的通信不依赖端口映射或地址转换,这样保证了在集群内Pod间通信的直观性。

集群内网络的“扁平化”:

Kubernetes网络模型是扁平的,即所有Pod不论所在的节点都可以直接相互通信。

Kubernetes通过CNI插件实现这种扁平化的网络,CNI插件会为每个Pod分配一个IP地址,构成一个逻辑上的大二层网络,或在某些实现中构成一个无缝连接的三层网络。

CNI(Container Network Interface,容器网络接口)是一种标准,用于定义容器运行时(如 Kubernetes)如何与网络插件进行交互,以便为容器配置网络。

常见的 CNI 插件

以下是一些常用的 CNI 插件,每个插件都有其独特的功能和适用场景:

1、Flannel:

  • 简单易用,适用于小规模集群。
  • 使用 overlay 网络,通常基于 VXLAN 技术。
  • 不支持复杂的网络策略,但足以满足基本的网络需求。

2、Calico:

  • 提供高性能和灵活的网络配置。
  • 支持 IPIP 和 BGP 等网络模式,适用于大规模生产环境。
  • 提供强大的网络策略(Network Policy)支持,用于定义和实施网络安全规则。

Service抽象简化服务访问:

Service是Kubernetes中的服务发现与负载均衡抽象层。通过ClusterIP、NodePort、LoadBalancer等类型的Service,集群可以动态适应变化的Pod负载,向集群内外提供稳定的访问入口。

2. 网络通信基础

Kubernetes 的网络模型假定了所有 Pod 都在一个可以直接连通的扁平的网络空间中,这在GCE ( Google Compute Engine )里面是现成的网络模型, Kubernetes 假定这个网络已经存在。而在私有云里搭建Kubernetes 集群,就不能假定这个网络已经存在了。我们需要自己实现这个网络假设,将不同节点上的 Docker 容器之间的互相访问先打通,然后运行 Kubernetes。

2.1、Flannel 网络

Flannel 是 CoreOS 团队针对 Kubernetes 设计的一个网络规划服务,是为 Kubernetes 提供网络解决方案的开源项目。

简单来说,Flannel 的功能是让集群中的不同节点主机创建的 Docker 容器都具有全集群唯一的虚拟 IP 地址。

而且它还能在这些 IP 地址之间建立一个覆盖网络( Overlay Network ),通过这个覆盖网络,将数据包原封不动地传递到目标容器内,确保不同节点上的 Pod 之间可以相互通信。

2.2、Flannel 网络流程图:

4.png

2.3、Flannel 的主要功能

  1. Overlay Network(覆盖网络):

    • Flannel 创建了一个虚拟的覆盖网络,使用户可以将容器的流量路由到不同的物理主机上。它通过在主机之间创建一个隧道(Tunnel),使得容器间的网络通信变得透明。
  2. IP 地址管理 (IPAM):

    • Flannel 提供了一个简单的 IP 地址管理方案,用于为每个节点和节点上的 Pod 分配独立的 IP 地址段。
  3. 支持多种后端:

    • Flannel 支持多种网络后端,包括 VXLAN、UDP、host-gw 等,用户可以根据自己的需求选择合适的后端。

2.4、ETCD 与 Flannel 之间的关系:

  • 存储管理 Flannel 可分配的 IP 地址段资源
  • 监控 ETCD 中每个 Pod 的实际地址,并在内存中建立维护 Pod

2.5 Flannel 的工作原理

  1. 分配子网:

    • 在集群启动时,Flannel 会为每个节点分配一个唯一的子网,这个子网用于分配给该节点上的 Pod。
  2. 数据包封装:

    • 当一个 Pod 需要与另一个节点上的 Pod 通信时,Flannel 会负责封装数据包。对于 VXLAN 后端,Flannel 使用 VXLAN 头部封装数据包,使其可以通过底层网络传输。
  3. 路由转发:

    • Flannel 在每个节点上配置路由,确保数据包能够正确地发送到目标节点。
  4. 跨节点通信:

    • 通过上述步骤,Flannel 确保了跨节点的 Pod 间通信是可能的。

2.6 Flannel 的优点

  1. 简单易用:

    • Flannel 的安装和配置相对简单,适合中小型 Kubernetes 集群。
  2. 良好的性能:

    • 对于大部分使用场景,Flannel 提供了不错的性能,特别是使用 VXLAN 后端时。
  3. 良好的兼容性:

    • Flannel 与大多数 Kubernetes 集群兼容,并且支持多种网络后端。

2.7、Flannel 的缺点

  1. 功能相对简单:

    • Flannel 主要专注于 Pod 间的网络通信,相比其他网络解决方案如 Calico,功能相对简单。
  2. 不支持高级网络功能:

    • Flannel 不支持网络策略、安全策略等高级网络功能。
  3. 性能可能受限:

    • 对于大规模集群或高负载场景,Flannel 的性能可能不如一些更复杂的网络解决方案。

2.8 Flannel 的使用场景

  • 中小型 Kubernetes 集群:

    • Flannel 非常适合中小型 Kubernetes 集群,特别是那些不需要复杂网络策略和安全策略的场景。
  • 开发和测试环境:

    • 由于其简单易用,Flannel 也非常适合用于开发和测试环境。

3.通信模式

Kubernetes中网络通信可以分为Pod-to-Pod通信、Pod-to-Service通信以及Ingress通信(从外部流量到集群内部)。

同Pod内部通信:

同一个 Pod 共享同一个网络命名空间,共享同一个 Linux 协议栈。

不同pod通信:

不在同一台主机:docker0 网段与宿主机网卡是两个完全不同的 IP 网段,不同 Node 之间的通信只能通过宿主机的物理网卡进行

同一台机器:由 Docker0 网桥直接转发请求

Pod与Service: 目前基于性能考虑,全部为 iptables(旧版)或 ipvs (新版) 维护和转发

Pod与外网:Pod 向外网发送请求,查找路由表 , 转发数据包到宿主机的网卡,宿主网卡完成路由选择后,iptables行Masquerade ,把源 IP 更改为宿主网卡的 IP ,然后向外网服务器发送请求。

K8S集群通信

我们集群的通信方式,根据不同的条件,可以分为以下三种方式:

1、集群内相互通信;

2、集群内访问集群外;

3、集群外访问集群内。

3.1、集群内相互通信

1、DNS+ClustreIP

图片

图释:

如果podA访问podB,由于pod的IP是会经常发生变化的,所以不能直接配置podB的IP地址,所以k8s提出了一个概念为service,它包含了一个clusterIP,也就是图中的10.1.1.1,那么这样子是不是就可以了呢?显然还是不太好,因为我们配置IP地址也很麻烦,这个时候service又提供了一个dns,可以理解为别名,这样我们直接配置dns就好了。

2、headless(去中心化)

图片

图释:

我们在部署整个架构的时候,是不是经常会遇到一些去中心化的服务,比如zookeeper服务,本意是为了保证高可用的,但是这样子就面临一个问题,我们应该访问谁呢?这时候k8s就提出了一个概念,hadeless类型的service,这个服务的作用是什么呢,你可以理解为透传,就是当PodA访问这PodB的时候,他就会给你返回一个列表,podA自己做选择访问谁。

3.2、集群内访问集群外

1、IP+Port

图片

图释:

集群内的PodA直接通过IP和port地址,访问集群外的数据库就行。

2、Endpoint

图片

图释:

如果有100个服务要访问外部的mysql呢?难道我们配置100次吗?万一哪天mysql的IP地址变了,我们怎么办呢?这个时候就引入了一个endpoint。使用endprint来做代理,它有一个和它同名的service,再往上面呢,它还有一个DNS,以供内部使用,我们的endpoint上面配置上外部服务的地址。

这个有什么好处呢?好处就是内部的服务访问的地址不会变,有变化的仅仅是endpoint,有问题的时候我们只需要修改endpoint即可立刻恢复服务。

3.3、集群外访问集群内

1、node-port

图片

图释: 当集群外的服务,想访问集群内的PodA的时候,每个node都会开启一个8080端口,虽然实际上podA只在node1上,但是也还是每个node都会开启一个8080端口号,然后client随便访问一个node节点的8080端口,然后内部都会转到podA上,但是这种方式不推荐,因为这样的话会形成资源浪费。

2、hostport

图片

图释: 从上面看,差别不大,就是少了个端口,少了两条线嘛,实际上也就是相差不大,nodeport的方式是每个节点都开了8080端口,hostport的方式,是只在podA服务存在的节点上开启8080端口,节省了资源,提高了命中率。

3、Ingress

图片

图释:

当我们要通过域名,访问到内部的pod服务的时候,由于pod的IP存在不稳定性,所以不能直接做在内部通过nginx做映射,这个时候k8s提供一个ingress的概念来帮我们实现,也就是通过ingress配置域名映射到哪个路径下的哪个服务,让他来帮你转发到具体的服务就行了。

  • 用户通过指定的域名发起请求。

  • Ingress控制器根据请求的域名和路径,将请求转发到相应的Service。

  • Service负载均衡至具体的Pod。

图片

4. Kube-Proxy深入解析

Kube-Proxy在Kubernetes集群中的主要作用是管理Service的负载均衡。Kube-Proxy有三种工作模式:User-Space模式、iptables模式和IPVS模式。

4.1 User-Space模式

工作原理:请求首先进入Kube-Proxy的用户空间进程,然后再转发到后端Pod。

性能缺陷:性能较低,逐渐被弃用。

4.2 iptables模式

工作原理:Kube-Proxy利用iptables规则将请求直接转发到后端Pod,不需要进入用户空间。

特点:性能相对较好,Kubernetes默认使用的模式。

4.3 IPVS模式

工作原理:基于Linux内核的IPVS模块进行负载均衡。

优势:IPVS支持更多负载均衡算法,性能更优。

适用场景:适合大规模集群或高并发流量场景。

以上就是k8s中几乎所有的通信方式了,在实际部署之前我们需要提前了解,我们在接下来的实操过程中都会慢慢掌握上面的通信方式。