使用IPVS实现Kubernetes入口流量负载均衡

本文涉及的产品
传统型负载均衡 CLB,每月750个小时 15LCU
应用型负载均衡 ALB,每月750个小时 15LCU
网络型负载均衡 NLB,每月750个小时 15LCU
简介: 新搭建的Kubernetes集群如何承接外部访问的流量,是刚上手Kubernetes时常常会遇到的问题。 在公有云上,官方给出了比较直接的答案,使用LoadBalancer类型的Service,利用公有云提供的负载均衡服务来承接流量, 同时在多台服务器之间进行负载均衡。

新搭建的Kubernetes集群如何承接外部访问的流量,是刚上手Kubernetes时常常会遇到的问题。 在公有云上,官方给出了比较直接的答案,使用LoadBalancer类型的Service,利用公有云提供的负载均衡服务来承接流量, 同时在多台服务器之间进行负载均衡。而在私有环境中,如何正确的将外部流量引入到集群内部,却暂时没有标准的做法。 本文将介绍一种基于IPVS来承接流量并实 现负载均衡的方法,供大家参考。

IPVS

IPVSLVS项目的一部分,是一款运行在Linux kernel当中的4层负载均衡器,性能异常优秀。 根据这篇文章的介绍,使用调优后的内核,可以轻松处理每秒10万次以上的转发请求。目前在中大型互联网项目中, IPVS被广泛的使用,用于承接网站入口处的流量。

Kubernetes Service

Service是Kubernetes的基础概念之一,它将一组Pod抽象成为一项服务,统一的对外提供服务,在各个Pod之间实现负载均衡。 Service有多种类型,最基本的ClusterIP类型解决了集群内部访问服务的需求,NodePort类型通过Node节点的端口暴露服务, 再配合上LoadBalancer类型所定义的负载均衡器,实现了流量经过前端负载均衡器分发到各个Node节点暴露出的端口, 再通过iptables进行一次负载均衡,最终分发到实际的Pod上这个过程。

在Service的Spec中,externalIPs字段平常鲜有人提到,当把IP地址填入这个字段后,kube-proxy会增加对应的iptables规则, 当有以对应IP为目标的流量发送到Node节点时,iptables将进行NAT,将流量转发到对应的服务上。一般情况下, 很少会遇到服务器接受非自身绑定IP流量的情况,所以externalIPs不常被使用,但配合网络层的其他工具,它可以实现给Service绑定外部IP的效果。

今天我们将使用externalIPs配合IPVS的DR(Direct Routing)模式实现将外部流量引入到集群内部,同时实现负载均衡。

环境搭建

为了演示,我们搭建了4台服务器组成的集群。一台服务器运行IPVS,扮演负载均衡器的作用,一台服务器运行Kubernetes Master组件, 其他两台服务器作为Node加入到Kubernetes集群当中。搭建过程这里不详细介绍,大家可以参考相关的文档。

所有服务器在172.17.8.0/24这个网段中。服务的VIP我们设定为172.17.8.201。整体架构入下图所示:

ipvs-kubernetes

接下来让我们来配置IPVS和Kubernetes。

使用externalIPs暴露Kubernetes Service

首先在集群内部运行2个nginx Pod用作演示。

$ kubectl run nginx --image=nginx --replicas=2

再将它暴露为Service,同时设定externalIPs字段

$ kubectl expose deployment nginx --port 80 --external-ip 172.17.8.201

查看iptables配置,确认对应的iptables规则已经被加入。

$ sudo iptables -t nat -L KUBE-SERVICES -n
Chain KUBE-SERVICES (2 references)
target prot opt source destination
KUBE-SVC-4N57TFCL4MD7ZTDA tcp -- 0.0.0.0/0 10.3.0.156 /* default/nginx: cluster IP */ tcp dpt:80
KUBE-MARK-MASQ tcp -- 0.0.0.0/0 172.17.8.201 /* default/nginx: external IP */ tcp dpt:80
KUBE-SVC-4N57TFCL4MD7ZTDA tcp -- 0.0.0.0/0 172.17.8.201 /* default/nginx: external IP */ tcp dpt:80 PHYSDEV match ! --physdev-is-in ADDRTYPE match src-type !LOCAL
KUBE-SVC-4N57TFCL4MD7ZTDA tcp -- 0.0.0.0/0 172.17.8.201 /* default/nginx: external IP */ tcp dpt:80 ADDRTYPE match dst-type LOCAL
KUBE-SVC-NPX46M4PTMTKRN6Y tcp -- 0.0.0.0/0 10.3.0.1 /* default/kubernetes:https cluster IP */ tcp dpt:443
KUBE-NODEPORTS all -- 0.0.0.0/0 0.0.0.0/0 /* kubernetes service nodeports; NOTE: this must be the last rule in this chain */ ADDRTYPE match dst-type LOCAL

