Ingress 上传文件报 413:改了 nginx.conf 没用,因为模板在 controller 里

举报
yd_271851511 发表于 2026/11/02 10:21:11 2026/11/02
【摘要】 2MB 的图片上传在测试环境正常,上了 K8s 就 413。改 ConfigMap、加 annotation、重启 Pod 都试过,报错依旧。413 是 nginx 层拦的,不是应用,而 ingress-nginx 的 client_max_body_size 有两级配置且注解名不叫这个。

现象:一个上传接口,本地和虚拟机部署都正常,迁到 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。

【声明】本内容来自华为云开发者社区博主,不代表华为云及华为云开发者社区的观点和立场。转载时必须标注文章的来源(华为云社区)、文章链接、文章作者等基本信息,否则作者和本社区有权追究责任。如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

评论(0)

0/1000
抱歉,系统识别当前为高风险访问,暂不支持该操作

全部回复

上滑加载中

设置昵称

在此一键设置昵称,即可参与社区互动!

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。