service使用local模式仍无法获取到访问端源ip问题总结
问题简介
根据kubernetes官方文档所述:
Kubernetes 提供了一个特性来保留客户端的源 IP 地址。设置
service.spec.externalTrafficPolicy
的值为Local
,请求就只会被代理到本地 endpoints 而不会被转发到其它节点。这样就保留了最初的源 IP 地址。如果没有本地 endpoints,发送到这个节点的数据包将会被丢弃。这样在应用到数据包的任何包处理规则下,你都能依赖这个正确的 source-ip 使数据包通过并到达 endpoint。参考文档:https://kubernetes.io/zh/docs/tutorials/services/source-ip/#type-nodeport-%E7%B1%BB%E5%9E%8B-services-%E7%9A%84-source-ip
我们将service的参数service.spec.externalTrafficPolicy
的值设置为 Local
,以保证我们部署的nginx可以正确看到源地址。但是在使用中发现,nginx日志中记录的地址,均非源地址,而是pod所在节点网桥的地址。
环境概览
ip地址信息如下:
podip:172.18.0.97
pod所在节点ip:10.0.1.37
有如下两个资源:
-
Deployment:nginx
使用官方默认镜像,无任何特殊配置,yaml如下,以略去非必要项
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
apiVersion: apps/v1 kind: Deployment metadata: name: nginx spec: replicas: 1 selector: matchLabels: k8s-app: nginx template: metadata: labels: k8s-app: nginx spec: containers: - image: nginx name: nginx
-
Service:nginx-svc
配置如下,已略去非必要内容,并已经开启
externalTrafficPolicy: Local
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
apiVersion: v1 kind: Service metadata: name: nginx-svc spec: clusterIP: 172.18.255.31 externalTrafficPolicy: Local ports: - name: http nodePort: 30567 port: 80 protocol: TCP targetPort: 80 selector: k8s-app: nginx qcloud-app: nginx type: NodePort
问题复现
通过自己的办公机,对pod所在节点进行ip地址+nodeport端口
方式进行访问测试,结果如下,nginx端看到的访问地址,并不是我办公机公网出口的地址,这个地址经我查询,是pod所在节点网桥上的地址:
问题排查
local模式下,请求就只会被代理到本地 endpoints 而不会被转发到其它节点。故此现象,问题应该是发生在pod所在节点上,应该是节点上有什么iptables规则,导致此问题发生。
在我们的集群上,有使用到ip-masq-agent组件,去控制在何种ip情况下去做SNAT转换,故怀疑是否因此问题导致。
经查询iptables的nat规则发现,节点上的nat规则如下:
但是我们的集群,容器的网络是172.18.0.0/16,这里明显是配置有误的,故查看ip-masq-agent的配置文件,发现这里的配置果然有问题:
修改这里的配置为我们期望的172.18.0.0/16后,等待约一分钟的时间,让configmap进行热更新,更新后,再次查看iptables的规则,已经恢复成我们期望的
修复后验证
修复ip-masq-agent规则后,再次尝试请求nodeip+nodeport进行测试,结果已经正常,nginx获取到的地址正是我办公机网络的出口地址
总结
ip-masq-agent组件会根据配置,决定于哪些ip需要进行nat转换,哪些不需要,本例为错误的配置了相关规则,导致service的local模式无法生效