kubernetes内部容器获取客户端IP

Posted by Zeusro on April 8, 2019

环境:

  1. kubernetes版本: 阿里云v1.11.5
  2. 节点系统 CentOS Linux 7 (Core)
  3. 节点容器版本 docker://17.6.2

概念介绍

X-Forwarded-For

1
X-Forwarded-For: <client>, <proxy1>, <proxy2>

remote_addr

remote_addr代表客户端的IP,但它的值不是由客户端提供的,而是服务端根据客户端的ip指定的,当你的浏览器访问某个网站时,假设中间没有任何代理,那么网站的web服务器(Nginx,Apache等)就会把remote_addr设为你的机器IP,如果你用了某个代理,那么你的浏览器会先访问这个代理,然后再由这个代理转发到网站,这样web服务器就会把remote_addr设为这台代理机器的IP。

内部请求(Pod对Pod请求)

1
podA-->podB

这时只有getRemoteAddr能够获取IP,其余header全空.podB获得的clientIP为podA的podIP(虚拟IP)

The client_address is always the client pod’s IP address, whether the client pod and server pod are in the same node or in different nodes.

外部请求

Nodeport svc

1
client-->svc-->pod

externalTrafficPolicy: Cluster

svc.spec设置externalTrafficPolicy: Cluster,意思是所有节点都会启动kube-proxy,外部流量可能转发多1次.

1
2
3
4
5
6
7
8
9
          client
             \ ^
              \ \
               v \
   node 1 <--- node 2
    | ^   SNAT
    | |   --->
    v |
 endpoint

这时流量通过node2的转发,app 获得的clientIP不定,有可能是node 2 的IP,也有可能是客户端的IP

externalTrafficPolicy: Local

svc.spec设置externalTrafficPolicy: Local,在运行pod的节点上启动kube-proxy,外部流量直达节点.

1
2
3
4
5
6
7
8
9
        client
       ^ /   \
      / /     \
     / v       X
   node 1     node 2
    ^ |
    | |
    | v
 endpoint

这时,只有运行了pod的节点才会有对应的proxy,避免了中间商(node 2)挣差价

clientIPremote_addr

LoadBalancer svc

svc.spec设置externalTrafficPolicy: Local.

1
2
3
4
5
6
7
8
9
                      client
                        |
                      lb VIP
                     / ^
                    v /
health check --->   node 1   node 2 <--- health check
        200  <---   ^ |             ---> 500
                    | V
                 endpoint

image

SLB监听HTTP:取X-Forwarded-For即可(从SLB获得客户端IP).

SLB监听TCP,则取remote_addr

externalTrafficPolicy: Cluster的情况就不用说了,没有意义.

ingress

1
client-->slb-->ingress svc-->ingress pod-->app svc-->pod

首先需要设置ingress的svc类型为Nodeport/LoadBalancer,并且externalTrafficPolicy: Local

app svc type为ClusterIP/NodePort/LoadBalancer都无所谓.

这个时候,X-Forwarded-For的值即为clientIP

remote_addringress pod Virtual IP

参考链接:

  1. source-ip
  2. HTTP 请求头中的 X-Forwarded-For
  3. 如何获取客户端真实IP
  4. 源地址审计:追踪 kubernetes 服务的SNAT
  5. 谈谈kubernets的service组件的Virtual IP