25. Service——负载均衡机制实现原理
本章讲解知识点
- Service 的负载均衡机制如何实现的
- Service 的类型
<br>
1. Service 的负载均衡机制如何实现的
上一节我们讲述了 Service 将流量转发到后端 Pod,实现了负载均衡的功能,那么其中的原理是什么?我们接下来讲述。
1.1 基本概念
Service 的负载均衡机制是通过 kube-proxy 实现的。kube-proxy 是 Kubernetes 系统中的一个网络代理组件,它在每个节点上运行,kube-proxy 会在节点上加入转发规则(即 iptables 规则或 ipvs 规则),将 Service 的 Cluster IP 地址和端口号映射到后端 Pod 的 Endpoint 上( IP 地址和端口号)。同时 kube-proxy 监听 Service 和 Endpoint 对象的变化(例如 Pod 的创建、删除、IP 地址变更等),并根据 Service 和 Endpoint 对象的变化,为 Service 创建新的对应的负载均衡规则(即 iptables 规则或 ipvs 规则)。
1.2 iptables
iptables 是一种在 Linux 操作系统上使用的网络包过滤工具,它可以根据自定义的规则对网络数据包进行过滤、修改、重定向、丢弃等操作。iptables 可以在 Linux 内核中的网络协议栈中拦截数据包,进行各种复杂的过滤和转发处理。
在 Kubernetes 中,kube-proxy 通过 iptables 模式实现 Service 的负载均衡功能。kube-proxy 会在每个节点上维护一个 iptables 规则集,这个规则集会根据 Service 和 Endpoint 的信息动态地生成和更新。当请求到达节点时,iptables 会根据规则集中的负载均衡策略将请求转发到相应的 Pod。说的直白点,流量到达 Service 后流向哪个后端 Pod,就是 iptables 规则决定的。
iptables 有四种表(table):filter、nat、mangle 和 raw。其中 filter 表用于防火墙过滤,nat 表用于网络地址转换,mangle 表用于数据报的特殊处理,raw 表用于控制数据包是否被连接跟踪系统跟踪。
iptables 规则表可以分为四种类型:
- Filter 表:Filter 表是最常用的规则表,用于过滤数据包并决定是否允许通过。Filter 表包括三个预定义的链:INPUT、OUTPUT 和 FORWARD,分别用于处理目标地址为本地主机、源地址为本地主机和通过本地主机转发的数据包。
- NAT 表:NAT 表用于实现网络地址转换(Network Address Translation)。NAT 表包括三个预定义的链:PREROUTING、POSTROUTING 和 OUTPUT,分别用于在数据包进入、离开和发出本地主机时进行地址转换。
- Mangle 表:Mangle 表用于修改数据包的特定字段,如TTL、TOS、IP、ID 等。Mangle 表包括五个预定义的链:PREROUTING、OUTPUT、INPUT、FORWARD 和 POSTROUTING。
- Raw 表:Raw表用于控制数据包是否被连接跟踪系统跟踪。Raw 表包括两个预定义的链:PREROUTING 和 OUTPUT。
iptables 规则链有五种:
- PREROUTING :在数据包进入路由之前使用,可以进行 DNAT(目标地址转换)和负载均衡等操作。
- INPUT :用于对发往本机的数据包进行过滤和处理。
- OUTPUT :用于对由本机发出的数据包进行过滤和处理。
- FORWARD :用于对转发给其他主机的数据包进行过滤和处理。
- POSTROUTING :在数据包从路由中出去之前使用,可以进行 SNAT(源地址转换)等操作。
除了预定义的链之外,用户还可以创建自定义链,并在规则表中进行引用。自定义链可以使 iptables 规则更加模块化和可维护。
1.3 处理规则
在 Linux 中,处理规则(Match Rule)是 iptables 规则中最重要的部分之一,用于匹配网络数据包的特定属性,并决定对数据包的处理方式。iptables 处理规则由匹配条件和动作两部分组成。
匹配条件是用于匹配网络数据包的属性,如源地址、目标地址、协议类型、端口号等。iptables 提供了多种匹配条件,可以基于数据包的不同属性进行过滤和匹配。
动作是用于决定如何处理匹配到的数据包,如 DROP、ACCEPT、REJECT、REDIRECT 等。DROP 用于丢弃匹配到的数据包,ACCEPT 用于允许匹配到的数据包通过,REJECT 用于拒绝匹配到的数据包并返回错误消息,REDIRECT 用于将匹配到的数据包重定向到指定的端口或 IP 地址。
iptables 处理规则的语法如下:
iptables [-t table] <chain> [options] [-j target]
其中,-t
选项用于指定规则表,默认为 filter 表;<chain>
用于指定规则链,可以是预定义链或自定义链;[options]
用于指定匹配条件;-j
选项用于指定动作。
例如,以下命令用于在 filter 表的 INPUT 链中添加一条处理规则,匹配源地址为 192.168.0.1,目标端口为 80 的 TCP 数据包,并将其丢弃:
iptables -A INPUT -t filter -s 192.168.0.1 -p tcp --dport 80 -j DROP
iptables 处理规则可以通过多种命令进行管理,如添加、删除、修改、查询等。用户可以根据自己的需要使用 iptables 命令来管理 iptables 处理规则,实现网络安全和访问控制。
1.4 iptables 命令
规则表的使用需要使用 iptables 命令进行管理,用户可以使用 iptables 命令来创建、删除、修改规则表中的规则和链。
以下是 iptables 常用的命令和选项:
- 添加规则:-A 或 --append使用 -A 选项可以在规则链的末尾添加一条规则。例如,以下命令将在 INPUT 链中添加一条处理规则,匹配源地址为 192.168.0.1,目标端口为 80 的 TCP 数据包,并将其丢弃:iptables -A INPUT -s 192.168.0.1 -p tcp --dport 80 -j DROP
- 删除规则:-D 或 --delete使用 -D 选项可以删除规则链中的一条规则。例如,以下命令将从 INPUT 链中删除匹配源地址为 192.168.0.1,目标端口为 80 的 TCP 数据包的规则:iptables -D INPUT -s 192.168.0.1 -p tcp --dport 80 -j DROP
- 修改规则:-R 或 --replace使用 -R 选项可以修改规则链中的一条规则。例如,以下命令将替换 INPUT 链中的第一条规则,匹配源地址为 192.168.0.1,目标端口为 80 的 TCP 数据包,并将其拒绝:iptables -R INPUT 1 -s 192.168.0.1 -p tcp --dport 80 -j REJECT
- 查看规则:-L 或 --list使用 -L 选项可以列出指定规则链中的所有规则。例如,以下命令将列出 INPUT 链中的所有规则:iptables -L INPUT
- 清除规则:-F 或 --flush使用 -F 选项可以清除指定规则链中的所有规则。例如,以下命令将清除 INPUT 链中的所有规则:iptables -F INPUT
- 保存规则:-S 或 --save使用 -S 选项可以将当前的 iptables 规则保存到文件中。例如,以下命令将保存当前 iptables 规则到文件 /etc/iptables/rules.v4 中:iptables-save > /etc/iptables/rules.v4
- 恢复规则:-I 或 --insert使用 -I 选项可以从文件中恢复保存的 iptables 规则。例如,以下命令将从文件 /etc/iptables/rules.v4 中恢复保存的 iptables 规则:iptables-restore < /etc/iptables/rules.v4
以上是 iptables 常用的命令和选项,还有一些其他的选项和命令可以用于更加高级的 iptables 配置和管理。用户可以通过 man iptables
命令查看 iptables 的完整帮助文档。
1.5 kube-proxy 的代理模式
kube-proxy 是 Kubernetes 集群中的一个组件,它实现了 Kubernetes Service 的负载均衡功能
在 Kubernetes 中,kube-proxy 有三种代理模式:
- userspace(默认):kube-proxy 在每个 Node 上通过一个 userspace 进程监听 Service 的 ClusterIP 和端口,将请求通过 NAT 的方式转发到后端 Pod 上。效率最低,不再推荐使用。
- iptables:kube-proxy 通过Linux Kernel 设置 iptables 规则实现 Service 的负载均衡,这种方式效率较高,能够支持大规模集群使用。但是,如果某个后端 Endpoint 在转发时不可用,此次客户端请求就会得到失败的响应,相对于 userspace 模式来说更不可靠。此时应该通过为 Pod 设置 readinessprobe(服务可用性健康检查)来保证只有达到 ready 状态的 Endpoint 才会被设置为 Service 的后端 Endpoint。
- ipvs:kube-proxy 通过设置 Linux Kernel 的 netlink 接口设置 IPVS 规则,转发效率和支持的吞吐率都是最高的。ipvs 模式要求 Linux Kernel 启用 IPVS 模块,如果操作系统未启用 IPVS 内核模块, kube-proxy 则会自动切换至 iptables 模式。
同时 ipvs 模式支持更多的负载均衡策略,如下:
- 轮询(Round Robin,RR):依次将请求分配到后端服务器,循环往复。
- 加权轮询(Weighted Round Robin,WRR):根据服务器的权重分配请求,权重越高的服务器被分配到的请求越多。
- 最少连接(Least Connections,LC):将请求分配到当前连接数最少的服务器。
- 源地址哈希(Source Hashing,SH):根据请求来源的 IP 地址进行散列,将相同 IP 地址的请求分配到同一台后端服务器上。
- 永不排队(never queue)
kube-proxy 作为 Kubernetes 重要组件,我们讲在以后章节详细讲解。
1.6 小实验
这里我们有必要简单实验,来帮助读者更好地理解 Service + kube-proxy + iptables 是如何实现负载均衡的。
在 iptables 模式下,kube-proxy 会根据 Service 以及 endpoints 对象的改变来实时刷新规则,kube-proxy 使用了 iptables 的 filter 表和 nat 表,并对 iptables 的链进行了扩充,自定义了 KUBE-SERVICES、KUBE-EXTERNAL-SERVICES、KUBE-NODEPORTS、KUBE-POSTROUTING、KUBE-MARK-MASQ、KUBE-MARK-DROP、KUBE-FORWARD 七条链。
另外还新增了以 “KUBE-SVC-xxx” 和 “KUBE-SEP-xxx” 开头的数个链,除了创建自定义的链以外还将自定义链插入到已有链的后面以便劫持数据包。
我们查看一下 Service 和 Pod:
[root@master mtuser]# kubectl get svc NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE my-first-deploy ClusterIP 10.97.139.74 <none> 8080/TCP 18d [root@master mtuser]# kubectl get pod -owide NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES my-first-deploy-785c6c79d9-7bgf5 1/1 Running 0 18d 10.244.1.137 node1 <none> <none> my-first-deploy-785c6c79d9-g4xr7 1/1 Running 0 17d 10.244.1.138 node1 <none> <none>
接下来我们导出 iptables:
iptables-save > iptables
可以通过 iptables -t nat -L -n
和 iptables -t filter -L -n
命令查看到 kube-proxy 生成了一系列 iptables 规则。
从 Pod 中访问 clusterIP 的 iptables 规则流向为:
PREROUTING --> KUBE-SERVICES --> KUBE-SVC-xxx --> KUBE-SEP-xxx
1.对于进入 PREROUTING 链的都转到 KUBE-SERVICES 链进行处理:
[root@master mtuser]# grep KUBE-SERVICES iptables | grep PREROUTING -A PREROUTING -m comment --comment "kubernetes service p
剩余60%内容,订阅专栏后可继续查看/也可单篇购买
本专刊适合于立志转行云计算的小白,有一定的编程、操作系统、计算机网络、数据结构、算法基础。 本专刊同时也适合于面向云计算(Docker + Kubernetes)求职的从业者。 本专刊囊括了云计算、VMWare、Docker、Kubernetes、Containerd等一系列知识点的讲解,并且最后总