写点什么

TiDB 如何在 LVS FULL NAT 模式下显示客户端真实 IP

  • 2022 年 7 月 11 日
  • 本文字数:3312 字

    阅读完需:约 11 分钟

原文来源:https://tidb.net/blog/1d65166f


【是否原创】是


【首发渠道】TiDB 社区


【正文】


作者:

靳献旗 汽车之家 DBA,TUG 2021 MVA

1. 背景

公司 TiDB 集群前端负载均衡器使用的是 LVS,FULL NAT 模式, 这种模式最大的一个问题是:RealServer 无法获得用户 IP ,即在 TiDB 数据库中无法显示客户端真实 IP,显示的是 LVS 服务器上的一个 IP。很多时候,在排查 TiDB 问题时,需要获取客户端真实 IP,这给我们带来了一定困难。本文简单讲述下如何在 TiDB-Server 端显示客户端真实 IP 的方法和工作原理。

2.FULL NAT 概述

本文主要针对 LVS FULL NAT 场景,所以本节简单介绍下其工作原理、优缺点及解决办法。本文中使用到的 IP 均已脱敏处理。

2.1 工作原理


如图所示,FULLNAT 模式是 NAT 的一种扩展,不仅仅将目的 IP 地址进行替换,同时还将源 IP 地址进行了替换,这样做的好处是将 real server 从 virtual server 的后端网络中解放出来,不再要求与 virtual server 位于同一子网内。工作过程如下:


(1) 当客户端发出一个请求的数据包到达负载均衡器后,负载均衡器会对请求数据包同时做 SNAT 和 DNAT,将请求数据包修改为:{ LVS 出口 IP 地址 192.168.2.101、LVS 端口号、LVS 的 MAC 地址 } -> { 某台 Tidb-Server 的 IP 地址、某台 Tidb-Server 的端口号、某台 Tidb-Server 的 MAC 地址 }。


(2) 这样负载均衡器就可以独立的和真实服务器进行数据包的传送。


(3) 真实服务器收到请求的数据包,返回响应的数据包:{ 某台 Tidb-Server 的 IP 地址、某台 Tidb-Server 的端口号、某台 Tidb-Server 的 MAC 地址 } -> { LVS 的入口 IP 地址、LVS 端口号、LVS 的 MAC 地址 } 。此时在真实服务器上查看 TCP 连接为:DIP -> RIP。


(4) 当返回的数据包到达负载均衡器后,负载均衡器将返回数据包再次同时做 DNAT 和 SNAT。


(5) 负载均衡器返回数据包给客户端。


FULL NAT 模式下报文变化:



说明:


2.2 优缺点

  • 优点

  • 扩展性好,负载均衡器和真实服务器可以跨 VLAN 部署

  • 缺点

  • 真实服务器无法获取客户端真实 IP

2.3 解决办法

针对上一小节中提到的 FULL NAT 模式无法获取客户端真实 IP 的问题有没有解决办法?答案是有。


TOA 名字全称是 tcp option address,是 FULL NAT 模式下能够让后端服务器获取 ClientIP 的一种实现方式,它的基本原理比较简单:


(1) 客户端用户请求数据包到达 LVS 时,LVS 在数据包的 tcp option 中插入 src ip 和 src port 信息


(2) 数据包到达后端服务器(装有 toa 模块)后,应用程序正常调用 getpeername 系统函数来获取连接的源端 IP 地址


(3) 由于在 toa 代码中 hook(修改)了 inet_getname 函数(getpeername 系统调用对应的内核处理函数),该函数会从 tcp option 中获取 LVS 填充的 src 信息


(4) 这样后端服务器应用程序就获取到了真实客户端的 ClientIP,而且对应用程序来说是透明的。

3. 实战

3.1 测试环境

3.2 部署步骤

(1) 升级 TiDB 到 5.0 版本


因为参数 enable-tcp4-only 是从 5.0 开始引入的,因此,如果集群版本低于 5.0 ,需要先升级集群,本文测试使用的版本是 5.1.3。


(2) 开启 enable-tcp4-only


所有 TiDB Server 节点需要开启 enable-tcp4-only,参考步骤如下


a) 编辑集群拓扑文件


tiup cluster edit-config stale_read_test


server_configs:


tidb:


enable-tcp4-only: true     # 添加或者修改这一行配置为 true
复制代码


b) 重新加载配置


tiup cluster reload stale_read_test -R tidb


c) 检查配置是否生效


select * from information_schema.cluster_config where TYPE=‘tidb’ and key=‘enable-tcp4-only’;


参数说明


enable-tcp4-only 从 v5.0 版本开始引入控制是否只监听 TCP4。默认值:false当使用 LVS 为 TiDB 做负载均衡时,可开启此配置项。这是因为 LVS 的 TOA 模块可以通过 TCP4 协议从 TCP 头部信息中解析出客户端的真实 IP。
复制代码


(3) 安装 ip_vs_ca 模块


需要在所有 TiDB Server 服务器上安装 ip_vs_ca 模块


