一文搞懂 Kubernetes Service 网络原理

为什么需要Service ?

由于 Kubernetes 环境中 Pod 的动态特性,分配给它们的 IP 地址不是静态的。 它们是短暂的,并且每次创建或删除 Pod 时都会发生变化。

Service解决了这个问题,并提供了一种稳定的机制来连接到一组 pod。主要解决了服务怎么提供给第三方使用的问题。

默认情况下,当您在 Kubernetes 中创建服务时,会保留并分配一个虚拟 IP。 从那里,您可以使用选择器将服务关联到目标 Pod。 删除 pod 并添加新 pod 时会发生什么情况? 该服务的虚拟IP保持静态且不变。 但是,流量将到达新创建的 Pod,无需干预。 换句话说,Kubernetes 中的Service 类似于负载均衡器。

但它们是如何工作的呢?

使用 Netfilter 和 Iptables 拦截和重写流量

Kubernetes 中的服务基于两个 Linux 内核组件构建: 网络过滤器和 iptables。

  • Netfilter 是一个框架,允许配置数据包过滤、创建 NAT 或端口转换规则以及管理网络中的流量。 此外,它还屏蔽并防止未经请求的连接访问服务。
  • Iptables 是一个用户空间实用程序,允许您配置 Linux 内核防火墙的 IP 数据包过滤规则。

iptables 是建立在 netfilter 框架之上的用户空间工具。 是内核级别的框架,而 则是用户空间中的工具,用于配置和管理这个框架。

iptables 作为不同的 Netfilter 模块实现。 您可以使用 iptables CLI 动态更改过滤规则并将其插入 netfilters 挂钩点。 过滤器组织在不同的表中,其中包含用于处理网络流量数据包的链。 每个协议使用不同的内核模块和程序。

当提到 iptables 时,通常意味着用于 IPv4。对于 IPv6 规则,CLI 称为 ip6tables。

iptables 有五种类型的链,每种链都直接映射到 Netfilter 的钩子。 从 iptables 的角度来看,它们是:

  • PRE_ROUTING
  • INPUT
  • FORWARD
  • OUTPUT
  • POST_ROUTING

它们相应地映射到 Netfilter 钩子:

  • NF_IP_PRE_ROUTING
  • NF_IP_LOCAL_IN
  • NF_IP_FORWARD
  • NF_IP_LOCAL_OUT
  • NF_IP_POST_ROUTING

当数据包到达时,根据它所处的阶段,它将"触发"Netfilter 钩子,该钩子应用特定的 iptables 过滤。图片来自 learnk8s

看起来很复杂,不过不用担心。这就是我们使用 Kubernetes 的原因,以上所有内容都是通过使用Service进行抽象的,并且简单的 YAML 定义会自动设置这些规则。 如果您有兴趣查看 iptables 规则,可以连接到节点并运行:

ruby 复制代码
$ iptables-save

您还可以使用此工具可视化节点上的 iptables 链。 具有可视化 iptables 链的示例图

可能配置了数百条规则。想象一下手工去配置这数百条规则有多么麻烦。

我们已经解释了当 Pod 位于相同和不同节点时 Pod 到 Pod 的通信是如何发生的。 在 Pod-to-Service 中,通信的前半部分保持不变。

当请求从 Pod-A 开始,并且想要到达 Pod-B(在本例中将位于Service"后面")时,传输中途会发生额外的更改,原始请求通过 Pod-A 命名空间中的 eth0 接口退出, 从那里,它穿过 veth 对并到达根命名空间以太网桥。 一旦到达网桥,数据包就会立即通过默认网关转发。

与 Pod 到 Pod 部分一样,主机进行按位比较,并且由于服务的 vIP 不是节点 CIDR 的一部分,因此数据包将立即通过默认网关转发。

如果默认网关的 MAC 地址尚未出现在查找表中,则相同的 ARP 解析将会找到该地址。

现在关键的事情发生了, 就在数据包通过节点的路由过程之前,NF_IP_PRE_ROUTING Netfilter 挂钩被触发,并应用 iptables 规则。该规则会进行 DNAT 更改,并且重写Pod的A数据包目的IP。

先前的服务 vIP 目标被重写为 Pod-B的 IP 地址。 从iptables 转化之后开始,路由就与直接进行 Pod 到 Pod 通信一样。

然而,在所有这些通信之间,还利用了另一个第三个功能conntrack(连接跟踪)。 当 Pod-B 发回响应时,Conntrack 会将数据包与连接相关联,并且跟踪其来源。

NAT 严重依赖 conntrack 来工作, 如果没有连接跟踪,它就不知道将包含响应的数据包发送回哪里, 使用 conntrack 时,可以使用相同的源或目标 NAT 更改设置数据包的返回路径。

返回请求的另一半现在按相反的顺序排列。 Pod-B 接收并处理了请求,现在将数据发送回 Pod-A。 接下来会发生什么呢?

Service的响应

现在 Pod-B 发送响应,将其 IP 地址设置为源,将 Pod A 的 IP 地址设置为目标。

其余的都是一样的; SNAT 完成后,数据包到达根命名空间中的以太网桥,并通过 veth 对转发到 Pod-A。

一个网络包从应用程序到发出去经过的步骤

至此我们了解了Service的网络原理。 现在我们回过头看 k8s负载均衡 代码是如何实现的就很好理解了,整体的代码都是在维护 iptables 的规则,并且由于 iptables 会存在一定的性能问题,所以通过接口的抽象能够灵活的替换底层功能的实现。

相关推荐
weixin_453965001 小时前
[单master节点k8s部署]30.ceph分布式存储(一)
分布式·ceph·kubernetes
weixin_453965001 小时前
[单master节点k8s部署]32.ceph分布式存储(三)
分布式·ceph·kubernetes
tangdou3690986551 小时前
1分钟搞懂K8S中的NodeSelector
云原生·容器·kubernetes
later_rql4 小时前
k8s-集群部署1
云原生·容器·kubernetes
weixin_453965006 小时前
[单master节点k8s部署]31.ceph分布式存储(二)
分布式·ceph·kubernetes
大G哥9 小时前
记一次K8S 环境应用nginx stable-alpine 解析内部域名失败排查思路
运维·nginx·云原生·容器·kubernetes
妍妍的宝贝9 小时前
k8s 中微服务之 MetailLB 搭配 ingress-nginx 实现七层负载
nginx·微服务·kubernetes
福大大架构师每日一题11 小时前
23.1 k8s监控中标签relabel的应用和原理
java·容器·kubernetes
程序那点事儿11 小时前
k8s 之动态创建pv失败(踩坑)
云原生·容器·kubernetes
唐大爹1 天前
项目实战:k8s部署考试系统
云原生·容器·kubernetes