配置IPVS实现流量转发

首先在IPVS服务器上,打开ipv4_forward

$ sudo sysctl -w net.ipv4.ip_forward=1

接下来加载IPVS内核模块。

$ sudo modprobe ip_vs

将VIP绑定在网卡上。

$ sudo ifconfig eth0:0 172.17.8.201 netmask 255.255.255.0 broadcast 172.17.8.255

再使用ipvsadm来配置IPVS,这里我们直接使用Docker镜像,避免和特定发行版绑定。

$ docker run --privileged -it --rm --net host luizbafilho/ipvsadm
/ # ipvsadm
IP Virtual Server version 1.2.1 (size=4096) Prot LocalAddress:Port Scheduler Flags -> RemoteAddress:Port Forward Weight ActiveConn InActConn / # ipvsadm -A -t 172.17.8.201:80 / # ipvsadm -a -t 172.17.8.201:80 -r 172.17.8.11:80 -g / # ipvsadm -a -t 172.17.8.201:80 -r 172.17.8.12:80 -g / # ipvsadm
IP Virtual Server version 1.2.1 (size=4096) Prot LocalAddress:Port Scheduler Flags -> RemoteAddress:Port Forward Weight ActiveConn InActConn
TCP 172.17.8.201:http wlc
 -> 172.17.8.11:http Route 1 0 0 -> 172.17.8.12:http Route 1 0 0

可以看到,我们成功建立了从VIP到后端服务器的转发。

验证转发效果

首先使用curl来测试是否能够正常访问nginx服务。

$ curl http://172.17.8.201 <!DOCTYPE html> <html> <head> <title>Welcome to nginx!</title> <style>
 body {
 width: 35em;
 margin: 0 auto;
 font-family: Tahoma, Verdana, Arial, sans-serif; } </style>
</head> <body> <h1>Welcome to nginx!</h1> <p>If you see this page, the nginx web server is successfully installed and
working. Further configuration is required.</p> <p>For online documentation and support please refer to
<a href="http://nginx.org/">nginx.org</a>.<br/> Commercial support is available at
<a href="http://nginx.com/">nginx.com</a>.</p> <p><em>Thank you for using nginx.</em></p> </body>
</html>

接下来在172.17.8.11上抓包来确认IPVS的工作情况。

$ sudo tcpdump -i any port 80
tcpdump: verbose output suppressed, use -v or -vv for full protocol decode
listening on any, link-type LINUX_SLL (Linux cooked), capture size 262144 bytes
04:09:07.503858 IP 172.17.8.1.51921 > 172.17.8.201.http: Flags [S], seq 2747628840, win 65535, options [mss 1460,nop,wscale 5,nop,nop,TS val 1332071005 ecr 0,sackOK,eol], length 0 04:09:07.504241 IP 10.2.0.1.51921 > 10.2.0.3.http: Flags [S], seq 2747628840, win 65535, options [mss 1460,nop,wscale 5,nop,nop,TS val 1332071005 ecr 0,sackOK,eol], length 0 04:09:07.504498 IP 10.2.0.1.51921 > 10.2.0.3.http: Flags [S], seq 2747628840, win 65535, options [mss 1460,nop,wscale 5,nop,nop,TS val 1332071005 ecr 0,sackOK,eol], length 0 04:09:07.504827 IP 10.2.0.3.http > 10.2.0.1.51921: Flags [S.], seq 3762638044, ack 2747628841, win 28960, options [mss 1460,sackOK,TS val 153786592 ecr 1332071005,nop,wscale 7], length 0 04:09:07.504827 IP 10.2.0.3.http > 172.17.8.1.51921: Flags [S.], seq 3762638044, ack 2747628841, win 28960, options [mss 1460,sackOK,TS val 153786592 ecr 1332071005,nop,wscale 7], length 0 04:09:07.504888 IP 172.17.8.201.http > 172.17.8.1.51921: Flags [S.], seq 3762638044, ack 2747628841, win 28960, options [mss 1460,sackOK,TS val 153786592 ecr 1332071005,nop,wscale 7], length 0 04:09:07.505599 IP 172.17.8.1.51921 > 172.17.8.201.http: Flags [.], ack 1, win 4117, options [nop,nop,TS val 1332071007 ecr 153786592], length 0

可以看到,由客户端172.17.8.1发送给172.17.8.201的封包,经过IPVS的中转发送给了172.17.8.11这台服务器, 并经过NAT后发送给了10.2.0.3这个Pod。返回的封包不经过IPVS服务器直接从172.17.8.11发送给了172.17.8.1。 说明IPVS的DR模式工作正常。重复多次测试可以看到流量分别从172.17.8.11172.17.8.12进入,再分发给不同的Pod, 说明负载均衡工作正常。

