登录
/
注册
首页
论坛
其它
首页
科技
业界
安全
程序
广播
Follow
关于
导读
排行榜
资讯
发帖说明
登录
/
注册
账号
自动登录
找回密码
密码
登录
立即注册
搜索
搜索
关闭
CSDN热搜
程序园
精品问答
技术交流
资源下载
本版
帖子
用户
软件
问答
教程
代码
写记录
写博客
小组
VIP申请
VIP网盘
网盘
联系我们
发帖说明
道具
勋章
任务
淘帖
动态
分享
留言板
导读
设置
我的收藏
退出
腾讯QQ
微信登录
返回列表
首页
›
业界区
›
业界
›
追踪链路--使用iptables/ipvs来记录后端pod真实ip ...
追踪链路--使用iptables/ipvs来记录后端pod真实ip
[ 复制链接 ]
硫辨姥
2 小时前
程序园永久vip申请,500美金$,无限下载程序园所有程序/软件/数据/等
前言
之前使用nginx-ingress-controller来记录后端真实ip,但是有位老哥说了,我没有用nginx-ingress-controller,而是用的原生nginx,这时候又当如何记录后端真实ip的问题呢
环境准备
nginx:
upstream backend_ups {
server backend-service:10000;
}
server {
listen 80;
listen [::]:80;
server_name localhost;
location /test {
proxy_pass http://backend_ups;
}
}
复制代码
apiVersion: apps/v1
kind: Deployment
metadata:
name: nginx-test
namespace: default
spec:
selector:
matchLabels:
app: nginx-test
template:
metadata:
labels:
app: nginx-test
spec:
containers:
- image: registry.cn-beijing.aliyuncs.com/wilsonchai/nginx:latest
imagePullPolicy: IfNotPresent
name: nginx-test
ports:
- containerPort: 80
protocol: TCP
volumeMounts:
- mountPath: /etc/nginx/conf.d/default.conf
name: nginx-config
subPath: default.conf
- mountPath: /etc/nginx/nginx.conf
name: nginx-base-config
subPath: nginx.conf
volumes:
- configMap:
defaultMode: 420
name: nginx-config
name: nginx-config
- configMap:
defaultMode: 420
name: nginx-base-config
name: nginx-base-config
---
apiVersion: v1
kind: Service
metadata:
name: nginx-test
namespace: default
spec:
ports:
- port: 80
protocol: TCP
targetPort: 80
selector:
app: nginx-test
type: NodePort
复制代码
backend:
apiVersion: apps/v1
kind: Deployment
metadata:
name: backend
namespace: default
spec:
replicas: 2
selector:
matchLabels:
app: backend
template:
metadata:
labels:
app: backend
spec:
containers:
- image: backend-service:v1
imagePullPolicy: Never
name: backend
ports:
- containerPort: 10000
protocol: TCP
---
apiVersion: v1
kind: Service
metadata:
name: backend-service
namespace: default
spec:
ports:
- port: 10000
protocol: TCP
targetPort: 10000
selector:
app: backend
type: ClusterIP
复制代码
部署完毕,检查一下
▶ kubectl get pod -owide
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
backend-6d4cdd4c68-mqzgj 1/1 Running 0 6m3s 10.244.0.64 wilson <none> <none>
backend-6d4cdd4c68-qjp9m 1/1 Running 0 6m5s 10.244.0.66 wilson <none> <none>
nginx-test-b9bcf66d7-2phvh 1/1 Running 0 6m20s 10.244.0.67 wilson <none> <none>
复制代码
▶ kubectl get svc
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
backend-service ClusterIP 10.105.148.194 <none> 10000/TCP 5m
nginx-test NodePort 10.110.71.55 <none> 80:30785/TCP 5m2s
复制代码
现在的架构大概是这个样子:
尝试访问一下nginx:
▶ curl 127.0.0.1:30785/test
i am backend in backend-6d4cdd4c68-qjp9m
复制代码
已经反向代理到后端,再看看nginx日志
10.244.0.1 - - [04/Dec/2025:07:27:17 +0000] "GET /test HTTP/1.1" 200 10.105.148.194:10000 40 "-" "curl/7.81.0" "-"
复制代码
不出意外的,其中10.105.148.194是backend-service的ip,并非是pod ip
在nginx配置中,upstream的配置是backend-service,使用了k8s的service做了负载均衡,所以在nginx这层无论如何也是拿不到后端pod的ip的
现在需要在真正负载均衡那一层把日志打开,就可以看到转发的real server了
iptables
如果用的是iptables做的转发,那就需要复习一下iptables的转发原理了
当包进入网卡之后,就进入了PREROUTING
其次进入路由,根据目的地址,就分为两个部分:
进入本机,走INPUT,随后进入更高层的应用程序处理
非本机的包,进入FORWARD,再进入POSTROUTING
规则探索
我们来看看具体的规则:
首先先检查PREROUTING,就发现了k8s添加的链表,KUBE-SERVICES
▶ sudo iptables -L PREROUTING -t nat
Chain PREROUTING (policy ACCEPT)
target prot opt source destination
KUBE-SERVICES all -- anywhere anywhere /* kubernetes service portals */
...
复制代码
继续检查KUBE-SERVICES,发现了很多service的规则
▶ sudo iptables -L KUBE-SERVICES -t nat
Chain KUBE-SERVICES (2 references)
target prot opt source destination
KUBE-SVC-W67AXLFK7VEUVN6G tcp -- anywhere 10.110.71.55 /* default/nginx-test cluster IP */
KUBE-SVC-EDNDUDH2C75GIR6O tcp -- anywhere 10.98.224.124 /* ingress-nginx/ingress-nginx-controller:https cluster IP */
KUBE-SVC-ERIFXISQEP7F7OF4 tcp -- anywhere 10.96.0.10 /* kube-system/kube-dns:dns-tcp cluster IP */
KUBE-SVC-JD5MR3NA4I4DYORP tcp -- anywhere 10.96.0.10 /* kube-system/kube-dns:metrics cluster IP */
KUBE-SVC-ZZAJ2COS27FT6J6V tcp -- anywhere 10.105.148.194 /* default/backend-service cluster IP */
KUBE-SVC-NPX46M4PTMTKRN6Y tcp -- anywhere 10.96.0.1 /* default/kubernetes:https cluster IP */
KUBE-SVC-CG5I4G2RS3ZVWGLK tcp -- anywhere 10.98.224.124 /* ingress-nginx/ingress-nginx-controller:http cluster IP */
KUBE-SVC-EZYNCFY2F7N6OQA2 tcp -- anywhere 10.101.164.9 /* ingress-nginx/ingress-nginx-controller-admission:https-webhook cluster IP */
KUBE-SVC-TCOU7JCQXEZGVUNU udp -- anywhere 10.96.0.10 /* kube-system/kube-dns:dns cluster IP */
复制代码
找到目标service:backend-service对应的链规则KUBE-SVC-ZZAJ2COS27FT6J6V,继续检查
▶ sudo iptables -L KUBE-SVC-ZZAJ2COS27FT6J6V -t nat
Chain KUBE-SVC-ZZAJ2COS27FT6J6V (1 references)
target prot opt source destination
KUBE-MARK-MASQ tcp -- !10.244.0.0/16 10.105.148.194 /* default/backend-service cluster IP */
KUBE-SEP-GYMSSX4TMUPRH3OB all -- anywhere anywhere /* default/backend-service -> 10.244.0.64:10000 */ statistic mode random probability 0.50000000000
KUBE-SEP-EZWMSI6QFXP3WRHV all -- anywhere anywhere /* default/backend-service -> 10.244.0.66:10000 */
复制代码
这里已经有明显的结论了,有2条链,对应的了两个pod,再深入检查其中一条链,KUBE-SEP-GYMSSX4TMUPRH3OB
▶ sudo iptables -L KUBE-SEP-GYMSSX4TMUPRH3OB -t nat
Chain KUBE-SEP-GYMSSX4TMUPRH3OB (1 references)
target prot opt source destination
KUBE-MARK-MASQ all -- 10.244.0.64 anywhere /* default/backend-service */
DNAT tcp -- anywhere anywhere /* default/backend-service */ tcp to:10.244.0.64:10000
复制代码
从这里的规则能够知晓,进入KUBE-SEP-GYMSSX4TMUPRH3OB,会进行DNAT转换,把目标的ip转换成:10.244.0.64;那同理可知,另外一条链会将目标ip转换成:10.244.0.66。所以我们只需要在这个地方加入日志记录,就可以 追踪对端的ip是哪个了
sudo iptables -t nat -I KUBE-SEP-GYMSSX4TMUPRH3OB 1 -j LOG --log-prefix "backend-service-pod: " --log-level 4
sudo iptables -t nat -I KUBE-SEP-EZWMSI6QFXP3WRHV 1 -j LOG --log-prefix "backend-service-pod: " --log-level 4
复制代码
来看下整体的效果
▶ sudo iptables -L KUBE-SEP-GYMSSX4TMUPRH3OB -t nat
Chain KUBE-SEP-GYMSSX4TMUPRH3OB (1 references)
target prot opt source destination
LOG all -- anywhere anywhere LOG level warning prefix "backend-service-pod: "
KUBE-MARK-MASQ all -- 10.244.0.64 anywhere /* default/backend-service */
DNAT tcp -- anywhere anywhere /* default/backend-service */ tcp to:10.244.0.64:10000
wilson.chai-ubuntu [ 17:18:03 ] /usr/src/trojan
▶ sudo iptables -L KUBE-SEP-EZWMSI6QFXP3WRHV -t nat
Chain KUBE-SEP-EZWMSI6QFXP3WRHV (1 references)
target prot opt source destination
LOG all -- anywhere anywhere LOG level warning prefix "backend-service-pod: "
KUBE-MARK-MASQ all -- 10.244.0.66 anywhere /* default/backend-service */
DNAT tcp -- anywhere anywhere /* default/backend-service */ tcp to:10.244.0.66:10000
复制代码
都已经做了对应的日志记录了,开始测试
请求nginx:curl 127.0.0.1:30785/test
查看日志
tail -f /var/log/syslog | grep backend-service
Dec 4 17:17:30 wilson kernel: [109258.569426] backend-service-pod: IN=cni0 OUT= PHYSIN=veth1dc60dd3 MAC=76:d8:f3:a1:f8:1b:a2:79:4b:23:58:d8:08:00 SRC=10.244.0.70 DST=10.105.148.194 LEN=60 TOS=0x00 PREC=0x00 TTL=64 ID=64486 DF PROTO=TCP SPT=51596 DPT=10000 WINDOW=64860 RES=0x00 SYN URGP=0
复制代码
什么?!为什么DST依然显示的是10.105.148.194
问题解决
再次查看链规则,在日志记录的时候,还没有做DNAT,所以DST依然是service ip,但是如果将LOG规则写在DNAT之后,那DNAT匹配之后就不会再进入LOG,那依然不能记录
▶ sudo iptables -L KUBE-SEP-GYMSSX4TMUPRH3OB -t nat
Chain KUBE-SEP-GYMSSX4TMUPRH3OB (1 references)
target prot opt source destination
LOG all -- anywhere anywhere LOG level warning prefix "backend-service-pod: "
KUBE-MARK-MASQ all -- 10.244.0.64 anywhere /* default/backend-service */
DNAT tcp -- anywhere anywhere /* default/backend-service */ tcp to:10.244.0.64:10000
复制代码
还是要回到iptables的工作原理,我们的请求先进入PREROUTING链,再进入FORWARD链,最后进入POSTROUTING链,请求进入在PREROUTING中已经进行了DNAT的转换,那其实就可以在后面两个链表中记录日志。这里选择在POSTROUTING中记录日志
iptables -t nat -I POSTROUTING -p tcp -d 10.244.0.64 -j LOG --log-prefix "backend-service: "
iptables -t nat -I POSTROUTING -p tcp -d 10.244.0.66 -j LOG --log-prefix "backend-service: "
复制代码
▶ sudo iptables -L POSTROUTING -t nat
Chain POSTROUTING (policy ACCEPT)
target prot opt source destination
LOG tcp -- anywhere 10.244.0.66 LOG level warning prefix "backend-service: "
LOG tcp -- anywhere 10.244.0.64 LOG level warning prefix "backend-service: "
...
复制代码
在测试一次
Dec 4 17:33:23 wilson kernel: [110211.770728] backend-service: IN= OUT=cni0 PHYSIN=veth1dc60dd3 PHYSOUT=vetha515043b SRC=10.244.0.70 DST=10.244.0.64 LEN=60 TOS=0x00 PREC=0x00 TTL=64 ID=59709 DF PROTO=TCP SPT=33454 DPT=10000 WINDOW=64860 RES=0x00 SYN URGP=0
Dec 4 17:33:24 wilson kernel: [110213.141975] backend-service: IN= OUT=cni0 PHYSIN=veth1dc60dd3 PHYSOUT=veth0a8a2dd3 SRC=10.244.0.70 DST=10.244.0.66 LEN=60 TOS=0x00 PREC=0x00 TTL=64 ID=54719 DF PROTO=TCP SPT=33468 DPT=10000 WINDOW=64860 RES=0x00 SYN URGP=0
复制代码
iptables小结
这个测试验证了,用linux的iptables规则,依然可以追踪每一条请求的链路,并且回顾了iptables的工作原理,以及探索了k8s基于iptables的转发规则的原理,但是这里有几个问题
一旦pod的ip变化,那日志规则也要改变,这在pod随时变化的环境中,需要大量精力维护
新增k8s node 节点,依然需要手动添加规则,这也需要大量维护
这个方法涉及到了根本的转发规则,一旦处理不当,错误的增删改,将导致不可预知的风险,甚至集群由此崩溃
所以这种方法是不太能够在生产环境当中使用的
在这里做了详细的分析,只是为了证明我们的思路没错,只要在负载均衡那一层进行日志记录,就能拿到real server
ipvs
ipvs 是内核转发,并不会记录访问日志,但是依然可以使用 iptables的方法来记录,就是在POSTROUTING链上记录日志
如果k8s的转发模式是ipvs,并不意味着只需要用ipvs就可以完成转发工作,它需要ipvs与iptables共同协作才能完成
内置于Linux内核中的核心技术模块,它工作在Netfilter框架的INPUT之前的hook点
当请求的目标ip是ipvs的vip时,ipvs就会接入工作,将数据包“劫持”过来,然后进行规则匹配并修改,比如进行DNAT
TCP 10.105.148.194:10000 rr
-> 10.244.0.73:10000 Masq 1 0 0
-> 10.244.0.74:10000 Masq 1 0 0
复制代码
如果修改后的目标ip就是本机ip,那ipvs就直接交给上层应用程序处理
如果修改后的目标ip不是本机ip,那该数据包会重新进入路由,然后通过FORWARD,POSTROUTING转发出去
小结
本文复习了linux传统的知识点,iptables与ipvs的工作原理,
并且详细讨论了,如果不加任何插件的情况下,使用操作系统自带的追踪方式查看后端真实的pod,但是这些都不适合在生产环境使用,因为它太底层了,日常的操作不应该去操作底层的配置,就算要用,也应该做一些自动化的脚 本或者插件封装一次才能使用
在不使用nginx-ingress-controller,或者我想记录服务间转发的真实pod,有没有可以直接使用的插件或者组件帮我们完成这个工作呢,答案肯定是有的,那这就是下一期的内容,敬请期待
联系我
联系我,做深入的交流
至此,本文结束
在下才疏学浅,有撒汤漏水的,请各位不吝赐教...
来源:程序园用户自行投稿发布,如果侵权,请联系站长删除
免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!
追踪
链路
使用
iptables
ipvs
相关帖子
使用i2s遇到的问题
使用_mm_stream_si128加速 Memory-Bound
一步一步学习使用LiveBindings(15)TListView进阶使用
VUE中使用AXIOS包装API代理
K8S 中使用 YAML 安装 ECK
OpenCVSharp:学习连通性检测的使用
如何使用 vxe-gantt table 甘特图来实现多个维度视图展示
记录 Windows系统开启hyper-v ,部分端口被保留,导致端口不能使用而报错的问题
Claude Code 使用 Skills
如何使用DashVector的多向量检索
回复
使用道具
举报
提升卡
置顶卡
沉默卡
喧嚣卡
变色卡
千斤顶
照妖镜
相关推荐
安全
使用i2s遇到的问题
1
378
肇默步
2025-12-11
业界
使用_mm_stream_si128加速 Memory-Bound
1
293
卓卞恻
2025-12-11
业界
一步一步学习使用LiveBindings(15)TListView进阶使用
0
296
徙办
2025-12-12
安全
VUE中使用AXIOS包装API代理
1
537
峰邑
2025-12-12
业界
K8S 中使用 YAML 安装 ECK
0
742
全跺俚
2025-12-12
业界
OpenCVSharp:学习连通性检测的使用
0
167
颜清华
2025-12-13
代码
如何使用 vxe-gantt table 甘特图来实现多个维度视图展示
1
794
晚能
2025-12-13
安全
记录 Windows系统开启hyper-v ,部分端口被保留,导致端口不能使用而报错的问题
0
202
溜椎干
2025-12-15
安全
Claude Code 使用 Skills
0
219
王妍芳
2025-12-16
业界
如何使用DashVector的多向量检索
0
248
别萧玉
2025-12-16
高级模式
B
Color
Image
Link
Quote
Code
Smilies
您需要登录后才可以回帖
登录
|
立即注册
回复
本版积分规则
回帖并转播
回帖后跳转到最后一页
签约作者
程序园优秀签约作者
发帖
硫辨姥
2 小时前
关注
0
粉丝关注
22
主题发布
板块介绍填写区域,请于后台编辑
财富榜{圆}
3934307807
991124
anyue1937
9994893
kk14977
6845358
4
xiangqian
638210
5
韶又彤
9997
6
宋子
9983
7
闰咄阅
9993
8
刎唇
9993
9
俞瑛瑶
9998
10
蓬森莉
9951
查看更多
今日好文热榜
278
上下文协议(MCP)Java SDK 指南
691
Mac办公效率翻倍?Charmstone教你玩转多任
769
深耕上海14年,专业防水补漏:如何为厂房、
822
【A】字符串
456
一个完全由大模型AI Coding开发而成的程序
695
【Ubuntu】Ubuntu+VScode+ESP-IDF 的环境搭
656
60 秒出高质量科研图!Gemini+DeepSeek 绘
774
追踪链路--使用iptables/ipvs来记录后端pod
157
【译】初探 Visual Studio 2026 全新的用户
319
建筑渗漏治理的标准化实践:基于上海芮生建
50
Aspire 13:从.NET 编排工具到真正的多语言
997
用 .NET 最小化 API 构建高性能 API
396
VonaJS是如何做到文件级别精确HMR(热更新)
388
PHP 值对象实战指南:避免原始类型偏执
98
北京上门收酒机构排行|3家靠谱之选,卖酒
921
好拼|免费在线拼图工具又收到赞助啦
481
数据点的“社交距离”:衡量它们之间的相似
721
告别“草率编程”:Vibe Engineering 如何
10
字符串匹配算法
343
监听小工具-股票监控神奇九转分钟线信号触