K8S网络系列之一:Service的基本原理和工作模式


kube-proxy的作用

kube-proxy的工作流程

在k8s中,service的ClusterIP能够实现数据报文请求的转发,需要在每个node节点上部署一个组件kube-proxy:

  • 实时监控API,获取service和pod信息,来保持pod和虚拟IP的映射关系
  • 维护本地netfilter、iptables、IPVS等内核组件,实现数据报文的转发规则
  • 实现每个node节点上虚拟IP的发布和路由维护
  • 构建路由信息,通过转发规则转发报文到虚拟IP对应的pod

kube-proxy的三种模式

1.Userspace Proxy Mode


在userspace代理模式下,kube-proxy起到一个反向代理的功能,对userspace的报文封装再往kernelspace转发,主要是处理路由规则下发,数据包转发和负载均衡,所以kube-proxy会在网络流量和数据报文传输较高时频繁地在userspace和kernelspace之间进行上下文切换。

在该模式下,kube-proxy流量转发步骤:

  • 接受APISserver新建或删除service和pod的指令
  • 当获取到新建service的指令后,kube-proxy在node上开放随机端口,然后转发到pod上
  • kube-proxy会维护iptables规则,将访问service的虚拟IP和端口的流量拦截并重定向到上面开放的端口
  • 当重定向的流量获取到node端口时,kube-proxy作为一个负载均衡器,把流量分发给后端的pod

2.Iptables Proxy Mode


userspace代理模式由于性能原因,在kubernetes v1.2以后就不再怎么使用了,取而代之的是iptables代理模式。在iptables模式中,kube-proxy不再作为反向代理在虚拟IP和pod之间进行转发,而是将这个工作交给iptables来做,iptables和netfilter紧密合作在kernelspace里就实现了数据包的转发。

在该模式下,kube-proxy流量转发步骤:

  • 接受APISserver新建或删除service和pod的指令
  • kube-proxy在node上设置iptables规则,当有请求转发到service的虚拟IP上时,会立即被捕获并重定向到此service的一个pod上
  • kube-proxy会在node上为每一个service对应的pod设置iptables规则

3.IPVS Proxy Mode


IPVS是lvs的一个组件,提供高性能、高可靠的四层负载均衡器,IPVS是IP Virtual Server的简写。IPVS构建在netfilter上,作为Linux内核的一部分,在四层实现了负载均衡。IPVS能直接转发基于service的TCP/UDP到Real Server上;还能直接构建一个虚拟IP并通过负载均衡算法,把请求转发到pod上。这里的IPVS的功能就类似于kube-proxy在userspace代理模式下作的工作。

而在iptables模式中,一个k8s集群会有大量service,意味着会有极大量的iptables规则,IPVS在这方面做了改进,它将网络转发规则用hash tables来存储,而且主要工作在kernelspace,尖山了上下文切换影响的性能。

Service的概念


service是K8S中的核心资源类型。一个pod运行起来以后,在集群的pod之间可以直接写podIP或者pod名称访问,但集群之外、或者跨namespace的pod想要想访问这个pod,就必须为之建立一个service。service是pod对外提供访问的必经之路。

service可以根据标签选择器(label selector)对应到pod。当创建一个service时也会对应创建一个endpoint对象,endpoint是用来做容器发现的。当pod重启以后,podIP和名称都会发生变化,但service不会变,它会监听APISserver通过endpoint实时更新它所关联的pod。service通过kube-proxy组件实现将网络数据路由到它所关联的pod。

service还提供了负载均衡的能力,它对于收到的请求会基于RoundRobin轮询算法路由到后端的pod。

Service四种类型

ClusterIP

默认类型,是NodePort和LoadBalancer类型的基础。使用clusterIP映射selector标签关联的pod的动态IP,为副本控制器管理的pod的多副本提供统一接入点。默认不指定serviceType的话会分配clusterIP,并根据创建集群时设置的service的CIDR随机分配一个IP。

NodePort

在ClusterIP基础之上,在所有集群成员节点上暴露相同的nodePort(可用范围30000~32767),用户通过访问任意集群成员节点的nodePort以转发ClusterIP。

LoadBalancer

在NodePort基础上,调用云供应商提供的功能自动创建一个4层负载均衡器,用户通过云供应商提供的负载均衡器以转发到成员节点的nodePort。负载均衡器的端口和service的端口保持一致。

ExternalName

不同于以上三种,不使用selector关联当前命名空间中的pod。把externalName所指定的互联网DNS主机名,在集群内创建Service NAME别名,类似于CNAME记录。

总结

K8S向集群外部暴露端口方案

暴露方案 原理 优点 缺点 使用场景
port-forward 通过kubectl port-forward,建立socket监听转发pod、deployment、service端口到本地,另起终端通过访问本机指定端口 独立于应用,无需修改应用配置。无权ssh访问成员节点时的用法 不可用于生产 开发人员测试
hostPort 但pod暴露方案,pod所在节点上的kube-proxy维护该节点iptables的NAT表的自定义链规则,在集群外部通过访问pod所在节点的固定端口,已访问pod。通过pod.spec.containers.ports.hostPort指定节点监听端口 简单、测试 无控制器的单pod 测试环境,集群外部临时访问无控制器管理的单pod
hostNetwork 单pod使用所在节点的网络名称空间,访问节点即访问pod。需要开启pod.spec.hostNetwork: true 简单,把传统基础架构服务容器化 安全隐患,需要使用securityContext加固 测试环境,或传统基础架构服务容器化。特殊容器如ingress controller
nodePort 暴露单pod、service或由rs、rc、deployment所管理的pod。NodePort类型SVC,通过访问所有成员节点的svc.spec.ports.nodePort以转发到service endpoints 可用于暴露多副本应用 依赖于外部自维护LB,统一集群节点访问入口 on-premise配置外部LB暴露4层业务
LoadBalancer 通过访问云供应商提供的LB,流量调度到成员节点的nodePort 云供应商提供LB,无需维护 依赖于公有云4层LB,不适合暴露http/https应用 使用云供应商托管的k8s,如AKS、EKS、GKE暴露非7层应用
ingress 7层暴露方案。通过访问DNS主机名,DNS记录解析到ingress controller,再由ingress controller转发到service 无需配置维护L7 LB适用于暴露http/https应用 类型较多,合理选择 标准化暴露7层应用

文章作者: 洪宇轩
版权声明: 本博客所有文章除特別声明外,均采用 CC BY 4.0 许可协议。转载请注明来源 洪宇轩 !
评论
  目录