文档首页/ 云容器引擎 CCE/ 最佳实践/ 网络/ 不同场景下容器内获取客户端源IP
更新时间:2024-11-12 GMT+08:00

不同场景下容器内获取客户端源IP

在容器化环境中,客户端与容器服务器间的通信可能涉及多种代理服务器。当外部请求经过代理服务器多层转发时,客户端源IP地址可能无法被成功传递至容器内的业务中。本文将针对CCE集群提供网络访问的不同方案,详细说明如何在容器内部有效地获取客户端源IP。

场景介绍

图1 容器中获取源IP

根据不同的网络设置,容器内获取客户端源IP的方法可能会有所不同。以下是几种常见的网络访问配置及其对应的解决方案:

  • Ingress七层转发:应用在七层访问时,客户端源IP默认保存在HTTP头部的“X-Forwarded-For”字段,无需进行其他配置即可获取客户端源IP。
  • Service四层转发:不同类型的Service获取源IP的方式及原理不同。
    • 负载均衡类型Service:将弹性负载均衡器作为流量入口,支持使用共享型或独享型的弹性负载均衡器。
      • 共享型弹性负载均衡器需要在监听器上开启“获取客户端IP”功能。
      • 独享型弹性负载均衡器在监听器上默认启用“获取客户端IP”功能,无需用户手动设置。
    • 节点访问类型Service:将容器端口映射到节点端口,将节点端口作为对外服务的访问入口。节点访问Service的客户端源IP能力与它的“服务亲和”配置相关。
      • 当节点访问类型Service的“服务亲和”配置为“集群级别”时,流量在集群中会经过一次转发,导致Service后端的容器无法获取客户端源IP。
      • 当节点访问类型Service的“服务亲和”配置为“节点级别”时,流量不经过转发直接访问节点上的容器,因此Service后端的容器可以获取客户端源IP。

若已使用Istio服务网格,获取源IP地址的方法请参见服务加入Istio后,如何获取客户端真实源IP?

支持获取源IP地址的场景

由于网络模型差异,CCE在部分使用场景下暂不支持获取源IP,如表1,若在集群使用过程中需要获取源IP,请尽量避免此类场景。表中“-”代表无此场景。

表1 支持获取源IP地址的场景分类

一级分类

二级分类

负载均衡类型

VPC、容器隧道网络模型

云原生网络2.0模型(CCE Turbo集群)

操作指导

七层转发(Ingress)

ELB型

共享型

支持

支持

ELB Ingress

独享型

支持

支持

Nginx型(对接NGINX Ingress控制器插件)

共享型

支持

暂不支持

Nginx Ingress

独享型

支持

支持

默认开启,无需进行其他配置

四层转发(Service)

负载均衡(LoadBalancer)

共享型

支持

暂不支持(使用hostNetwork的工作负载支持)

负载均衡( LoadBalancer )

独享型

支持

支持

节点访问(NodePort)

-

支持

暂不支持(使用hostNetwork的工作负载支持)

节点访问 ( NodePort )

ELB Ingress

对于ELB Ingress(即使用HTTP/HTTPS协议),ELB默认会开启获取客户端源IP,无需其他操作。

客户端源IP会被负载均衡放在HTTP头部的X-Forwarded-For字段,格式如下:

X-Forwarded-For: 客户端源IP, 代理服务器1-IP,  代理服务器2-IP, ...

X-Forwarded-For字段中获取的第一个地址就是获取客户端源IP。

Nginx Ingress

