需求:需要收集客户端的真实IP,要将service的externalTrafficPolicy的类型改为local模式(原来是cluster模式)

一、externalTrafficPolicy概述

  把集群外部的服务引入到集群内部来,在集群内部直接使用;当我们的集群服务需要访问k8s之外的集群时,可以选择这种类型,然后将服务的IP及端口写入到k8s服务中,k8s的代理将会帮助我们访问到外部的集群服务。

  • service.spec.externalTrafficPolicy​ - 表示此服务是否希望将外部流量路由到节点本地或集群范围的端点。
  • 有两个可用选项:Cluster(默认)和 Local。
  • Cluster 隐藏了客户端源 IP,可能导致第二跳到另一个节点,但具有良好的整体负载分布。流量可以转发到其他节点上的Pod
  • Local 保留客户端源 IP 并避免 LoadBalancer 和 NodePort 类型服务的第二跳, 但存在潜在的不均衡流量传播风险。流量只发给本机的Pod
  • service.spec.healthCheckNodePort​​ - 指定服务的 healthcheck nodePort(数字端口号)。 如果未指定​​healthCheckNodePort​​​,服务控制器从集群的 NodePort 范围内分配一个端口。 你可以通过设置 API 服务器的命令行选项​​--service-node-port-range​​​ 来配置上述范围。 它将会使用用户指定的​​healthCheckNodePort​​​ 值(如果被客户端指定)。 仅当​​type​​​ 设置为 LoadBalancer 并且​​externalTrafficPolicy​​ 设置为 Local 时才生效。

  

kubernetes的service对象之externalTrafficPolicy_负载均衡

 

 

  可以通过在service的配置文件中将externalTrafficPolicy设置为local来激活此功能

apiVersion: v1
kind: Service
metadata:
name: front-help-center
namespace: biz-dev-front
spec:
externalTrafficPolicy:Local- nodePort: 31003
port: 80
protocol: TCP
targetPort: 80
selector:
name: front-help-center
type: NodePort

二、​​externalTrafficPolicy​​ 的Cluster模式和Local模式的区别

  存在这2种模式的原因就是,当前节点的Kube-proxy在转发报文的时候,会不会保留原始访问者的IP。

  一)Cluster模式

   注:cluster是默认模式。kube-proxy不管容器在哪,公平转发。

  Kube-proxy转发时会替换掉报文的源IP。即:容器收的报文,源IP地址,已经被替换为上一个转发节点的了。

  

kubernetes的service对象之externalTrafficPolicy_客户端_02

  原因:kube-proxy在做转发的时候,会做一次SNAT (source network address translation),所以源IP变成了节点1的IP地址。

延展知识点:snat确保回去的报文可以原路返回,不然回去的路径不一样,客户会认为非法报文的。

  优缺点:

  • 优点:服务负载会比较好,因为无论容器实例怎么分布在多个节点上,他都会转发过去
  • 缺点:由于多了一次转发,性能会损失一点

 

  二)Local模式

  只转发本地的pod,绝不跨节点转发

  特点:kube-proxy转发时会保留源IP。即:容器收到的报文,看到的源IP还是客户的。

  

kubernetes的service对象之externalTrafficPolicy_ip地址_03

 

 

   优缺点

  • 优点:因为少一次转发,性能会好一点
  • 缺点:负载均衡不会很好,因为当容器分布在不同节点上,kube-proxy只转发到本机,不转到其他节点的pod。

  注意:这种模式下的Service类型只能为外部流量,即:LoadBalancer 或者 NodePort 两种,否则会报错

  同时,由于本机不会跨节点转发报文,所以要想所有节点上的容器有负载均衡,就需要上一级的Loadbalancer来做了。

  

kubernetes的service对象之externalTrafficPolicy_负载均衡_04

 

 

  不过流量还是会不太均衡,如上图,Loadbalancer看到的是2个后端(把节点的IP),每个Node上面几个Pod对Loadbalancer来说是不知道的。

  想要解决负载不均衡的问题:可以给Pod容器设置反亲和,让这些容器平均的分布在各个节点上

affinity:
podAntiAffinity:
preferredDuringSchedulingIgnoredDuringExecution:
- weight: 100
podAffinityTerm:
labelSelector:
matchExpressions:
- key: k8s-app
operator: In
values:
- my-app
topologyKey: kubernetes.io/hostname

三、externalTrafficPolicy怎么选择是用Cluster还是Local模式

  若追求性能,选择Local模式,毕竟少了一次转发。

  不过要考虑好怎么解决负载不均衡问题:一般使用pod反亲和性,将pod部署到不同节点

  从外部LB接收流量的,那么使用:Local模式 + Pod反亲和,一般是足够的