kube-proxy 简介
kube-proxy
是 K8s 中负责实现服务暴露和负载均衡的组件。它为 K8s 集群中的 Service 提供网络代理和负载均衡功能。kube-proxy
支持两种工作模式:iptables
和 ipvs
,它们分别在性能和维护性上有所不同。
1. kube-proxy 工作模式
1.1 iptables
iptables
是一种传统的网络规则管理工具,K8s 最初默认使用它来处理服务的代理和负载均衡。kube-proxy
在 iptables
模式下工作时,它会根据规则集,将流量路由到相应的 Pod。
- 性能问题:由于
iptables
基于规则链的方式,随着规则数量的增加,查找规则的时间复杂度会线性增加,性能会受到影响。每条规则需要绑定到一个链中,当规则过多时,规则链的长度增加,导致规则遍历的时间复杂度为 O(N)。 - 可维护性:
iptables
配置较为复杂,尤其是在大量服务和规则存在时,维护起来不方便。
1.2 ipvs
ipvs
(IP Virtual Server)是一种基于 Linux 内核的负载均衡技术,相比于 iptables
,它提供了更高效的性能和更低的延迟。
- 性能优势:
ipvs
采用了哈希表的方式来管理负载均衡规则,查找规则的时间复杂度为 O(1),这使得它在处理大量流量时比iptables
更加高效。 - 调度算法:
ipvs
支持多种负载均衡算法,如轮询(RR)、加权轮询(WRR)、最小连接数等,能够更灵活地处理不同类型的流量。
2. 查看 kube-proxy 默认代理模式
默认情况下,kube-proxy
使用 iptables
作为代理模式。可以通过以下命令查看当前 kube-proxy
的代理模式:
[root@master231 ~]# kubectl get pods -n kube-system -l k8s-app=kube-proxy
NAME READY STATUS RESTARTS AGE
kube-proxy-2vxh9 1/1 Running 1 (6d21h ago) 6d22h
kube-proxy-65z9n 1/1 Running 1 (6d21h ago) 6d22h
kube-proxy-rmn84 1/1 Running 1 (6d21h ago) 6d22h
查看日志时可以发现,kube-proxy
默认会提示使用 iptables
代理模式:
[root@master231 ~]# kubectl -n kube-system logs kube-proxy-2vxh9
I0805 07:02:38.581194 1 server_others.go:138] "Detected node IP" address="10.0.0.231"
I0805 07:02:38.584086 1 server_others.go:572] "Unknown proxy mode, assuming iptables proxy" proxyMode=""
I0805 07:02:38.712188 1 server_others.go:206] "Using iptables Proxier"
3. 查看 CoreDNS 对应的 Service 如何基于 iptables 进行代理
3.1 查看 Service 和 Pods 的对应关系
[root@master231 ~]# kubectl get pods -n kube-system -l k8s-app=kube-dns --show-labels -o wide
查看 kube-dns
服务的详细信息:
[root@master231 ~]# kubectl get svc -A
3.2 查看 iptables 规则
使用 iptables-save
命令查看与 kube-dns
服务对应的 iptables 规则:
[root@master231 ~]# iptables-save | grep 10.200.0.10
查看 Service 到 Pod 的流量转发规则:
[root@master231 ~]# iptables-save | grep KUBE-SVC-ERIFXISQEP7F7OF4
4. 修改 kube-proxy 的工作模式为 ipvs
4.1 安装 ipvsadm
和 conntrack
模块
为了启用 ipvs
,需要安装 ipvsadm
和 conntrack
工具:
[root@master231 ~]# apt -y install conntrack ipvsadm
4.2 配置加载 ipvs
模块
编写加载 ipvs
模块的配置文件:
mkdir -pv /etc/sysconfig/modules
cat > /etc/sysconfig/modules/ipvs.modules <<EOF
#!/bin/bash
modprobe -- ip_vs
modprobe -- ip_vs_rr
modprobe -- ip_vs_wrr
modprobe -- ip_vs_sh
modprobe -- ip_conntrack
EOF
4.3 启用并加载 ipvs
模块
运行以下命令以加载 ipvs
模块:
chmod 755 /etc/sysconfig/modules/ipvs.modules && bash /etc/sysconfig/modules/ipvs.modules
检查模块是否已加载:
lsmod | grep -e ip_vs -e nf_conntrack_ipv4
4.4 修改 kube-proxy 配置
修改 kube-proxy
配置,将 strictARP
设置为 true
并将代理模式修改为 ipvs
:
[root@master231 ~]# kubectl get configmap kube-proxy -n kube-system -o yaml | sed -e "s/strictARP: false/strictARP: true/" | kubectl apply -f - -n kube-system
[root@master231 ~]# kubectl get configmap kube-proxy -n kube-system -o yaml | sed -e 's/mode: ""/mode: "ipvs"/' | kubectl apply -f - -n kube-system
4.5 删除旧的 kube-proxy
Pod 并重新创建
删除当前所有的 kube-proxy
Pod,确保它们会重新以新的配置启动:
[root@master231 ~]# kubectl get pods -n kube-system -l k8s-app=kube-proxy -o jsonpath="{.items[*].metadata.name}" | xargs kubectl -n kube-system delete pods
4.6 验证是否修改成功
通过以下命令检查是否成功修改为 ipvs
模式:
[root@master231 ~]# kubectl -n kube-system describe cm kube-proxy | egrep "mode|strictARP"
4.7 验证 ipvs
工作模式
检查 ipvs
的工作状态,查看负载均衡信息:
[root@master231 ~]# ipvsadm -ln | grep 10.200.0.10 -A 2
注意
- 逐个删除 Pod:在修改
kube-proxy
的配置时,建议逐个删除 Pod,而不是批量删除,以避免影响服务的可用性。 - 注意兼容性:
ipvs
在大流量、高负载的生产环境中表现更好,因此推荐在此类环境中使用ipvs
模式。
5. kube-proxy
的性能优化
在 Kubernetes 集群中,kube-proxy
作为流量的路由器和负载均衡器,它对集群的网络性能有直接影响。切换 kube-proxy
工作模式从 iptables
到 ipvs
,不仅提升了性能,也改善了集群的可扩展性。以下是一些在生产环境中常见的性能优化措施:
5.1 使用 ipvs
提升性能
- 更高的性能:
ipvs
模式相比于iptables
模式,能够提供更高效的流量转发。ipvs
使用哈希表来管理服务的转发规则,因此查询时间为常数时间复杂度 O(1),而iptables
基于链规则,时间复杂度为 O(N),当规则较多时会导致性能下降。 - 负载均衡算法:
ipvs
支持多种负载均衡算法,诸如轮询(Round Robin)、加权轮询(Weighted Round Robin)、最小连接数(Least Connection)等,这使得它可以根据负载和资源使用情况进行灵活的流量调度。
5.2 考虑资源消耗
- 内存使用:
ipvs
模式通常会消耗更多的内存来存储流量转发规则,特别是在大规模集群中。需要定期监控节点的资源使用情况,确保内存使用不会过载。 - CPU 使用:
ipvs
模式下,流量转发操作的 CPU 占用相对较低,但同样需要在高负载情况下监控系统的 CPU 使用情况,防止因过多的流量转发导致 CPU 过载。
5.3 健康检查与故障恢复
kube-proxy
使用健康检查来确定 Pod 是否可用。如果某个 Pod 健康检查失败,它将被从负载均衡池中剔除。这对于确保服务的高可用性至关重要。
- 健康检查:确保每个 Pod 都设置了健康检查(
livenessProbe
和readinessProbe
),以便在 Pod 出现故障时能够及时从负载均衡池中移除,避免流量被路由到不可用的 Pod 上。 - 故障恢复:通过配置合理的容错机制(如设置多个副本),即使部分节点或 Pod 失败,其他 Pod 也能接管流量,保持服务的高可用性。
6. kube-proxy
与服务暴露
kube-proxy
的另一个重要作用是为 Kubernetes 集群中的 Service 提供访问入口,它通过代理将请求转发到正确的 Pod。
6.1 ClusterIP 和 NodePort
- ClusterIP:在
iptables
或ipvs
模式下,kube-proxy
会为每个 Service 分配一个虚拟 IP 地址,只有集群内部的 Pod 能够访问这个虚拟 IP。通过负载均衡,流量被正确地转发到相关的 Pod。 - NodePort:当 Service 类型为
NodePort
时,kube-proxy
还会在每个节点的指定端口上暴露该服务,使得集群外部的用户能够通过节点的 IP 和端口访问 Service。
6.2 外部流量与负载均衡
在生产环境中,常常需要将外部流量通过负载均衡器引入 Kubernetes 集群。例如,使用 Ingress Controller 来处理 HTTP/HTTPS 流量,并通过 kube-proxy
来转发到合适的 Service。
- Ingress Controller:作为 Kubernetes 集群外部流量的入口,Ingress Controller 可以通过设置路由规则,将外部 HTTP/HTTPS 请求转发到不同的 Service 上。
kube-proxy
会根据这些规则进行负载均衡。
7. 高可用性与多区域部署
在大规模的生产环境中,kube-proxy
的高可用性和多区域部署非常关键。为了确保跨多个区域的高可用性,可以通过以下方式进行配置和优化:
7.1 多区域支持
- Global Load Balancer:在跨区域的 Kubernetes 部署中,可以使用全局负载均衡器来确保不同区域的流量能够均匀分配到各个区域的 Kubernetes 集群中。这通常涉及到使用云服务提供商的负载均衡服务(如 AWS Global Accelerator 或 Google Cloud Load Balancer)。
- 跨区域的
kube-proxy
配置:为了支持跨区域的流量转发,kube-proxy
可以配置为支持多个集群,并通过跨集群服务发现来实现多区域部署。
7.2 故障切换
- Pod 故障切换:在
ipvs
模式下,kube-proxy
会确保当某个 Pod 故障时,流量会被自动重新路由到其他健康的 Pod。这种自动故障切换机制对于确保服务持续可用至关重要。
小结
通过将 kube-proxy
的工作模式从 iptables
切换到 ipvs
,Kubernetes 集群可以显著提高网络性能,尤其是在流量较大或集群规模较大时。除了性能提升之外,ipvs
还提供了更强大的负载均衡能力和更低的延迟,是生产环境中推荐使用的代理模式。
- 性能优化:
ipvs
相较于iptables
提供了更高的效率和更低的延迟,适合于处理大规模流量。 - 健康检查与故障恢复:确保
kube-proxy
配置合理的健康检查机制,以便及时剔除不健康的 Pod,保障服务的高可用性。 - 高可用性与多区域支持:对于大规模集群和跨区域部署,
kube-proxy
需要具备高可用性和跨区域流量分配能力。