通常,当 Kubernetes 集群内的客户端连接到服务的时候,是支持服务的 Pod 可以获取到客户端的 IP 地址的,但是,当通过节点端口接收到连接时,由于对数据包执行了源网络地址转换(SNAT),因此数据包的源 IP 地址会发生变化,后端的 Pod 无法看到实际的客户端 IP,对于某些应用来说是个问题,比如,nginx 的请求日志就无法获取准确的客户端访问 IP 了,比如下面我们的应用:

apiVersion: apps/v1kind: Deploymentmetadata:  name: nginxspec:  replicas: 3  selector:    matchLabels:      app: nginx  template:    metadata:      labels:        app: nginx    spec:      containers:      - name: nginx        image: nginx:1.7.9        ports:        - containerPort: 80---apiVersion: v1kind: Servicemetadata:  name: nginxspec:  selector:    app: nginx  type: NodePort  ports:  - protocol: TCP    port: 80    targetPort: 80

直接创建后可以查看 nginx 服务被自动分配了一个 32761 的 NodePort 端口:

$ kubectl get svcNAME         TYPE        CLUSTER-IP       EXTERNAL-IP   PORT(S)        AGEkubernetes   ClusterIP   10.96.0.1        <none>        443/TCP        28dnginx        NodePort    10.106.190.194   <none>        80:32761/TCP   48m$ kubectl get pods -o wideNAME                              READY   STATUS    RESTARTS   AGE     IP             NODE         NOMINATED NODE   READINESS GATESnginx-54f57cf6bf-nwtjp            1/1     Running   0          3m      10.244.3.15    ydzs-node3   <none>           <none>nginx-54f57cf6bf-ptvgs            1/1     Running   0          2m59s   10.244.2.13    ydzs-node2   <none>           <none>nginx-54f57cf6bf-xhs8g            1/1     Running   0          2m59s   10.244.1.16    ydzs-node1   <none>           <none>

我们可以看到这个3个 Pod 被分配到了 3 个不同的节点,这个时候我们通过 master 节点的 NodePort 端口来访问下我们的服务,因为我这里只有 master 节点可以访问外网,这个时候我们查看 nginx 的 Pod 日志可以看到其中获取到的 clientIP 是 10.151.30.11,其实是 master 节点的内网 IP,并不是我们期望的真正的浏览器端访问的 IP 地址:

$ kubectl logs -f nginx-54f57cf6bf-xhs8g10.151.30.11 - - [07/Dec/2019:16:44:38 +0800] "GET / HTTP/1.1" 200 612 "-" "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_5) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/78.0.3904.108 Safari/537.36" "-"

这个是因为我们 master 节点上并没有对应的 Pod,所以通过 master 节点去访问应用的时候必然需要额外的网络跳转才能到达其他节点上 Pod,在跳转过程中由于对数据包进行了 SNAT,所以看到的是 master 节点的 IP。这个时候我们可以在 Service 设置 externalTrafficPolicy 来减少网络跳数:

spec:  externalTrafficPolicy: Local

如果 Service 中配置了 externalTrafficPolicy=Local,并且通过服务的节点端口来打开外部连接,则 Service 会代理到本地运行的 Pod,如果本地没有本地 Pod 存在,则连接将挂起,比如我们这里设置上该字段更新,这个时候我们去通过 master 节点的 NodePort 访问应用是访问不到的,因为 master 节点上并没有对应的 Pod 运行,所以需要确保负载均衡器将连接转发给至少具有一个 Pod 的节点。

但是需要注意的是使用这个参数有一个缺点,通常情况下,请求都是均匀分布在所有 Pod 上的,但是使用了这个配置的话,情况就有可能不一样了。比如我们有两个节点上运行了 3 个 Pod,假如节点 A 运行一个 Pod,节点 B 运行两个 Pod,如果负载均衡器在两个节点间均衡分布连接,则节点 A 上的 Pod 将接收到所有请求的 50%,但节点 B 上的两个 Pod 每个就只接收 25% 。

由于增加了externalTrafficPolicy: Local这个配置后,接收请求的节点和目标 Pod 都在一个节点上,所以没有额外的网络跳转(不执行 SNAT),所以就可以拿到正确的客户端 IP,如下所示我们把 Pod 都固定到 master 节点上:

apiVersion: apps/v1kind: Deploymentmetadata:  name:  nginxspec:  replicas: 3  selector:    matchLabels:      app: nginx  template:    metadata:      labels:        app: nginx    spec:      tolerations:      - operator: "Exists"      nodeSelector:        kubernetes.io/hostname: ydzs-master      containers:      - name: nginx        image: nginx:1.7.9        ports:        - containerPort: 80---apiVersion: v1kind: Servicemetadata:  name: nginxspec: externalTrafficPolicy: Local  selector:    app: nginx  type: NodePort  ports:  - protocol: TCP    port: 80    targetPort: 80

