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层应用 |