深入理解 Kubernetes之:Service

在Kubernetes 集群中, Service是一个抽象的概念。它通过一个虚拟的IP的形式(VIPs),映射出来指定的端口,通过代理客户端发来的请求转发到后端一组Pods中的一台(也就是endpoint)。这样的好处呢?显而易见,在Kubernetes中用到的管理微服务的常用的到的类型就是deployment, 里面有个参数replicas 来管理整个deployment里面Pod的生命周期,因为有容器的销毁和生成导致Pod IP也就是动态变化的。而Service做为客户端和Pod(backends)中间的代理层,并抽象一个clusterIP的虚拟IP ,集群内部都可以通过这个IP访访问到具体Pod的服务。Service在 Kubernetes 版本迭代中,有过几次变更。在 Kubernetes v1.0 中开始使用 user space proxy mode (用户空间代理态代理模式),Kubernetes v1.1 增加了iptables 代理模式,Kubernetes v1.2 默认把IPtables 当成kube-proxy 的代理模式。在 Kubernetes v1.8 增加了性能更强劲的ipvs proxy mode。

 
1. kube-proxy作用
 
在Kubernetes中,Service的Cluster IP实现数据报文请求的转发,都离不开在node上部署的比较重要的一个组件kube-proxy。
总结来说kube-proxy实现的主要有几点作用。
  • 实时watching Kubernetes kube-API ,获取建立Service的建立、升级信息,增加或者删除backend Pod 信息,来获取Pod 和 vip的映射关系。
  • 维护本地Netfilter 、 iptables、 IPVS 内核组件:
      通过修改和更新Netfilter,iptables,IPVS 规则,来实现数据报文的转发规则;
  • 实现每个node上 clusertIP的发布和路由为维护;
  • 构建路由信息,通过转发规则转发报文到VIPs对应的Pod。
 
2. Userspace 和 Kernelspace
 
说到kube-proxy 能操作iptables 和 netfilter 进行路由的变更和包的转发操作。我们需要弄清楚两个概念:Userspace(用户空间) 和 Kernelspace(内核空间)。
在Linux 系统中,内存被分成两个不同的区域:Userspace、Kernelspace。
Userspace值得是,在操作系统中,用户安装的所有的软件和并启动的进程的服务。
Kernelspace是值得是在操作系统中,能执行命令,提供操作系统的底层服务的能力。
Userspace 需要操作系统的资源时,例如为计算指令需要请求占用CPU time 、操作磁盘的I/O,或者fork一个程序进程等。都需要call   Kernel 请求资源服务。
通常,Kernelspace模块和进程比Userspace进程快得多,因为它们直接与系统硬件交互。如果了解更深入,这里有redhat的的一篇文章。
 

 

3. kube-proxy三种模式

在K8s中,kube-proxy有三种模式在实现虚拟IP、路由信息和报文转发。
  • userspace 代理模式
  • iptables 模式
  • IPVS 模式
我们分别对着三种模式进入细节的讨论。
3.1. Userspace Proxy Mode
在userspace 模式下,kube-proxy 就是一个反向代理的功能,对userspace 的报文封装往 kernelspace 转发,主要是处理路由规则下发、包转发规则、负载均衡功能,所以kube-proxy会在网络流量比较高时,数据报文传输比较高的情况下,kube-proxy会频繁在userspace和kernelspace来回进行上下文切换。
 
在这个模式下,kube-proxy 主要有这么几步来实现实现报文转发:
  • 通过watching kubernetes集群 cluster API, 获取新建、删除Service或者Endpoint Pod指令。
  • 获取建立新ClusterID的Service时,kube-proxy在本地node上开放随机端口,基于服务的“SessionAffinity”策略选择要转发到 backend Pod。
  • kube-proxy会安装iptables规则,以拦截到Services的VIPs和Services端口的流量,并将该流量重定向到在上述步骤中打开的主机端口。
  • 当重定向的流量获取到node端口时,kube-proxy 作为一个负载均衡,把流量分发到后端的backend。选择后端Pod的默认方式负载均衡是轮询。
 
从VIP转发流量重定向到到node上的随机端口,进行netfilter 包过滤;再回Userspace进行负载均衡转发;在这个Userspace这个模式下,没有用到iptables的路由规则,kube-proxy在这个过程中多次进行 Userspace 和kernelspace 的切换,因此Userspace 模式对性能损耗比其它两个方式要大。
 

