前言
上篇文章中我应用了ip2region
获取到了ip归属地,然而我发现我的框架next.js
通过k8s公布到生产环境之后发现获取的ip是pod的ip而不是实在的外网ip,上面就来谈谈如何解决!
操作
首先我想到的是可能是阿里云ACK本人的问题,于是问了他们客服之前机器人给了上面的解决方案:
ACK容器集群利用Pod如何获取客户端实在IP
ACK容器集群Pod如何获取客户端实在IP?
如果您未应用WAF,且集群是通过SLB裸露的业务,请查看Service的YAML文件,确保externaltrafficpolicy为Local模式,该模式下可获取到客户端实在IP。如果集群是通过Ingress裸露的业务,请查看nginx-ingress-lb的externaltrafficpolicy,确保externaltrafficpolicy为Local模式。如果您应用了WAF,请参见K8s Ingress获取实在IP地址解决。
发现解决不了问题之后,上面是他们客服给的解决方案:
1、查看service中nginx-ingress-lb
内部流量策略是不是Local
发现设置的就是Local,所以通过!
2、设置nginx-configuration
执行上面命令:
kubectl -n kube-system edit cm nginx-configuration
在data中增加上面内容:
compute-full-forwarded-for: "true" forwarded-for-header: "X-Forwarded-For" use-forwarded-headers: "true" enable-real-ip: "true"
设置好即失效,通过!
3、查看deploy无状态的nginx-ingress-controller
日志中展现是不是实在ip
172.22.32.48 - [172.22.32.48] - - [31/Aug/2023:11:49:00 +0800] "GET /api/space/info/urlCategory/zhangwei HTTP/1.1" 200 20188 "-" "axios/1.5.0" 320 0.059 [seaurl-testapi-seaurl-gatewayserver-svc-7777] 172.22.32.57:7777 20188 0.059 200 9c6a2589d7926d266abe56b6e4b38488 testapi.seaurl.com []114.222.247.210 - [114.222.247.210] - - [31/Aug/2023:11:49:01 +0800] "GET /api/space/crud/urlCategory/zhangwei/categoryTreeList HTTP/2.0" 200 20188 "https://test.seaurl.com/" "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/116.0.0.0 Safari/537.36" 56 0.027 [seaurl-testapi-seaurl-gatewayserver-svc-7777] 172.22.32.57:7777 20188 0.027 200 e165866b16394694c332e82aa47de562 testapi.seaurl.com []
通过下面显示,发现每次应用的pod的ip都是axios申请的,实在的都是客户端浏览器申请的,这是为啥呢???
剖析
于是我就开始剖析起造成的起因,因为客户端浏览器发动的申请就是实在的ip,服务端next.js中的axios发动的申请就是pod的ip,再联合之前next.js遇到的cookie问题,我终于破案了!
神思之蛙始终摸你肚子!
浏览器申请(实在ip)->nginx-ingress-controller->spring cloud gateway
next.js所在的pod中的axios申请(pod ip)->nginx-ingress-controller->spring cloud gateway
剖析问题:
也就是说浏览器申请的X-Forwarded-For
申请头应用的就是内部实在的ip,而next.js所在的pod的axios发动的申请头中我没有设置X-Forwarded-For
,所以它默认应用的是pod的ip。
解决:
只有在next.js中设置axios申请头X-Forwarded-For
即可,如下所示:
export const getServerSideProps = wrapper.getServerSideProps(store => async (ctx) => { const ip = ctx.req.headers['x-forwarded-for'] || ctx.req.connection.remoteAddress; axios.defaults.headers.cookie = ctx.req.headers.cookie || null axios.defaults.headers['X-Forwarded-For'] = ip
这样实在的ip就会设置到axios申请头中,完满解决!!!
IP属地:中国|0|江苏省|南京市|电信
总结
1、首先排除是阿里云ACK的问题
2、剖析后才晓得是next.js应用axios导致的,批改申请头即可解决。