美文网首页k8sk8s
k8s集群中ipvs负载详解

k8s集群中ipvs负载详解

作者: Feel_狗焕 | 来源:发表于2019-06-15 17:19 被阅读0次

    目录:

    1. ipvs vs iptables
    2. ipvs kube-proxy原理分析
      2.1.cluster-ip到pod访问
      2.2.node-ip到pod访问
    3. 总结

    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 地址上显示为虚拟服务。

    1、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模式。

    2、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-clsterip.png

    ipvs 会使用 iptables 进行包过滤、SNAT、masquared(伪装)。具体来说,ipvs 将使用
    ipset来存储需要DROP或masquared的流量的源或目标地址,以确保 iptables 规则的
    数量是恒定的,这样我们就不需要关心我们有多少服务了。

    2.1、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

    ipvs-cls-out.png
    匹配到倒数第二条就是将流量引入到KUBE-SERVICES规则中处理。如下图:

    2)、入口流量引流到全局链KUBE-SERVICES中:
    ipset list KUBE-CLUSTER-IP
    iptables -S -tnat | grep KUBE-SERVICES

    ipvs-cls-out-2.png

    第一步中上面的数据包流入到KUBE-SERVICES该规则中目的就是让源地址不是
    10.244.0.0/16,目的地址match 到 KUBE-CLUSTER-IP 的数据包打上标签。

    3)、入口流量标签化处理:
    将上面KUBE-SERVICES链中的流量进行打标签处理:
    $iptables -S -tnat | grep KUBE-MARK-MASQ

    ipvs-cls-tag.png

    4)、入口流量SNAT处理:
    那么数据包在出去的时候一定是要经过POSTROUTING链进行SNAT即将所有来源外部
    流量转换成该cluster ip的源地址。
    $iptables -S -tnat | grep POSTROUTING

    ipvs-cls-pro-1.png

    然后通过内部的lvs进行流量转发到后端pod上。如下图:
    $ipvsadm -Ln


    ipvs-cls-out-3.png

    2.2、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


    ipvs-node-1.png

    1)、入口流量匹配:
    集群外部通过node ip 访问到后端pod服务,流量肯定是先在PREROUTING链中处理:
    $iptables -S -tnat | grep PREROUTING

    ipvs-node-2.png

    匹配到倒数第二条就是,将流量引入到KUBE-SERVICES规则中处理。

    2)、入口流量引流到全局链KUBE-SERVICES中:
    $ipset list KUBE-CLUSTER-IP

    $iptables -S -tnat | grep KUBE-SERVICES


    ipvs-node-3.jpg

    第一步中上面的数据包流入到KUBE-SERVICES该规则中目的就是让源地址不是10.244.0.0/16,目的地址match 到 KUBE-CLUSTER-IP 的数据包打上标签

    3)、入口流量标签化处理:
    $iptables -S -tnat | grep KUBE-MARK-MASQ

    ipvs-node-4.png

    4)、入口流量SNAT处理:
    那么数据包在出去的时候一定是要经过POSTROUTING链进行SNAT即将所有来源外部流量转换成该cluster ip的源地址。
    $iptables -S -tnat | grep POSTROUTING

    ipvs-node-5.png

    iptables中POSTROUTING链最先将流量引流到KUBE-POSTROUTING中做进一步的SNAT处理
    $iptables -S -tnat | grep KUBE-POSTROUTING

    ipvs-node-6.png

    端口的转换
    $iptables -S -tnat | grep KUBE-NODE-PORT

    ipvs-node-7.png

    上面的流程进行SNAT后即将所有来源外部流量转换成该cluster ip的源地址的对应得端
    口。然后通过内部的lvs进行流量转发到后端pod上。


    3、总结如下流程:

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


    lc.png

    相关文章

      网友评论

        本文标题:k8s集群中ipvs负载详解

        本文链接:https://www.haomeiwen.com/subject/zombfctx.html