当clusetr iP建立的时候,kube-proxy 就在本地node物理网卡上,生成一个随机端口,并建立了一条从 VIPs到node物理网卡IP上随机端口的netfiters规则。有请求包文转发到这个端口上的时候,kube-proxy 选择一个Pod并转发报文。
3.2. Iptables Proxy Mode
 
 基于userspace 模块性能原因,在 Kubernetes v1.2 以后,Iptables模式为Services的默认代理模式。在iptables 代理模式中,kube-proxy不在作为反向代理的在VIPs 和backend Pods之间进行负载均衡的分发。这个工作放给工作在四层的iptables来实现。iptables 和netfilter紧密集成,密切合作,都在kernelspace 就实现了包的转发。
 
在这个模式下,kube-proxy 主要有这么几步来实现实现报文转发:
  • 通过watching kubernetes集群 cluster API, 获取新建、删除Services或者Endpoint Pod指令。
  • kube-proxy 在node上设置iptables规则,当有请求转发到Services的 ClusterIP上后,会立即被捕获,并重定向此Services对应的一个backend的Pod。
  • kube-proxy会在node上为每一个Services对应的Pod设置iptables 规则,选择Pod默认算法是随机策略。
在iptables模式中,kube-proxy把流量转发和负载均衡的策略完全委托给iptables/netfiter 来做,这些转发操作都是在kernelspace 来实现,比userspace 快很多。
  

在iptables 中kube-proxy 只做好watching API 同步最新的数据信息这个角色。路由规则信息和转发都放在了kernelspace 的iptables 和netfiter 来做了。但是,这个这个模式不如userspace模式的一点是,在usersapce模式下,kube-proxy做了负载均衡,如果选择的backend 一台Pod没有想要,kube-proxy可以重试,在iptables模式下,就是一条条路由规则,要转发的backend Pod 没有响应,且没有被K8S 摘除,可能会导致转发到此Pod请求超时,需要配合K8S探针一起使用。
3.3. IPVS proxy mode
IPVS是LVS一个组件,提供高性能、高可靠性的四层负载均衡器。IPVS 是IP Virtual Server的简写。IPVS构建在netfilter上,作为Linux 内核的一部分,从传输层实现了负载均衡。IPVS能直接转发 基于Services的TCP 和UDP到真实服务器。IPVS能直接构建一个VIPs 并通过负载均衡算法,把请求转发到backend Pod。可能会将IPVS视为Linux内核负载平衡器,类似于kube-proxy在用户空间模式下所做的工作。
我们都知道,在Linux 中iptables设计是用于防火墙服务的,对于比较少规则的来说,没有太多的性能影响。但是对于,一个K8S集群来说,会有上千个Services服务,当然也会转发到Pods,每个都是一条iptables规则,对集群来说,每个node上会有大量的iptables规则,简直是噩梦。
同样IPVS可以解决可能也会遇见这样大规模的网络转发需求,但是IPVS用hash tabels来存储网络转发规则,比iptables 在这上面更有优势,而且它主要工作在kernelspace,减少了上下文切换带来的开销。
 
kube-proxy和IPVS在配置网络转发中,有这么几步:
  • 通过watching kubernetes集群 cluster API, 获取新建、删除Services或者Endpoint Pod指令,有新的Service建立,kube-proxy回调网络接口,构建IPVS规则。
  • 同时,kube-proxy会定期同步 Services和backend Pods的转发规则,确保失效的转发能被更新修复。
  • 有请求转发到后端的集群时,IPVS的负载均衡直接转发到backend Pod。
IPVS支持的负载均衡算法有这么几种:
  • rr: 轮询
  • lc: 最小连接数
  • dh: 目的地址hash
  • sh: 源地址hash
  • sed: 最短期望延迟
  • nq: 无须队列等待
在node上通过 “–ipvs-scheduler”参数,指定kube-proxy的启动算法。
 
总的来说,Kubernets的Service组件,越来越完善,性能也越来越高。至少现在,我们看到已经加入了四层的转发策略,在实际运用中,很多公司都有自己的接入层和中间API的网关,可以解决转发和流量调度;Pod服务注册通过调用服务中心也解决了对于后端Pod异常的监控检查功能。当然我们也希望尽量复用Kubernets技术和组件,降低服务的可维护性。
K8S中文社区微信公众号

评论 抢沙发

  • 昵称 (必填)
  • 邮箱 (必填)
  • 网址