一次jenkins-kubernetes服务报错排查记录 (Request Header Fields Too Large)

news/2024/7/12 2:19:35 标签: jenkins, kubernetes, 运维, 云原生, 容器

背景

最近我们自研的云原生发布平台新支持了一种发布场景,简单来说client里面会把k8s里面的各资源文件比如:

deploy.yaml

service.yaml

ingress.yaml

pvc.yaml

分别用字符串变量保存,然后通过jenkins开源库sdk传给一个带参数的jenkins pipeline job,来触发该job的运行,但是client在调用jenkins job的build方法(实际post的总数据是大于8KB)的时候程序了报了如下异常,

Exception:Request Header Fields Too Large

排查

由于我们的jenkins和client发布平台程序都是运行在K8s里面,client里面的用的是jenkins开源库通过Ingress域名访问的jenkins master,所以开始怀疑是Kubernetes Ingress Nginx的参数设置的过小导致,跟Header有关的nginx参数如下:

# body (和本次异常无关,顺带记录一下)
client_body_buffer_size 10K; 
client_max_body_size 8m;
# header
client_header_buffer_size 2m;
large_client_header_buffers 4 8k;

含义如下:

client_body_buffer_size:

Nginx分配给请求数据的Buffer大小,如果请求的数据小于client_body_buffer_size直接将数据先在内存中存储。如果请求的值大于client_body_buffer_size小于client_max_body_size,就会将数据先存储到临时文件中,使用client_body_temp 指定的路径中,默认该路径值是/tmp/.
所以配置的client_body_temp地址,一定让执行的Nginx的用户组有读写权限。否则,当传输的数据大于client_body_buffer_size,写进临时文件失败会报错。

client_max_body_size

默认 1M,表示 客户端请求服务器最大允许大小,在“Content-Length”请求头中指定。如果请求的正文数据大于client_max_body_size,HTTP协议会报错 413 Request Entity Too Large。就是说如果请求的正文大于client_max_body_size,一定是失败的。如果需要上传大文件,一定要修改该值

client_header_buffer_size:

假设client_header_buffer_size的配置为1k,如果(请求行+请求头)的大小如果没超过1k,放行请求。如果(请求行+请求头)的大小如果超过1k,则以large_client_header_buffers配置为准

large_client_header_buffers:

请求行+请求头的总大小不能超过32k(4 * 8k)

在我们调整k8s ingress nginx的相关配置后

# header
client_header_buffer_size 2m;
large_client_header_buffers 4 2m;

注意上述配置,可以不用修改k8s ingress controller 的全局配置,可以在应用级别配置,需要用k8s ingress controller的Snippets配置,具体参考:Advanced Configuration with Snippets | NGINX Ingress Controller

使用上述配置后,报错依然没有消失,为了排除nginx的干扰,我们直接通过访问service来继续测试:

curl --user user:pwd http://jenkins-svc.demo:8080/jenkins/job/my-test/config.xml

发现依然报错,然后我们在去看jenkins k8s master的日志,发现了端倪:

WARNING eclipse.jetty.http.HttpParser#parseFields: Header is too large 8193>8192

到这里可以确认是jetty容器的设置,导致接受到的请求被解析失败了

修复

我们的jenkins是运行在k8s里面,而jetty又是jenkis内嵌的服务器,还没有办法直接调参数,传统的jetty用法,我们是把应用丢进jetty的webapps目录和tomcat类似,所以是可以直接去调ini文件参数的,当如果应用是引用jetty-core.jar,把web容器做成了内嵌服务,那么很多参数都是硬编码的,所以调起来很不方便。

经过查询,发现jenkins有个JENKINS_OPTS参数,可以调整,在k8s里面这个参数的内容是挂在secret里面,所以,我们直接在secret里面新增下面的内容即可(单位Byte),具体大小可以根据业务调整:

"--requestHeaderSize=258140" (252KB)

问题本质

上面解决方案确实有用,但却不是这个问题的本质原因,经过查看我们用的jenkis开源库的源码:

        <dependency>
            <groupId>com.offbytwo.jenkins</groupId>
            <artifactId>jenkins-client</artifactId>
            <version>0.3.8</version>
        </dependency>

发现其代码里,将post请求转为url拼接:

    public QueueReference build(Map<String, String> params, Map<String, File> fileParams, boolean crumbFlag) throws IOException {
        String qs = join(Collections2.transform(params.entrySet(), new MapEntryToQueryStringPair()), "&");
        ExtractHeader location = client.post(url + "buildWithParameters?" + qs,null, ExtractHeader.class, fileParams, crumbFlag);
        return new QueueReference(location.getLocation());
    }

