转载自:https://www.codetd.com/article/1948828


使用externalTrafficPolicy: Local保留报文的源地址:

1.1 nodePort类型

kubernetes将在Pod所在Node上针对nodePort下发DNAT规则,而在其他节点上针对nodePort下发DROP规则。


        client
       ^ /   \
      / /     \
     / v       X
   node 1     node 2
    ^ |
    | |
    | v
 endpoint


以下使用nginx的例子。 

在svc的编排文件中增加externalTrafficPolicy后,重新创建nginx-service。 

kind: ServiceapiVersion: v1metadata:
  name: nginx-servicespec:
  type: NodePort
  externalTrafficPolicy: Local
  ports:
    - port: 80
      targetPort: 80
      nodePort: 30080
  selector:
    component: nginx

externalTrafficPolicy的好处是,Pod内应用的确可以拿到真实的客户端地址了,但坏处是: 客户端只能使用pod所在的node的IP访问,无法使用其他node的ip访问以及使用vrrp之类的virtual IP来实现ha,对客户端来说会麻烦一点。 

设置 service.spec.externalTrafficPolicy 的值为 Local,请求就只会被代理到本地 endpoints 而不会被转发到其它节点。这样就保留了最初的源 IP 地址。

1.2如果使用ingress NodePort方式,并以DaemonSet方式安装nginx-ingress-controller,可以实现客户端从任何节点都可以访问,并可获取到客户端的真实IP:

经过修改后的ingress:https://github.com/4220182/k8s/tree/master/ingress-nginx/0.15.0/daemonset

跟原版比较,改动比较少的:


$ diff ./ingress-nginx/0.15.0/deployment/mandatory.yaml ./ingress-nginx/0.15.0/daemonset/mandatory.yaml 225c225
< kind: Deployment
---> kind: DaemonSet230d229
<   replicas: 1
$ diff ./deployment/service-nodeport.yaml ./daemonset/service-nodeport.yaml 8d7>   externalTrafficPolicy: Local

测试样例:https://github.com/4220182/k8s/tree/master/example/nginx

                client  
           ^ /          ^ \ 
          / /            \ \ 
         / v              \ v    
node 1 service-NodePort     node 2 serviceNodePort  
     ^ |                    ^ |
     | |                    | |
     | v                    | v
node1 ingress-controller  node2 ingress-controller 
    ^  \                  /  ^    
     \  \                /  /   
      \  \              /  /  
       \  v            v  /          
             endpoint

测试结果:

$ ab -n 100 -c 1  http://my.test.com/
$ kubectl logs po/nginx-5d758c4f46-p5r2j -f172.30.23.0 - - [06/Jul/2018:15:30:35 +0000] "GET / HTTP/1.1" 200 612 "-" "curl/7.54.0" "192.168.5.101"172.30.23.0 - - [06/Jul/2018:15:33:20 +0000] "GET / HTTP/1.1" 200 612 "-" "ApacheBench/2.3" "192.168.5.101"172.30.23.0 - - [06/Jul/2018:15:33:20 +0000] "GET / HTTP/1.1" 200 612 "-" "ApacheBench/2.3" "192.168.5.101"172.30.23.0 - - [06/Jul/2018:15:33:20 +0000] "GET / HTTP/1.1" 200 612 "-" "ApacheBench/2.3" "192.168.5.101"...

可以看到,nginx的日志($http_x_forwarded_for)已经记录了客户端的真实IP(192.168.5.101); 

2. LoadBalancer 类型 : 

参考 https://kubernetes.io/cn/docs/tutorials/services/source-ip/


ingress-nginx 安装:https://blog.csdn.net/kozazyh/article/details/80580196


其他参考:

https://kubernetes.io/cn/docs/tutorials/services/source-ip/

https://kubernetes.io/docs/tutorials/services/source-ip/

https://ieevee.com/tech/2017/09/18/k8s-svc-src.html

https://blog.csdn.net/mailjoin/article/details/79686979

通过request获取真实客户端ip:http://wei5201.iteye.com/blog/735165