周蕾 发布于 07月20, 2018

浅析kube-proxy中IPVS模式

浅析kube-proxy的IPVS模式

在k8s中,提供相同服务的一组pod可以抽象成一个service,通过service提供的统一入口对外提供服务,每个service都有一个虚拟IP地址(VIP)和端口号供客户端访问。Kube-proxy存在于各个node节点上,主要用于Service功能的实现,具体来说,就是实现集群内的客户端pod访问service,或者是集群外的主机通过NodePort等方式访问service。在当前版本的k8s中,kube-proxy默认使用的是iptables模式,通过各个node节点上的iptables规则来实现service的负载均衡,但是随着service数量的增大,iptables模式由于线性查找匹配、全量更新等特点,其性能会显著下降。从k8s的1.8版本开始,kube-proxy引入了IPVS模式,IPVS模式与iptables同样基于Netfilter,但是采用的hash表,因此当service数量达到一定规模时,hash查表的速度优势就会显现出来,从而提高service的服务性能。

1. IPVS

IPVS是LVS的核心组件,是一种四层负载均衡器。IPVS具有以下特点:

  • 与Iptables同样基于Netfilter,但使用的是hash表;
  • 支持TCP, UDP,SCTP协议,支持IPV4,IPV6;
  • 支持多种负载均衡策略:rr, wrr, lc, wlc, sh, dh, lblc…
  • 支持会话保持;

LVS主要由两部分组成:

  • ipvs(ip virtual server):即ip虚拟服务,是工作在内核空间上的一段代码,主要是实现调度的代码,它是实现负载均衡的核心。
  • ipvsadm: 工作在用户空间,负责为ipvs内核框架编写规则,用于定义谁是集群服务,谁是后端真实服务器。我们可以通过ipvsadm指令创建集群服务,例如:
    # ipvsadm -A -t 192.168.2.xx:80 -s rr //创建一个DR,并指定调度算法采用rr。
    # ipvsadm -a -t 192.168.2.xx:80 -r 192.168.10.xx 
    # ipvsadm -a -t 192.168.2.xx:80 -r 192.168.11.xx //添加两个RS
    

IPVS基于Netfilter,在介绍IPVS的工作原理之前,首先介绍一下Netfilter的挂载点。 Netfilter 中制定了数据包的五个挂载点(Hook Point),我们可以将挂载点理解为回调函数点,数据包到达这些位置的时候会主动调用我们的函数,使我们有机会能在数据包路由的时候改变它们的方向、内容,如源和目的IP等,这5个挂载点分别是PRE_ROUTING、INPUT、OUTPUT、FORWARD、POST_ROUTING,如下图所示,IPVS工作在其中的INPUT链上。

alt

LVS工作原理如下图所示:

alt

  1. 当客户端的请求到达负载均衡器的内核空间时,首先会到达PREROUTING链。
  2. 当内核发现请求数据包的目的地址是本机时,将数据包送往INPUT链。
  3. 当数据包到达INPUT链时,首先会被IPVS检查,如果数据包里面的目的地址及端口没有在IPVS规则里面,那么这条数据包将被放行至用户空间。
  4. 如果数据包里面的目的地址及端口在IPVS规则里面,那么这条数据报文的目的地址被修改为通过负载均衡调度算法选好的后端服务器(DNAT),并送往POSTROUTING链。
  5. 最后经由POSTROUTING链发往后端服务器。

2.kube-proxy使用IPVS做负载均衡

kube-proxy可以调用内核中的IPVS模块进行负载均衡,此时,客户端pod所在的node节点充当Director的角色。在kube-proxy的IPVS模式下,客户端pod通过service的Cluster IP 访问服务端pod的过程如下图所示。图中着重标注了数据包的源和目的IP在整个过程中的变化情况,从中可以看出kube-proxy工作在IPVS的NAT模式,并且负载均衡过程在客户端pod所在的Node节点上就已经完成了。

alt

  1. 客户端pod发出请求报文,请求报文源地址是CIP(客户端pod的IP),目标地址为service的VIP。
  2. 请求报文到达客户端pod所在的Node节点的INPUT链,此时,内核中IPVS模块 发挥作用,通过调度算法选择一个后端pod提供服务,将该请求报文的目的IP地址修改为选中的后端pod的IP,然后直接送到node节点的POSTROUTING链,发往后端pod。
  3. 请求 报文送到后端pod后,由于请求报文的目标地址是自己,所以会响应该请求,并将响应报文返回,响应报文的源IP为后端pod的IP,目的IP为客户端pod的IP。
  4. 响应报文到达客户端所在的Node节点, 然后IPVS将此报文的源地址修改为service的VIP并发送给客户端pod,这样对于客户端来说,为其提供服务便是service的VIP。