从 git 上 (https://github.com/yubo/ip_vs_ca) 下载安装包 ip_vs_ca-master.zip


yum -y install cmake


unzip ip_vs_ca-master.zip


cd ip_vs_ca-master


cmake .


cd src/


make


insmod ./ip_vs_ca.ko


cp -fr /root/ip_vs_ca-master /usr/local/src/


echo insmod /usr/local/src/ip_vs_ca*/src/ip_vs_ca.ko >> /etc/rc.local


查看计数器和版本信息


cat /proc/net/ip_vs_ca_stats


(4) 测试


客户端通过 LVS VIP 连接到 TiDB 集群后,在 TiDB 端通过 show processlist 查看客户端 IP。

3.3 实际效果

未开启 enable-tcp4-only 的效果


dba@192.168.2.100:4000 : (none) > select * FROM information_schema.cluster_processlist\"G*************************** 1. row ***************************INSTANCE: 192.168.3.1:10080      ID: 15    USER: dba    HOST: 192.168.2.101:5394 #LVS DIP      DB: NULL COMMAND: Query    TIME: 0   STATE: autocommit    INFO: select * FROM information_schema.cluster_processlist  DIGEST: b1e38e59fbbc3e2b35546db5c8053040db989a497ac6cd71ff8dd4394395701a     MEM: 4    DISK: 0TxnStart: 01-19 11:25:30.423(430587964404006913)1 row in set (0.00 sec)
复制代码


开启 enable-tcp4-only 的效果


show processlist;


dba@192.168.2.100:4000 : (none) > select * FROM information_schema.cluster_processlist\"G*************************** 1. row ***************************INSTANCE: 192.168.3.1:10080      ID: 190927    USER: dba    HOST: 192.168.1.1:13557   #客户端真实IP       DB: NULL COMMAND: Query    TIME: 0   STATE: autocommit    INFO: select * FROM information_schema.cluster_processlist  DIGEST: b1e38e59fbbc3e2b35546db5c8053040db989a497ac6cd71ff8dd4394395701a     MEM: 0    DISK: 0TxnStart: 01-19 08:53:36.472(430585575236435969)1 row in set (0.00 sec)
复制代码


慢日志


# Time: 2022-01-19T09:04:18.429228693+08:00# Txn_start_ts: 0# User@Host: dba[dba] @ 192.168.1.1 [192.168.1.1] #客户端真实IP# Conn_ID: 190927# Query_time: 10.00093258# Parse_time: 0.000098847# Compile_time: 0.000132781# Rewrite_time: 0.000073525# Optimize_time: 0.00001867# Wait_TS: 0.000006643# Is_internal: false# Digest: a0adeeb79b71315ac13a77f3f11162106b5ec7b48212cf17c20c754263ab9228# Num_cop_tasks: 0# Prepared: false# Plan_from_cache: false# Plan_from_binding: false# Has_more_results: false# KV_total: 0# PD_total: 0.000004254# Backoff_total: 0# Write_sql_response_total: 0.000003211# Succ: true# Plan: tidb_decode_plan('gQHwVTAJM18zCTAJMQlzbGVlcCgxMCktPkNvbHVtbiMxCTEJdGltZToxMHMsIGxvb3BzOjIsIENvbmN1cnJlbmN5Ok9GRgkwIEJ5dGVzCU4vQQoxCTI1XzQJAVAQcm93czoZQxAuMDTCtRlHIAlOL0EJTi9BCg==')# Plan_digest: a55eaee1d30304ad05500afbbfff1409ce22376e0f062c0d06ff34b8ed9c2b47select sleep(10);
复制代码


general log


[2022/01/19 11:04:42.863 +08:00] [INFO] [session.go:2796] [GENERAL_LOG] [conn=219317] [user=dba@192.168.1.1] [schemaVersion=1007] [txnStartTS=0] [forUpdateTS=0] [isReadConsistency=false] [current_db=db23] [txn_mode=PESSIMISTIC] [sql="select * from t1"]
复制代码


从以上信息可以看到,无论是 show processlist,还是慢日志,还是 general log ,都可以看到客户端真实 IP 地址,为排查问题提供了很大便利。

4. 总结

公司私有云提供统一的 LVS 服务,为了减少维护成本,TiDB 集群统一使用之家云 LVS 作为负载均衡器。由于 LVS FULL NAT 模式的工作原理决定了在 TiDB 端无法看到客户端真实 IP,本文主要讲解了 TiDB 在这种工作模式下如何查看客户端真实 IP 的解决方法,希望能够帮助需要的同学。


参考资料


https://docs.pingcap.com/zh/tidb/v5.1/tidb-configuration-file/


https://github.com/pingcap/tidb/pull/21552


https://www.jianshu.com/p/e770a11481e9


https://github.com/yubo/ip_vs_ca


https://zhuanlan.zhihu.com/p/364703954


https://github.com/alibaba/LVS/tree/master/docs


发布于: 刚刚阅读数: 3
用户头像

TiDB 社区官网:https://tidb.net/ 2021.12.15 加入

TiDB 社区干货传送门是由 TiDB 社区中布道师组委会自发组织的 TiDB 社区优质内容对外宣布的栏目,旨在加深 TiDBer 之间的交流和学习。一起构建有爱、互助、共创共建的 TiDB 社区 https://tidb.net/

评论

发布
暂无评论
TiDB 如何在 LVS FULL NAT 模式下显示客户端真实 IP_实践案例_TiDB 社区干货传送门_InfoQ写作社区