Ingress 上传文件报 413:改了 nginx.conf 没用,因为模板在 controller 里
现象:一个上传接口,本地和虚拟机部署都正常,迁到 K8s + ingress-nginx 之后,超过 1MB 的文件直接返回 413 Request Entity Too Large,而且返回的是 nginx 的 HTML 错误页,不是后端的 JSON 错误体。这一点很关键:返回 HTML 说明请求根本没到应用。
为什么"改了 nginx.conf 没用"
很多人会 exec 进 controller 的 Pod,找到 /etc/nginx/nginx.conf 里的 client_max_body_size 改成 20m,然后 reload。改完发现还是 413。原因有两个:
1. 这个文件是 controller 根据模板 + ConfigMap + Ingress 注解实时生成的,Pod 一重启就被覆盖。
2. 就算当时生效了,nginx 的匹配顺序是 server 块优先于 http 块。ingress-nginx 会给每个 host 生成一个 server 块,块里带着从注解算出来的 client_max_body_size,所以 http 层的值被覆盖。
正确的两级配置
第一级:全局(controller ConfigMap)
apiVersion: v1
kind: ConfigMap
metadata:
name: ingress-nginx-controller
namespace: ingress-nginx
data:
proxy-body-size: "0" # 0 表示不限制;生产建议给具体值,比如 20m
proxy-read-timeout: "300"
proxy-send-timeout: "300"
这里注意命名:ConfigMap 的 key 是 `proxy-body-size`,不是 `client-max-body-size`。nginx 里的 `client_max_body_size` 被 ingress-nginx 映射成了 `proxy-body-size`(下划线变中划线,去掉 client)。
第二级:单个 Ingress(推荐,粒度更细)
metadata:
annotations:
nginx.ingress.kubernetes.io/proxy-body-size: "20m"
注解名同样是 proxy-body-size。写成 client-max-body-size 会静默无效——annotation 不认识就当没写,不会报错,这是最容易白折腾半天的地方。
另一个容易踩的点:注解必须写在 **Ingress** 对象上,不能写在 Service 上。写在 Service 的 annotations 里完全不生效。
为什么是 1MB 正好卡住
ingress-nginx 的默认值就是 1m。所以"小文件能传、大文件 413"且分界线接近 1MB,基本可以断定是这一层。
还有一种 413 不在这里
如果返回的 413 是 JSON,带后端的错误结构,那就是应用层自己的限制:
- Spring Boot:spring.servlet.multipart.max-file-size 和 max-request-size,默认 1MB / 10MB。
- Nginx 反代在上游时,上游的 client_max_body_size 也可能拦,但错误页样式会不同。
- Tomcat 的 maxPostSize 默认 2MB,超出时有些版本返回 400 而不是 413。
区分方法很简单:看响应头的 Server 字段和错误页的 HTML 结构。ingress-nginx 返回的是标准 nginx 错误页,带 `<center>nginx</center>`。
验证是否真的生效
别只看配置,去 controller Pod 里看生成出来的配置:
kubectl -n ingress-nginx exec deploy/ingress-nginx-controller -- grep -n "client_max_body_size" /etc/nginx/nginx.conf
应该能在对应 server 块里看到你设的值。如果看到的是 1m,说明注解没被识别,回去检查 key 的拼写和它挂在哪个对象上。
顺带说三个相关配置
- proxy-read-timeout / proxy-send-timeout:大文件上传不只是大小问题,慢网络下默认 60 秒会被掐断,表现为 504。上传接口一般要调到 300 秒以上。
- proxy-request-buffering: "off":流式上传(比如大文件直传对象存储)时,关掉请求缓冲能让数据边收边转发,避免 nginx 先把整个 body 落到临时磁盘。默认开启,磁盘紧张时容易出问题。
- client-body-buffer-size:控制内存里的缓冲大小,超过就写临时文件。跟 413 无关,但会影响大请求的内存占用。
小结
- 413 + nginx 错误页 = 根本没到应用,别去改后端配置。
- ingress-nginx 的开关叫 proxy-body-size,两级:ConfigMap 全局、Ingress 注解局部,注解要挂在 Ingress 上。
- 改完一定进 Pod 看生成后的 nginx.conf,确认 server 块里的值真的变了。
- 大文件上传还要一起看 timeout 和 buffering,否则 413 解决了会变成 504。
- 点赞
- 收藏
- 关注作者
评论(0)