不同场景下容器内获取客户端源IP
背景
Kubernetes已经成为当今容器化的标准,人们在享受容器带来的高效与便利的同时,也遇到一些烦恼:客户端和容器服务器之间可能存在多种不同形式的代理服务器,那容器中如何获取到客户端真实的源IP呢?下面我们就几种场景类型进行讨论。
原理介绍
七层转发:
Ingress:应用在七层访问时,客户端源IP默认保存在HTTP头部的“X-Forwarded-For”字段,无需做其他操作。
- ELB型:自研ELB型Ingress基于弹性负载均衡服务ELB实现公网和内网(同一VPC内)的七层网络访问,后端服务为NodePort类型,需将“服务亲和”选项设置为“节点级别”。
- Nginx型:基于nginx-ingress插件实现七层网络访问,后端服务支持ClusterIP和NodePort类型。当后端服务为NodePort类型,同样需将“服务亲和”选项设置为“节点级别”。
四层转发:
- 负载均衡:ELB访问方式,是通过华为云弹性负载均衡ELB产品来实现负载均衡。共享型负载均衡四层监听器(TCP/UDP)支持开启“获取客户端IP”功能。而独享型负载均衡的四层监听器(TCP/UDP)默认开启源地址透传功能,无需手动开启。
- 节点访问:Nodeport访问方式,是将容器端口映射到节点端口,如果“服务亲和”选择“集群级别”需要经过一次服务转发,无法实现获取客户端源IP,而“节点模式”不经过转发,可以获取客户端源ip。
七层转发(Ingress)
针对七层服务(HTTP/HTTPS协议),需要对应用服务器进行配置,然后使用X-Forwarded-For的方式获取来访者的真实IP地址。
真实的来访者IP会被负载均衡放在HTTP头部的X-Forwarded-For字段,格式如下:
X-Forwarded-For: 来访者真实IP, 代理服务器1-IP, 代理服务器2-IP, ...
当使用此方式获取来访者真实IP时,获取的第一个地址就是来访者真实IP。
详情请参见如何获取来访者的真实IP?。

- 云原生网络2.0模型下,Ingress开启对接nginx-ingress插件时使用共享型ELB暂不支持获取源IP,参见支持获取源IP地址的场景。如需获取源IP,请卸载nginx-ingress插件并在重新安装时使用独享型ELB。
- 添加Ingress时,若后端为NodePort类型的Service,需将服务亲和设置为“节点级别”,即spec.externalTrafficPolicy需设置为“Local”,参见节点访问 ( NodePort )。
负载均衡( LoadBalancer )
- CCE集群(VPC、容器隧道网络模型):使用共享型和独享型ELB均支持获取源IP。
- CCE Turbo集群(云原生网络2.0模型):仅使用独享型ELB(ENI负载均衡)时支持获取源IP。
VPC、容器隧道网络模型
开启获取源IP的步骤如下:
- 在CCE控制台创建负载均衡类型的Service,服务亲和选择“节点级别”而不是“集群级别”。
- 前往ELB控制台,开启ELB实例对应监听器的“获取客户端IP”功能。独享型ELB默认开启源地址透传功能,无需手动开启。
- 登录弹性负载均衡ELB的管理控制台。
- 在管理控制台左上角单击
图标,选择区域和项目。
- 选择“服务列表 > 网络 > 弹性负载均衡”。
- 在“负载均衡器”界面,单击需要操作的负载均衡名称。
- 切换到“监听器”页签。
- 新增场景:单击“添加监听器”。
- 修改场景:单击需要修改的监听器名称右侧的
。
- 开启“获取客户端IP”开关。图1 开启开关
云原生网络2.0模型
云原生网络2.0模型下,使用共享型ELB创建负载均衡时服务亲和无法设置服务亲和选项为“节点级别”,因此无法获取源IP。如需获取源IP,必须使用ENI负载均衡对接独享型ELB,外部访问可不经过转发直通容器。
独享型ELB默认开启源地址透传,无需前往ELB控制台手动开启“获取客户端IP”开关,只需要在CCE控制台创建ENI负载均衡时选择独享型负载均衡,即可获取客户端源IP,如下图所示。