需要注意的是,由于IPVS工作在INPUT链,为了使客户端pod的请求数据包能够到达INPUT链,必须要让内核识别 service的VIP 是本机的 IP,因此必须绑定service的VIP,如下图所示,kube-proxy默认将service的VIP绑定在kube-ipvs0上。

alt

3. 总结

本文主要简单介绍了kube-proxy的IPVS模式,首先分析了IPVS的工作原理,然后介绍了其应用在kube-proxy中做负载均衡的大体流程。当service的数量达到一定规模时,大量的iptables规则会严重降低service的性能,IPVS基于hash表的查找方式、多种负载均衡策略等特点为k8s提供了一种大规模service场景下的解决方案。

阅读全文 »

刘毅 发布于 07月19, 2018

LVS流量异常检测

背景

公司中存在大量的vip流量数据,vip流量异常将会导致一些严重的问题,运维人员也可以通过对vip流量数据异常的检测判断当前LVS是否正常,以及时解决问题。

流量数据实际是一组时间序列,因此流量异常检测就是时间序列异常点的检测问题。本文通过计算环比,同比,振幅等值以及运用iForest算法实现了时间序列异常点的检测问题。

阅读全文 »

王希刚 发布于 07月09, 2018

浅谈Cgroups

说起容器监控,首先会想到通过Cadvisor, Docker stats等多种方式获取容器的监控数据,并同时会想到容器通过Cgroups实现对容器中的资源进行限制。但是这些数据来自哪里,并且如何计算的?答案是Cgroups。最近在写docker容器监控组件,在深入Cadvisor和Docker stats源码发现数据都来源于Cgroups。了解之余,并对Cgroups做下笔记。

阅读全文 »

刘毅 发布于 07月02, 2018

退还机器推荐方法整理与总结

退还机器推荐方法整理与总结

背景

对于某些业务所使用的机器可能会出现老化,迁移等问题需要退还,随着业务数量的增多,机器数量的增多,退换机器的数量也随之增大。然而并不可能将业务中的所有机器全部退还,有效的机器退还不仅能够节约成本,也能提高业务的稳定性与效率。因此需要设计一个算法用于判断机器是否需要退还。

这个问题很容易把它想想成一个机器的分类问题,即设计一个分类器用于判断机器是否需要退还。实际上,该问题不仅仅可以用分类的方法进行解决,也可以设计一个推荐系统,为用户(即业务)推荐最应该退还的机器。

阅读全文 »

籍鑫璞 发布于 06月12, 2018

时间序列聚类方法的研究

背景

为了保证系统、服务的可靠性和稳定性,监控系统日渐成为每个公司、企业的一个必不可少的系统。随着服务、机器等数量越来越多,如何分析海量时间序列KPI成为我们在智能运维领域首先需要解决的问题。

在众多的时间序列中,有一些序列存在相关性,如果我们能将时序数据进行快速准确地聚类,只对不同类别的数据进行分析,这样就能大大降低后续数据分析与挖掘工作的开销。

阅读全文 »

高广鹏 发布于 06月11, 2018

Golang short write

背景

自定义数据结构,替换golang标准库"os/exec"中cmd原始的标准输出、标准错误输出,达到获取并限制其大小,便于日志上报。在输出达到上限后遇到“short write”报错,本文记录排查思路及过程。

阅读全文 »

高广鹏 发布于 06月08, 2018

Channels In Go

Channels In Go

原文来自go101,本文是翻译后留存,方便自己学习。

go有两个重要的内置功能,同时也是它的特性。分别是channel、goroutine。这两个特性使go编写并发程序变的简单、有趣。本文将主要介绍channel

阅读全文 »

王希刚 发布于 06月04, 2018

Kube-controller-manager解析之启动流程

最近在工作之余准备看看Kube-controller-manager比较核心的几个控制器,也是现在容器平台主要使用的几个,如:Deployment, ReplicaSet, Garbage Collection, ReousrceQuota, Node Controller等。在分析这些控制器之前,先介绍下kube-controller-manager的功能及它的启动流程。

注意: kubernetes 1.9.0, commit Id: 925c127ec6b946659ad0fd596fa959be43f0cc05

阅读全文 »