云原生网络2.0模型下(即CCE Turbo集群),Ingress开启对接NGINX Ingress控制器插件时使用共享型ELB暂不支持获取源IP,参见支持获取源IP地址的场景。如需获取源IP,请卸载NGINX Ingress控制器插件并在重新安装时使用独享型ELB。

  • Nginx Ingress使用独享型ELB时,默认开启源地址透传功能,无需其他配置即可获取客户端源IP。
  • Nginx Ingress使用共享型ELB时,获取客户端源IP的操作步骤如下:
  1. 以Nginx工作负载为例,未配置源IP访问前,使用以下命令查看访问日志,其中nginx-c99fd67bb-ghv4q为Pod名称:

    kubectl logs nginx-c99fd67bb-ghv4q

    回显如下:

    ...
    10.0.0.7 - - [17/Aug/2023:01:30:11 +0000] "GET / HTTP/1.1" 200 19 "http://114.114.114.114:9421/" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/115.0.0.0 Safari/537.36 Edg/115.0.1901.203" "100.125.**.**"

    其中100.125.**.**为负载均衡的地址段,说明流量经过负载均衡转发。

  2. 开启“获取客户端IP”功能。仅使用共享型ELB时需操作,独享型ELB默认开启源地址透传功能,无需手动开启。

  3. 重新访问工作负载,并查看新增的访问日志如下:

    ...
    10.0.0.7 - - [17/Aug/2023:02:43:11 +0000] "GET / HTTP/1.1" 304 0 "http://114.114.114.114:9421/" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/115.0.0.0 Safari/537.36 Edg/115.0.1901.203" "124.**.**.**"

    显示成功获取到客户端源IP。

如果您需要为集群Nginx Ingress Controller所使用的ELB开启WAF功能,不同的WAF模式会影响Nginx Ingress Controller获取真实的客户端IP:

  • 使用WAF云模式的CNAME接入

    采用CNAME模式接入,会导致请求先通过WAF,经过WAF进行防护检查之后再转发给ELB。因此即使ELB已开启源地址透传,实际上客户端得到为WAF的回源IP,造成Nginx Ingress Controller将默认无法获得真实的客户端IP。此时您可以编辑NGINX Ingress控制器插件,在nginx配置参数处添加以下配置。

    {
         "enable-real-ip": "true",
         "use-forwarded-headers": "true",
         "proxy-real-ip-cidr": <您从WAF获取到的回源IP段> 
    }
  • 使用WAF云模式ELB接入

    该模式为透明接入(旁路部署),仅支持独享型ELB,Nginx Ingress Controller默认可以获得真实的客户端IP。

负载均衡( LoadBalancer )

负载均衡( LoadBalancer )的Service模式下,不同类型的集群获取源IP的场景不一,部分场景下暂不支持获取源IP,参见支持获取源IP地址的场景
  • CCE集群(VPC、容器隧道网络模型):使用共享型和独享型ELB均支持获取源IP。
  • CCE Turbo集群(云原生网络2.0模型):使用独享型ELB时支持获取源IP;使用共享型ELB时,仅开启hostNetwork的工作负载支持获取源IP。

VPC、容器隧道网络模型

通过控制台开启获取源IP的步骤如下:

  1. 在CCE控制台创建负载均衡类型的Service,服务亲和选择“节点级别”而不是“集群级别”。

  2. 前往ELB控制台,开启ELB实例对应监听器的“获取客户端IP”功能。独享型ELB默认开启源地址透传功能,无需手动开启。

    1. 在管理控制台左上角单击图标,选择区域和项目。
    2. 选择“服务列表 > 网络 > 弹性负载均衡 ELB”。
    3. 在“弹性负载均衡器”界面,单击需要操作的负载均衡名称。
    4. 切换到“监听器”页签,单击需要修改的监听器名称右侧的“编辑”按钮。如果存在修改保护,请在监听器基本信息页面中关闭修改保护后重试。
    5. 开启“获取客户端IP”开关。
      图3 开启开关

云原生网络2.0模型(CCE Turbo集群)

云原生网络2.0模型集群中使用共享型ELB创建负载均衡时:
  • 开启hostNetwork的工作负载:支持将服务亲和选项设置为“节点级别”,可获取源IP。
  • 其他工作负载:无法将服务亲和选项设置为“节点级别”,因此无法获取源IP。

建议使用独享型ELB,外部访问可不经过转发直通容器。独享型ELB默认开启源地址透传,无需前往ELB控制台手动开启“获取客户端IP”开关,只需要在CCE控制台创建负载均衡服务时选择独享型负载均衡,即可获取客户端源IP。

节点访问 ( NodePort )

节点访问(NodePort)类型的Service的服务亲和需选择“节点级别”而不是“集群级别”,即Service的spec.externalTrafficPolicy需要设置为Local

云原生网络2.0模型集群中使用节点访问(NodePort)类型的Service时,只有开启hostNetwork的工作负载支持设置“节点级别”的服务亲和,因此仅开启hostNetwork的工作负载支持获取源IP。

图4 服务亲和选择节点级别