与传统的IPVS DR模式配置不同的是,我们并未在承接流量的服务器上执行绑定VIP,再关闭ARP的操作。 那是因为对VIP的处理直接发生在iptables上,我们无需在服务器上运行程序来承接流量,iptables会将流量转发到对应的Pod上。

使用这种方法来承接流量,仅需要配置externalIPs为VIP即可,无需对服务器做任何特殊的设置,使用起来相当方便。

总结

在本文中演示了使用IPVS配合externalIPs实现将外部流量导入到Kubernetes集群中,并实现负载均衡的方法。 希望可以帮助大家理解IPVS和externalIPs的工作原理,以便在恰当的场景下合理使用这两项技术解决问题。 实际部署时,还需要考虑后台服务器可用性检查,IPVS节点主从备份,水平扩展等问题。在这里就不详细介绍了。

在Kubernetes中还有许多与externalIPs类似的非常用功能,有些甚至是使用Annotation来进行配置,将来有机会再进一步分享。

本文转自中文社区-使用IPVS实现Kubernetes入口流量负载均衡

相关实践学习
通过Ingress进行灰度发布
本场景您将运行一个简单的应用,部署一个新的应用用于新的发布,并通过Ingress能力实现灰度发布。
容器应用与集群管理
欢迎来到《容器应用与集群管理》课程,本课程是“云原生容器Clouder认证“系列中的第二阶段。课程将向您介绍与容器集群相关的概念和技术,这些概念和技术可以帮助您了解阿里云容器服务ACK/ACK Serverless的使用。同时,本课程也会向您介绍可以采取的工具、方法和可操作步骤,以帮助您了解如何基于容器服务ACK Serverless构建和管理企业级应用。 学习完本课程后,您将能够: 掌握容器集群、容器编排的基本概念 掌握Kubernetes的基础概念及核心思想 掌握阿里云容器服务ACK/ACK Serverless概念及使用方法 基于容器服务ACK Serverless搭建和管理企业级网站应用
相关文章
|
1月前
|
弹性计算 负载均衡 网络安全
slb使用中流量转发不均
【10月更文挑战第23天】
41 8
|
2月前
|
Kubernetes 负载均衡 网络协议
在K8S中,负载均衡器有何作用?
在K8S中,负载均衡器有何作用?
|
2月前
|
负载均衡 Kubernetes 区块链
随机密码生成器+阿里k8s负载均衡型服务加证书方法+移动终端设计+ico生成器等
随机密码生成器+阿里k8s负载均衡型服务加证书方法+移动终端设计+ico生成器等
56 1
|
2月前
|
Kubernetes 应用服务中间件 nginx
k8s学习--Traffic Shifting 流量接入
k8s学习--Traffic Shifting 流量接入
|
2月前
|
Kubernetes 负载均衡 网络协议
k8s学习--负载均衡器matelLB的详细解释与安装
k8s学习--负载均衡器matelLB的详细解释与安装
141 0
|
3月前
|
弹性计算 负载均衡 监控
slb分发流量到ecs一般是如何判断?
【9月更文挑战第1天】
62 1
|
4月前
|
负载均衡 监控 算法
揭秘负载均衡的五大算法秘籍:让你的服务器轻松应对亿万流量,不再崩溃!
【8月更文挑战第31天】在互联网快速发展的今天,高可用性和可扩展性成为企业关注的重点。负载均衡作为关键技术,通过高效分配网络流量提升系统处理能力。本文介绍了轮询、加权轮询、最少连接及IP哈希等常见负载均衡算法及其应用场景,并提供Nginx配置示例。此外,还探讨了如何根据业务需求选择合适算法、配置服务器权重、实现高可用方案、监控性能及定期维护等最佳实践,助力系统优化与用户体验提升。
79 2
|
4月前
|
Kubernetes 负载均衡 应用服务中间件
在k8S中,什么是负载均衡器?
在k8S中,什么是负载均衡器?
|
4月前
|
域名解析 负载均衡 网络协议
双重神器合璧,流量洪流中的稳如磐石:揭秘Bind+Nginx负载均衡的超级力量!
【8月更文挑战第9天】在现代网站架构中,负载均衡至关重要,它通过分散客户端请求至多台服务器,确保了系统的高可用性和稳定性。本文介绍如何结合Bind与Nginx实现高效负载均衡。Bind作为DNS服务器,可为单一域名解析出多个IP地址;Nginx作为高性能HTTP服务器,则在这些IP对应的服务器间智能分配流量。通过配置Bind的A记录与Nginx的`upstream`和`proxy_pass`指令,我们能够构建一个既稳定又易扩展的负载均衡系统,显著提升用户体验与系统可靠性。
81 11
|
4月前
|
Kubernetes 网络协议 数据可视化
kubernetes Tcp流量可视化
kubernetes Tcp流量可视化
54 4