前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >访问ingress nginx出现400报错

访问ingress nginx出现400报错

作者头像
SRE运维实践
发布2024-07-12 16:31:58
2510
发布2024-07-12 16:31:58
举报
文章被收录于专栏:SRE运维实践

序言

在k8s中,使用的比较多就是ingress nginx了,如果你不仔细看一些配置信息,那么就会出现一些意想不到的报错。

背景:当把nginx里面的服务迁移到ingress nginx之后,访问出现了400报错,如果是你,你会怎么来排查?

400报错排查

1 收到问题

当迁移完成之后,就有人报障说,访问全部出现出现400 bad request,第一时间看到这个状态码,那么就认为是客户端的问题,毕竟4xx的报错都是客户端的问题。

先查看了一个error log信息,发现没有对应的报错信息,再去看看access log,好像也没看到有用的信息。(此处有坑)

接着又收到了其他的反馈:当使用nginx的容器进行代理的时候,请求服务都是正常的;但是一旦请求经过ingress nginx,那么全部报错400

2 抓包

这种进行对比的结果就很烦躁了,没迁移之前是好的,迁移之后是坏的,那说明问题大概率在ingress nginx上面,但是并不知道问题出在哪里。

当没有头绪的时候,就只能抓包了,从而对ingress nginx的pod进行了抓包。

代码语言:javascript
复制
tcpdump -w 400.pcap

在进行抓包的时候,还是比较喜欢直接抓所有的包,虽然在查看结果的时候,要从无数个包里面进行过滤,但是既然抓了,那就抓全一点。

当在这种反向代理场景进行抓包的时候,如果进行ip或者其他的过滤,很可能抓的包不全,一个方面是客户端与ingress nginx的连接,一个是ingress nginx对后端的连接,有的时候还要把两个连接串起来进行分析,抓包的时候,注意包的大小,因为一不小心,磁盘就会被打爆了。

在抓包开启之后,就要进行模拟命令了,一个是正常的请求,一个是不正常的请求

代码语言:javascript
复制
正常的请求,会返回200的响应码,可以请求一个特殊的url,便于找包
curl upsteam_server_ip/health
非正常请求的,会返回400的响应码
curl ingress_nginx_pod_ip/health

包抓完后,就可以下载到本地进行分析了。

3 分析包

分析包的时候,直接ctrl + f,和普通的搜索一样,可以输入url里面的关键字来进行搜索,也就是上面的health,从而能找到两个对应的包,然后右键,选择follow http steam,从而可以看到整个包的信息,从而把两个连接的http 头取出来进行对比。

在进行400分析的时候,可以看到异常的请求中,header头多了如下的信息:

代码语言:javascript
复制
X-Forwarded-For
X-Forwarded-Proto
X-Forwarded-Port
X-Forwarded-Host
X-Real-IP

从这个信息看起来,肯定是这些header头导致的,那么就构造一个请求,将请求正常的加上这些头直接请求后端,看是否能正常响应

代码语言:javascript
复制
curl upsteam_server_ip/health -H "X-Real-IP:xx"
 -H "X-Forwarded-Port:xx" -H "X-Forwarded-Proto:xx"
  -H "X-Forwarded-For:xx"

发送请求之后,发现依旧是正确的响应,这。。。莫非是玄学,百思不得其解(此处有坑)。

没有办法,只能再次查看下异常的请求包,具体查看ingress nginx与后端的连接情况,发现ingress nginx把请求已经发送了后端,但是后端直接返回了一个400,那么说明是后端也就是服务端返回的,从而判断可能是服务端的问题。

4 查看服务端日志

拉服务端的人一起来看,发现是一个python的代码,里面用的是django的框架,然后查看对应的日志信息,发现了具体的报错信息:

代码语言:javascript
复制
Invalid HTTP_HOST header: '127.0.0.1:8000,127.0.0.1'.
 The domain name provided is not valid according
  to RFC 1034/1035.

看到这个报错,那么就肯定了是host的header头出了问题,进行了header头的拼接,正好有人对python比较熟悉,从而修改了这段验证的逻辑,再次进行请求,就都变成了正常响应,从而问题解决。‍

5 误区

  • 查看access log的时候,没有细看,从而没看到是upsteam_status也为400,并且具有upsteam_server,还有各种和后端连接时间,响应时间,从而未能及时判断是后端返回的400
  • 在抓包的时候,构造请求的时候,所有的参数都加上了,但是唯独没加上那个导致有问题的header头X-Forwarded-Host,从而未能判断是这个header头导致的400
  • 抓包不能解决一切问题,抓包的重点在于找到是谁发送的400响应,也就是谁发送的,那么就谁有问题,在看reset包的时候,也是这样,重点找到源头
  • 最大的问题:在看到400报错的时候,理都不想理,因为这都是客户端的问题,和我的配置有个毛的关系
  • 迁移之前是好的,迁移之后是坏的,心态容易爆炸,这两玩意儿不是一样的吗?其实并不是,在nginx的默认配置中,这些头基本上都是不传的,而在ingress nginx中,这些头默认都是传的,是ingress nginx的默认配置。

如果能修改ingress的话,那么也可以将这一段配置去掉,也能解决问题,不过修改这种helm chart的配置超级麻烦,所以就不这么修改了。

风言风语

本来是不想理的问题,最后真正去解决的时候,发现忽然走到了死胡同,服务端返回的400,已经超出了ingress nginx的范畴了,还好最后找到了应用的人配合,才得到解决。

想想为啥没从日志里面看到对应后端的返回,因为粗心咯;再想想为啥构造的请求,居然还是成功的,一度怀疑curl命令进行构造的时候,没有将对应的header传过去,重新抓了下包,发现都传了,但是命令没有拼接最关键的header头。

解决了一个问题,毫无成就感,一个问题没解决,挫败感铺天盖地。。。

本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。
原始发表:2024-06-29,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 SRE运维实践 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
相关产品与服务
容器服务
腾讯云容器服务(Tencent Kubernetes Engine, TKE)基于原生 kubernetes 提供以容器为核心的、高度可扩展的高性能容器管理服务,覆盖 Serverless、边缘计算、分布式云等多种业务部署场景,业内首创单个集群兼容多种计算节点的容器资源管理模式。同时产品作为云原生 Finops 领先布道者,主导开源项目Crane,全面助力客户实现资源优化、成本控制。
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档