Kubernetes部署服务通过Ingress访问报错413解决

场景

这里先简单说明本文的背景情况,下面的情况应该可以覆盖大部分场景

  1. 最右侧是服务中的HTTP服务,假设也是Nginx做的HTTP服务

所以综上所述,这个场景里面有3个Nginx,而413 Request Entiry Too large就是请求的实体太大了,抛去服务本身的问题,从Kubernetes和Nginx中间件上分析这个问题。

分析

外部负载

stream {
          
   
    upstream 80_proxy {
          
   
        hash $remote_addr consistent;  #远程地址做个hash
        server Kubernetes任意节点IP:Ingress80端口;        #Kubernetes集群IP(一般为内部IP)+Ingress端口
    }

    server {
          
   
        listen       80;
        proxy_pass   80_proxy;
    }

    upstream 443_proxy {
          
   
        hash $remote_addr consistent;  #远程地址做个hash
        server Kubernetes任意节点IP:Ingress443端口;        #Kubernetes集群IP(一般为内部IP)+Ingress端口
    }

    server {
          
   
        listen       443;
        proxy_pass   443_proxy;
    }
}

Ingress

网上很多说在Ingress的yaml中加配置nginx.ingress.kubernetes.io/proxy-body-size: 30M,但是不一定适用,因为大家的Ingress镜像、版本不一定一致,需要看apiVersion: networking.k8s.io/v1这里是使用的什么API,找到对应的文档和镜像信息,然后再进行配置。

比如Kubernetes官方的文档中对APInetworking.k8s.io/v1的介绍如下

    翻译的

这里很清楚的说,这个没有设置的话,如果超过了默认值(一般是1m)就会出现413错误。client_max_body_size就是Nginx的请求实体大小配置,但是Ingress中不配置它,不要被误导了。这里面给出的解决方案,是以下两个配置:

  1. 要在 Ingress 规则全局配置此设置,需要在NGINX ConfigMap中设置proxy-body-size
  2. 要在 Ingress 规则中使用自定义值,请定义以下注释annotationnginx.ingress.kubernetes.io/proxy-body-size: 30m

解决:Ingress配置

官方文档对NGINX ConfigMap中的proxy-body-size是如下解释,该值和client_max_body_size的作用一致,所以配置该项即可 但是文档没有说该项属于metadata(annotation、label)还是data,所以又去看了示例的 如下Example,是在ConfigMap中的data配置下,注意data是根配置,顶头写

将Ingress的ConfigMap添加data配置后如下即可

---
apiVersion: v1
data:
  proxy-body-size: 50M
  1. Ingress.yaml

这个文档中直接说明了,要在 Ingress 规则中定义注释,也就是annotationnginx.ingress.kubernetes.io/proxy-body-size: 30m,所以在配置中增加annotation后如下即可

---
apiVersion: networking.k8s.io/v1
kind: IngressClass
metadata:
  annotations:
    nginx.ingress.kubernetes.io/enable-cors: true
    nginx.ingress.kubernetes.io/proxy-body-size: 50M

Nginx HTTP

业务系统的Nginx就很简单啦,直接在nginx.conf中的http、server、location部分增加client_max_body_size配置即可

解决:Nginx配置

http {
          
   
    include       mime.types;
    default_type  application/octet-stream;

    log_format  main  $remote_addr - $remote_user [$time_local] "$request" 
                      $status $body_bytes_sent "$http_referer" 
                      "$http_user_agent" "$http_x_forwarded_for";

    access_log  logs/access.log  main;

    client_max_body_size 50M;
    sendfile        on;
    ……
经验分享 程序员 微信小程序 职场和发展