如果是在body的data里,就不会有问题,因为body是没限制的,而url的长度也就是header长度是有限制的,这也是为什么GET请求和POST的请求的一个最大区别,这个确实是坑了,因为源码是这样,所以为了快速修复,我们采用加大了jetty容器的header检查限制,这样可快速修复问题,也不用改动源码再次发布,那样影响会比较大。

最后推荐大家,如果使用开源库操作jenkins,可以使用官网推荐的jenkins-rest:

        <dependency>
            <groupId>com.cdancy</groupId>
            <artifactId>jenkins-rest</artifactId>
            <version>0.0.27</version>
        </dependency>

总结

云原生时代,很多应用跑在Kubernetes里面很方便,但相应的请求访问链路也变多了,这样就会导致排查问题起来相对比较困难,因为不仅仅涉及应用程序,还会和应用请求经过的中间层nginx,业务网关,以及k8s本身网络等依赖的组件都可能有关联,排查问题时,可以用排除法,逐步缩小问题范围,这样排查起来就高效多了。


http://www.niftyadmin.cn/n/787141.html

相关文章

分层结构的生活例子_分层架构中的服务层-服务层实战

引言服务层是在交互的两个层中间又定义了另外一个层&#xff0c;典型的是在表现层和业务逻辑层之间。这个中间层只是实现应用的用例的类集合。服务和面向服务的出现&#xff0c;使得整个解决方案更有价值、更加成功。与表现层相比&#xff0c;服务层提供了松散的耦合&#xff0…

asc.desc

DESC 是descend 降序意思 asc 是ascend 升序的意思转载于:https://www.cnblogs.com/toSeeMyDream/p/5860480.html

企业级实战——畅购商城SpringCloud-微服务网关鉴权限流解决方案-JWT+nginx——添加商品参数查询实现

QQ 1274510382 Wechat JNZ_aming 商业联盟 QQ群538250800 技术搞事 QQ群599020441 解决方案 QQ群152889761 加入我们 QQ群649347320 共享学习 QQ群674240731 纪年科技aming 网络安全 ,深度学习,嵌入式,机器强化,生物智能,生命科学。 纸上得来终觉浅,绝知此事要躬行 &#xff0…

vue3+axios刷新浏览器interceptors无效问题

问题描述 vue前端应用在用户登录之后&#xff0c;服务端会返回一个认证token&#xff0c;前端会将此token存在cookie中&#xff0c;之后前端每次发起的向服务端的请求时&#xff0c;会通过axios的interceptors.request方法&#xff0c;来自动将cookie中的token取出来放在请求头…

【数据挖掘】时间序列教程【一】

第一章 说明 对于时间序列的研究&#xff0c;可以追溯到19世纪末和20世纪初。当时&#xff0c;许多学者开始对时间相关的经济和社会现象进行研究&#xff0c;尝试发现其规律和趋势。其中最早的时间序列研究可以追溯到法国经济学家易贝尔&#xff08;Maurice Allais&#xff09;…

企业级实战——畅购商城SpringCloud-微服务网关鉴权限流解决方案-JWT+nginx——根据分类ID查询规格集合实现

QQ 1274510382 Wechat JNZ_aming 商业联盟 QQ群538250800 技术搞事 QQ群599020441 解决方案 QQ群152889761 加入我们 QQ群649347320 共享学习 QQ群674240731 纪年科技aming 网络安全 ,深度学习,嵌入式,机器强化,生物智能,生命科学。 纸上得来终觉浅,绝知此事要躬行 &#xff0…

[ CodeVS冲杯之路 ] P1014

不充钱&#xff0c;你怎么AC&#xff1f; 题目&#xff1a;http://codevs.cn/problem/1014/ 一道不用考虑价值的DP题&#xff0c;那么我们可以用 0 和 1 表示是否能够达到该步骤 1 #include<cstdio>2 #include<cstdlib>3 #include<cstring>4 #include<cma…

stat在python中_python os.stat() 和 stat模块详解

stat 系统调用时用来返回相关文件的系统状态信息的。首先我们看一下stat中有哪些属性:>>> import os>>> print os.stat("/root/python/zip.py")(33188, 2033080, 26626L, 1, 0, 0, 864, 1297653596, 1275528102, 1292892895)>>> print os…