摘要:客户端和容器服务器之间可能存在多种不同形式的代理服务器,那容器中如何获取到客户端真实的源ip呢?
k8s已经成为当今容器化的标准,人们在享受容器带来的高效与便利的同时,也遇到一些烦恼:客户端和容器服务器之间可能存在多种不同形式的代理服务器,那容器中如何获取到客户端真实的源ip呢?下面我们就几种场景类型如何能获取到源ip进行讨论。
原理介绍:
四层转发:
Nodeport:nodeport访问方式,是将容器端口映射到节点端口,如果“服务亲和”选择“集群级别”需要经过一次服务转发,无法实现获取客户端源ip,而“节点模式”不经过转发,可以获取客户端源ip。
ELB:ELB访问方式,是通过华为云ELB产品来实现负载均衡,“服务亲和”也是需要选择“节点级别”,其中“共享型”ELB需要在节点安装TOA插件,而“独享型”ELB默认透传源ip,不需要安装TOA插件。
七层转发:
Ingress:应用在七层访问时,客户端源ip默认保存在HTTP头部的“X-Forwarded-For”字段,无需做其他操作。
具体操作:
一、负载均衡 ( LoadBalancer )
负载均衡( LoadBalancer )的Service模式下,支持容器中获取源IP需要满足以下前提条件:
1. 服务亲和选择“节点级别”而不是“集群级别”。
2. 在pod所在的节点安装TOA插件。(“独享型”ELB无需进行以下操作)
安装TOA插件步骤如下:
1) 准备编译环境:
执行如下命令,安装gcc编译器。
]# yum install gcc
执行如下命令,安装make工具。
]# yum install make
2)编译内核模块
a) 下载TOA内核模块源代码。
]# wget https://github.com/Huawei/TCP_option_address/archive/master.zip b) 执行如下命令,进入源码目录,编译模块。
]# unzip master.zip
]# cd TCP_option_address-master/src/
]# make
编译过程未提示warning或者error,说明编译成功,检查当前目录下是否已经生成toa.ko文件。
说明:如果报错提示“config_retpoline=y but not supported by the compiler, Compiler update recommended”,表明gcc版本过老,建议将gcc升级为较新版本。
3)加载内核模块
执行如下命令,加载内核模块。
]# insmod toa.ko
执行如下命令,验证模块加载情况,查看内核输出信息。
]# dmesg | grep TOA
若提示信息包含“TOA: toa loaded”,说明内核模块加载成功。
4) 自动加载内核模块
为了使TOA内核模块在系统启动时生效,可以将加载TOA内核模块的命令加到客户的启动脚本中。
在“/etc/sysconfig/modules/”目录下新建toa.modules文件。该文件包含了TOA内核模块的加载脚本,请参考如下示例:
#!/bin/sh
/sbin/modinfo -F filename /root/toa/toa.ko > /dev/null 2>&1
if [ $? -eq 0 ]; then
/sbin/insmod /root/TCP_option_address-master/src/toa.ko
fi
注意:其中“/root/TCP_option_address-master/src/toa.ko”为TOA内核模块文件的路径,客户需要将其替换为自己编译的TOA内核模块路径。
执行以下命令,为toa.modules启动脚本添加可执行权限。
]# chmod +x /etc/sysconfig/modules/toa.modules
这种情况下可以从四层负载均衡上获取到客户端的源IP(可以通过netstat查看)。
测试要点:这种情况下可以使用netstat看到客户端连接到POD的IP地址。
二、节点访问 ( NodePort )
节点访问(NodePort)类型的Service的服务亲和选择“节点级别”而不是“集群级别”,即Service的 spec.externalTrafficPolicy 需要设置为 Local。
图1 服务亲和选择节点级别
三、七层负载均衡(Ingress)
七层负载均衡的模式下,不能在四层负载均衡上获取客户端IP(不能通过netstat查看客户端IP),需要对应用服务器进行配置,然后通过七层负载均衡的http头中的x-forward-for获取。
真实的来访者IP会被负载均衡放在HTTP头部的X-Forwarded-For字段,格式如下:
X-Forwarded-For: 来访者真实IP, 代理服务器1-IP, 代理服务器2-IP, ...
测试要点:从容器中获取http请求头”x-forward-for”,获取的IP为客户端的IP。