更新服务后,然后再通过 NodePort 访问服务可以看到拿到的就是正确的客户端 IP 地址了:

$ kubectl logs -f nginx-ddc8f997b-ptb7b182.149.166.11 - - [07/Dec/2019:17:03:43 +0800] "GET / HTTP/1.1" 200 612 "-" "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_5) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/78.0.3904.108 Safari/537.36" "-"

K8S 进阶训练营,点击下方图片了解详情

获取客户端ip_获取客户端访问真实IP相关推荐

  1. php 获取用户访问真实IP方法

    /*** 获取客户端IP地址* @param int $type 返回类型 0 返回IP地址 1 返回IPV4地址数字* @param bool $adv 是否进行高级模式获取(有可能被伪装)* @r ...

  2. JAVA如何获取访问真实IP地址?

    解决方法: 获取请求主机IP地址,如果通过代理进来,则透过防火墙获取真实IP地址,如果没有代理,则获取真实ip public static String getIp(HttpServletReques ...

  3. C#获取本机上所有网络接口及真实IP地址信息

    下面显示了如何获取本机上所有网络接口及IP地址的相关信息 它们层次关联为: 一个本机可以有多个网络接口,这些接口包括实际接口与虚拟接口. 每个网络接口可以得到多个IP地址,可能是IPV4也可能是IPV ...

  4. WordPress 使用 CDN 后获取访客真实 IP

    WordPress 往数据库存 IP 的时候似乎用的是 REMOTE_ADDR,这样一来数据库里面的评论信息就全是从各个 CDN 服务器来的 IP. 在 wp-config.php 文件中增加下面代码 ...

  5. 绕过CDN寻找真实IP的8种方法

    正常情况下,通过cmd命令可以快速找到域名对应IP,最常见的命令如ping.nslookup.但很多站点出于用户体验和安全的角度,使用CDN加速,将域名解析到CDN,这时候就需要绕过CDN来查找真实I ...

  6. python获取客户端ip_各种脚本语言获取客户端真实IP的方法

    各种语言获取客户端真是ip的方法 1.PHP脚本获取客户端真实ip的方法 整体思路:需要依次检查HTTP_CLIENT_IP.HTTP_X_FORWARDED_FOR.REMOTE_ADDR这三个是否 ...

  7. 获取客户端真实IP地址

    Java-Web获取客户端真实IP: 发生的场景:服务器端接收客户端请求的时候,一般需要进行签名验证,客户端IP限定等情况,在进行客户端IP限定的时候,需要首先获取该真实的IP. 一般分为两种情况: ...

  8. nginx多层反向代理获取客户端真实ip

    访问路径: 用户 --> www.chinasoft.cn(nginx反向代理) --> www.chinasoft.com(nginx反向代理) --> python服务端程序经过 ...

  9. 如何获取客户端的真实IP

    原文地址:http://blog.csdn.net/zhangyaoming2004/article/details/6792695 问题引出: <hr/> 在JSP里,获取客户端的IP地 ...

最新文章

  1. Zabbix监控MongoDB
  2. mac命令行用sublime,vscode,atom打开目录或文件的方法
  3. JS、JQuery和ExtJs的跨域处理
  4. containers文件夹可以删除吗_电脑进行C盘清理,appdata文件夹可以删除吗?
  5. 在CentOS上安装ZooKeeper集群
  6. python办公自动化博客_自动化办公 Python 操控 Word
  7. 一篇关于兼容问题的基础总结
  8. 幼小衔接语言教案上c册_关于幼小衔接,这里有你最想要的解答
  9. C++_IO类型_文件输入输出流_字符串流
  10. 时下超火的在线教育移动应用UI套件设计素材
  11. 关于如何在Android、Java等非微软平台上建立高信任的SharePoint应用程序
  12. 大数据分析平台的作用有什么
  13. 深度学习TF—12.Auto-Encoders(AE)与Varational Auto Encoder(VAE)实战
  14. Linux中DHCP主配置文件解析
  15. LVM 逻辑卷管理(原理概念篇)
  16. Java项目实战--健康管理系统设计实现【Springboot+mybatis+layui等实现】
  17. Flash遮罩做地球旋转效果
  18. LoadRunner教程06:录制测试脚本
  19. 访问网络计算机提示0 80070035,win7访问局域网共享文件出现 0x80070035错误的解决办法...
  20. python创建工作簿_【Python操作Excel】02_操作工作簿与工作表

热门文章

  1. HTTP Error: 413 Request Entity Too Large的解决
  2. AngularJS+Satellizer+Node.js+MongoDB-Instagram-01
  3. 利用python os模块搜索指定目录下包含指定字符的文件
  4. Java读取word中表格
  5. Excel VBA 入门(零)
  6. 【译】使用 CocoaPods 模块化iOS应用
  7. C++实践笔记(四)----AVL树的简单实现
  8. shell脚本实现一个彩色进度条
  9. Retrofit使用
  10. js 操作java对象_js对象复制