前言

IPVS简介:
尽管 Kubernetes 在版本v1.6中已经支持5000个节点,但使用 iptables 的 kube-proxy 实
际上是将集群扩展到5000个节点的瓶颈。 在5000节点集群中使用 NodePort 服务,如
果有2000个服务并且每个服务有10个 pod,这将在每个工作节点上至少产生20000个
iptable 记录,这可能使内核非常繁忙。
ipvs (IP Virtual Server) 实现了传输层负载均衡,也就是我们常说的4层LAN交换,作为
Linux 内核的一部分。ipvs运行在主机上,在真实服务器集群前充当负载均衡器。ipvs
可以将基于TCP和UDP的服务请求转发到真实服务器上,并使真实服务器的服务在单个
IP 地址上显示为虚拟服务。

一、ipvs vs iptables:

我们知道kube-proxy支持 iptables 和 ipvs 两种模式, 在kubernetes v1.8 中引入了 ipvs
模式,在 v1.9 中处于 beta 阶段,在 v1.11 中已经正式可用了。iptables 模式在 v1.1 中
就添加支持了,从 v1.2版本开始 iptables 就是 kube-proxy 默认的操作模式,ipvs 和
iptables 都是基于netfilter的。ipvs 会使用 iptables 进行包过滤、SNAT、masquared。
具体来说,ipvs 将使用ipset来存储需要DROP或masquared的流量的源或目标地址,
以确保 iptables 规则的数量是恒定的,这样我们就不需要关心我们有多少服务了。
启动ipvs的要求:
k8s版本 >= v1.11
使用ipvs需要安装相应的工具来处理”yum install ipset ipvsadm -y“
确保 ipvs已经加载内核模块, ip_vs、ip_vs_rr、ip_vs_wrr、ip_vs_sh、
nf_conntrack_ipv4。如果这些内核模块不加载,当kube-proxy启动后,会退回到iptables模式。

二、ipvs kube-proxy原理分析:

先前基于iptables规则表的DNAT->SNAT方式来处理外部客户端到k8s集群pod内的流量
和集群内部流量(cluster-ip到pod ip),无需在宿主机上管理cluster-ip都由iptables来进行
管理。
使用IPVS后是需要对vs(虚拟服务也就是vip)进行管理,由于IPVS的DNAT钩子挂在
INPUT链上,因此必须要让内核识别 VIP(cluster-ip) 是本机的 IP。k8s 通过设置将
service cluster ip 绑定到虚拟网卡kube-ipvs0,其中下面的10.96.x.x都是VIP,也就
是cluster-ip。
在这里插入图片描述
ipvs 会使用 iptables 进行包过滤、SNAT、masquared(伪装)。具体来说,ipvs 将使用
ipset来存储需要DROP或masquared的流量的源或目标地址,以确保 iptables 规则的
数量是恒定的,这样我们就不需要关心我们有多少服务了。
cluster-ip到pod访问
这里访问cluster ip为10.96.0.10,k8s集群内部的dns服务
1)、入口流量匹配:
数据包是通过本地协议发出的,在宿主机本地通过访问cluster-ip到后端真是的pod那
么就要伪装所有访问 Service Cluster IP 的外部流量,k8s只能在OUTPUT这个链上
来做相应的规则:
$iptables -S -tnat | grep OUTPUT
在这里插入图片描述
匹配到倒数第二条就是将流量引入到KUBE-SERVICES规则中处理。如下图:2)、入口流量引流到全局链KUBE-SERVICES中:
ipset list KUBE-CLUSTER-IP
iptables -S -tnat | grep KUBE-SERVICES
在这里插入图片描述
第一步中上面的数据包流入到KUBE-SERVICES该规则中目的就是让源地址不是
10.244.0.0/16,目的地址match 到 KUBE-CLUSTER-IP 的数据包打上标签。
入口流量标签化处理:
将上面KUBE-SERVICES链中的流量进行打标签处理:
$iptables -S -tnat | grep KUBE-MARK-MASQ
在这里插入图片描述
入口流量SNAT处理:
那么数据包在出去的时候一定是要经过POSTROUTING链进行SNAT即将所有来源外部
流量转换成该cluster ip的源地址。
$iptables -S -tnat | grep POSTROUTING
在这里插入图片描述
然后通过内部的lvs进行流量转发到后端pod上。如下图:
$ipvsadm -Ln
在这里插入图片描述
node-ip到pod访问
这里创建一个service为NodePort的nginx应用对应为nodeip:port(192.168.100.100:30080),
clusterip:port(10.101.19.237:80)
$ip ad| grep ipvs
$kubectl get svc
在这里插入图片描述
入口流量匹配:
集群外部通过node ip 访问到后端pod服务,流量肯定是先在PREROUTING链中处理:
$iptables -S -tnat | grep PREROUTING
在这里插入图片描述
匹配到倒数第二条就是,将流量引入到KUBE-SERVICES规则中处理。
2)、入口流量引流到全局链KUBE-SERVICES中:
$ipset list KUBE-CLUSTER-IP
$iptables -S -tnat | grep KUBE-SERVICES
在这里插入图片描述
第一步中上面的数据包流入到KUBE-SERVICES该规则中目的就是让源地址不是10.244.0.0/16,目的地址match 到 KUBE-CLUSTER-IP 的数据包打上标签
3)、入口流量标签化处理:
$iptables -S -tnat | grep KUBE-MARK-MASQ
在这里插入图片描述
入口流量SNAT处理:
那么数据包在出去的时候一定是要经过POSTROUTING链进行SNAT即将所有来源外部流量转换成该cluster ip的源地址。
$iptables -S -tnat | grep POSTROUTING
在这里插入图片描述
iptables中POSTROUTING链最先将流量引流到KUBE-POSTROUTING中做进一步的SNAT处理
$iptables -S -tnat | grep KUBE-POSTROUTING
在这里插入图片描述
端口的转换
$iptables -S -tnat | grep KUBE-NODE-PORT
在这里插入图片描述
上面的流程进行SNAT后即将所有来源外部流量转换成该cluster ip的源地址的对应得端
口。然后通过内部的lvs进行流量转发到后端pod上。
ipvsadm
–stat选项是统计自该条转发规则生效以来的包
ipvsadm -ln --stats
在这里插入图片描述

  1. Conns (connections scheduled) 已经转发过的连接数
  2. InPkts (incoming packets) 入包个数
  3. OutPkts (outgoing packets) 出包个数
  4. InBytes (incoming bytes) 入流量(字节)
  5. OutBytes (outgoing bytes) 出流量(字节)
    –rate选项是显示速率信息
    在这里插入图片描述
    –rate选项是显示速率信息
  6. CPS (current connection rate) 每秒连接数
  7. InPPS (current in packet rate) 每秒的入包个数
  8. OutPPS (current out packet rate) 每秒的出包个数
  9. InBPS (current in byte rate) 每秒入流量(字节)
  10. OutBPS (current out byte rate) 每秒入流量(字节)
    ipvsadm -Z 清空计数器
    模拟DDOS之前
    在这里插入图片描述
    开启DDOS后
    在这里插入图片描述

总结

这种的LB方式和之前分析的swarm集群中LB类似都是用lvs来直接进行负载,这比起原先使用iptables来进行负载在性能上要好的多,同时也比较清晰友好。总之一句话流量都是要先经过iptables清理一遍然后交给4层的lvs进行负载。
在这里插入图片描述

Logo

K8S/Kubernetes社区为您提供最前沿的新闻资讯和知识内容

更多推荐