kubernetes 中 nginx-ingress 问题排查及配置调优

原文作者:郭旭东x
原文链接
更多云原生技术资讯可关注阿里巴巴云原生技术圈

前言

随着公司容器化的深入,越来越多的服务陆续迁移到kubernetes集群中,有些问题在测试环境并未凸显,但是在生产环境中这些问题就显得格外的扎眼。这里就对实践中kubernetes集群中的7层负载均衡器ingress遇到的问题进行总结。

HTTP(S)负载均衡器-ingress

Ingress是kubernetes API的标准资源类型之一,其本质就是一组基于DNS名称(host)或URL路径把请求转发至指定的Service资源的规则,用于将集群外的请求流量转发至集群内部完成服务发布
Ingress控制器(Ingress Controller)可以由任何具有反向代理(HTTP/HTTPS)功能的服务程序实现,如Nginx、Envoy、HAProxy、Vulcand和Traefik等。Ingress控制器本身也作为Pod对象与被代理的运行为Pod资源的应用运行于同一网络中。我们在这里选择了NGINX Ingress Controller,由于对NGINX的配置较为熟悉,同时我们使用的kubernetes是阿里云的容器服务,构建集群的时候,容器服务会自带NGINX Ingress Controller。
kubernetes 中 nginx-ingress 问题排查及配置调优

根据实际情况Ingress调优

  1. 解决 Nginx-Ingress 重定向失败问题

    • 现象
      最近对公司 Kubernetes 集群的 nginx-ingress-controller 进行了升级,但是升级后却出现了大问题,之前所有采用 nginx.ingress.kubernetes.io/rewrite-target: / 注释进行重定向的 Ingress 路由全部失效了,但是那些直接解析了域名,没有进行重定向的却没有发生这个问题。
    • 问题分析

      1. 首先检查对应服务健康状态,发现所有出问题的服务的状态均正常,同时受影响的之后 http 调用,而 RPC 调用却不受影响,这时问题就定位到了 ingress。
      2. 然后检查 nginx-ingress-controller ,发现 nginx-ingress-controller 的状态也是正常的,路由也是正常的。
      3. 最后发现受影响的只有添加了重定向策略的 ingress 。
    • 问题解决
      问题已经定位,接下来就是着手解决问题,这时候值得注意的就是之前进行了什么变更:升级了 nginx-ingress-controller 版本!看来问题就出现在新版本上,那么就打开官方文档:https://kubernetes.github.io/ingress-nginx/examples/rewrite/ 看一下吧。

Attention
Starting in Version 0.22.0, ingress definitions using the annotation nginx.ingress.kubernetes.io/rewrite-target are not backwards compatible with previous versions. In Version 0.22.0 and beyond, any substrings within the request URI that need to be passed to the rewritten path must explicitly be defined in a capture group.

  1. 文档上给出了非常明显的警告️:从 V0.22.0 版本开始将不再兼容之前的入口定义,再查看一下我的 nginx-ingress-controller 版本,果然问题出现来这里。

Note
Captured groups are saved in numbered placeholders, chronologically, in the form $1, $2 ... $n. These placeholders can be used as parameters in the rewrite-target annotation.

  • 示例
  1. 到这里问题已经解决了,在更新了 ingress 的配置之后,之前所有无法重定向的服务现在都已经可以正常访问了。修改见如下示例:
$ echo '
apiVersion: extensions/v1beta1
kind: Ingress
metadata:
  annotations:
    nginx.ingress.kubernetes.io/rewrite-target: /$2
  name: rewrite
  namespace: default
spec:
  rules:
  - host: rewrite.bar.com
    http:
      paths:
      - backend:
          serviceName: http-svc
          servicePort: 80
        path: /something(/|$)(.*)
' | kubectl create -f -
  1. 解决400 Request Header Or Cookie Too Large问题

    • 现象
微信小程序需要调用后端接口,需要在header中传一段很长的token参数,直接使用浏览器访问该端口可以访问通,但是在加上token访问之后,会报“400 Request Header Or Cookie Too Large”
<html>
    <head>
        <title>400 Request Header Or Cookie Too Large</title>
    </head>
    <body>
        <center>
            <h1>400 Bad Request</h1>
        </center>
        <center>Request Header Or Cookie Too Large</center>
        <hr>
        <center>nginx/1.15.6</center>
    </body>
</html>
- ####问题定位
    直接修改Service使用nodeport的形式访问,则没有报错,初步定位需要在ingress中nginx配置客户端的请求头,进入Ingress Controller的Pod查询配置,果然是请求头空间不足。
$ cat nginx.conf | grep client_header_buffer_size
    client_header_buffer_size       1k;
$ cat nginx.conf | grep large_client_header_buffers
    large_client_header_buffers     4 8k;
- ####解决方法
    在ingress中添加注释
nginx.ingress.kubernetes.io/server-snippet: client_header_buffer_size 2046k;
> **Server snippet**
    >Using the annotation ```nginx.ingress.kubernetes.io/server-snippet``` it is possible to add custom configuration in the server configuration block.
    >该注释是将自定义配置加入nginx的server配置中
  1. 解决请求超时问题

    • 现象
有一个数据导出功能,需要将大量数据进行处理,然后以Excel格式返回,在导出一个大约3W条数据的时候,出现访问超时情况。
![image](https://ws2.sinaimg.cn/mw690/ad5fbf65ly1g0ubdwwzo5j21b30bjaat.jpg)
  • 解决方法
调整proxy_read_timeout,连接成功后_等候后端服务器响应时间_其实已经进入后端的排队之中等候处理
在ingress中添加注释
nginx.ingress.kubernetes.io/proxy-read-timeout: 600
>这里需要注意的事该注释的value需要时number类型,不能加s,否则将不生效
  1. 增加白名单

    • 现象
在实际的使用中,会有一部分应用需要设置只可以在办公场地的网络使用,之前使用阿里云 SLB 的时候可以针对端口进行访问控制,但是现在走 ingress ,都是从80 or 443端口进,所以需要在 ingress 设置
  • 解决方法
> **Whitelist source range**
>You can specify allowed client IP source ranges through the nginx.ingress.kubernetes.io/whitelist-source-range annotation. The value is a comma separated list of CIDRs, e.g. 10.0.0.0/24,172.10.0.1.
在 ingress 里配置 ```nginx.ingress.kubernetes.io/whitelist-source-range``` ,如有多个ip段,用逗号分隔即可
nginx.ingress.kubernetes.io/whitelist-source-range: 10.0.0.0/24
如果想全局适用,可以在阿里云 SLB 里操作,也可以将该配置加入到 ```NGINX ConfigMap``` 中。

根据工作中遇到的实际问题,持续更新中...

总结

使用NGINX ingress controller的好处就是对于nginx配置相对比较熟悉,性能也不差。相关nginx配置的对应的ingress可以在 https://kubernetes.github.io/ingress-nginx/user-guide/nginx-configuration/annotations/ 上查到。

阿里巴巴云原生关注微服务、Serverless、容器、Service Mesh 等技术领域、聚焦云原生流行技术趋势、云原生大规模的落地实践,做最懂云原生开发者的技术圈。”

上一篇:Docker 容器实战 (一) : 封神 Server 端技术


下一篇:如何快速搭建免费云上 MongoDB 副本集群