ingress nginx传递用户真实ip问题

背景

业务应用经常有需要用到用户真实ip的场景,比如:异地登录的风险预警、访问用户分布统计等功能等。当有这种需求的时候,在业务上容器过程中,如果用到ingress就要注意配置了。通常,用户ip的传递依靠的是X-Forwarded-*参数。但是默认情况下,ingress是没有开启的。

ingress的文档还比较详细,这里介绍一下可能用到的这3个参数:
在这里插入图片描述

注:在文档顶栏的搜索框搜索forward字样就可以找到这3个参数

1. use-forwarded-headers

  • 如果Nginx在其他7层代理或负载均衡后面,当期望Nginx将X-Forwarded-*的头信息传递给后端服务时,则需要将此参数设为true
  • 如果设为false(默认为false),Nginx会忽略掉X-Forwarded-*的头信息。false设置适用于Nginx直接对外或前面只有3层负载均衡的场景

由于ingress的主配置是从configmap中获取的,更新参数则需要修改名为nginx-configuration的configmap的配置:在data配置块下添加use-forwarded-headers: "true"

修改后,ingress nginx会自动加载更新nginx.conf主配置文件。下图为更新前后配置文件变化对比:
在这里插入图片描述

注:左边为开启use-forwarded-headers后ingress nginx主配置文件,右边为开启前

2. forwarded-for-header

用来设置识别客户端来源真实ip的字段,默认是X-Forwarded-For。如果想修改为自定义的字段名,则可以在configmap的data配置块下添加:forwarded-for-header: "THE_NAME_YOU_WANT"。通常情况下,我们使用默认的字段名就满足需求,所以不用对这个字段进行额外配置。

3. compute-full-forwarded-for

如果只是开启了use-forwarded-headers: "true"的话,会发现还是没能获取到客户端来源的真实ip,原因是当前X-Forwarded-For变量是从remote_addr获取的值,每次取到的都是最近一层代理的ip。为了解决这个问题,就要配置compute-full-forwarded-for字段了,即在configmap的data配置块添加:compute-full-forwarded-for: "true"。其作用就是,将客户端用户访问所经过的代理ip按逗号连接的列表形式记录下来。

待ingress nginx加载configmap并更新主配置文件后,对比更新前后变化如下:
在这里插入图片描述
在这里插入图片描述

注:左边是未开启compute-full-forwarded-for配置的ingress nginx主配置文件,右边是开启了的

举例说明

如果从客户端ip0发起一个HTTP请求到达服务器之前,经过了三个代理proxy1、proxy2、proxy3,对应的ip分别为ip1、ip2、ip3,那么服务端最后得到的X-Forwarded-For值为:ip0,ip1,ip2。列表中并没有ip3,ip3可以在服务端通过remote_addr来获得。这样应用程序通过获取X-Forwarded-For字段的第一个ip,就可以得到客户端用户真实ip了。

注意项

值得注意的是,并不是所有的场景都能通过X-Forwarded-For来获取用户正式ip。
比如,当服务器前端使用了CDN的时候,X-Forwarded-For方式获取到的可能就是CDN的来源ip了,
这种情况,可以根CDN厂商约定一个字段名来记录用户真实ip,然后代理将这个字段逐层传递,最后到服务端。

### 关于 Ingress-Nginx 的配置方法 #### 1. 部署 Ingress-Nginx 控制器 为了使 Ingress 功能正常工作,首先需要部署一个 Ingress 控制器。常见的控制器实现之一是 `ingress-nginx`[^3]。可以通过官方文档中的 YAML 文件完成其部署过程[^4]。 以下是典型的部署命令: ```bash kubectl apply -f https://raw.githubusercontent.com/kubernetes/ingress-nginx/controller-v1.1.1/deploy/static/provider/cloud/deploy.yaml ``` 此操作会启动 `ingress-nginx-controller` 并将其注册到集群中作为服务的一部分。 --- #### 2. 修改 Service 类型为 NodePort 或 LoadBalancer 默认情况下,`ingress-nginx` 使用的是 ClusterIP 类型的服务。如果希望外部能够访问该服务,则需将 Service 类型更改为 `NodePort` 或 `LoadBalancer`: 编辑对应的 Service 对象并设置 `.spec.type=NodePort` 或者通过以下方式修改端口号: ```yaml apiVersion: v1 kind: Service metadata: name: ingress-nginx-controller namespace: ingress-nginx spec: type: NodePort ports: - port: 80 targetPort: 80 nodePort: 30080 ``` 上述配置将 HTTP 流量映射至节点上的端口 `30080`。 --- #### 3. 编写 Ingress 资源定义 一旦控制器成功运行,可以创建自定义的 Ingress 资源来管理流量路由规则。下面是一个简单的示例: ```yaml apiVersion: networking.k8s.io/v1 kind: Ingress metadata: name: example-ingress annotations: nginx.ingress.kubernetes.io/rewrite-target: / spec: rules: - host: example.com http: paths: - path: / pathType: Prefix backend: service: name: my-service port: number: 80 ``` 在此例子中,所有发往 `example.com` 主机名下的请求都会被转发给名为 `my-service` 的 Kubernetes 服务,并且路径会被重写为目标根目录 `/`。 --- #### 4. 处理常见问题 当遇到某些特定错误时(如 `413 Request Entity Too Large`),可通过调整 Nginx 参数解决。例如,在 Ingress 资源上添加如下注解即可增加上传文件大小限制: ```yaml annotations: nginx.ingress.kubernetes.io/proxy-body-size: "50m" ``` 对于 SSL/TLS 相关异常情况,可参考 Rancher 文档中的解决方案[^5]。具体来说,有时需要初始化容器以修复证书权限问题。这涉及向 `Deployment` 添加额外字段用于执行脚本逻辑。 --- #### 5. 实践案例分析 假设存在两个微服务分别监听不同 URL 子路径,那么完整的 Ingress 定义可能是这样的形式: ```yaml apiVersion: networking.k8s.io/v1 kind: Ingress metadata: name: multi-path-example annotations: nginx.ingress.kubernetes.io/rewrite-target: /$2 spec: rules: - host: app.example.org http: paths: - path: /serviceA(/|$)(.*) pathType: ImplementationSpecific backend: service: name: service-a port: number: 80 - path: /serviceB(/|$)(.*) pathType: ImplementationSpecific backend: service: name: service-b port: number: 80 ``` 这里利用正则表达式匹配子路径并将剩余部分传递给目标服务处理。 --- ### 总结 以上展示了从基础安装到高级功能定制的一系列步骤,涵盖了如何正确配置 `ingress-nginx` 及其关联资源的方法[^4]。实际项目开发过程中可根据需求灵活扩展这些方案。
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值