天天看點

kubernetes 中 nginx-ingress 問題排查及配置調優

前言

随着公司容器化的深入,越來越多的服務陸續遷移到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。

根據實際情況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 .
    文檔上給出了非常明顯的警告️:從 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.
    • 示例

    到這裡問題已經解決了,在更新了 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 -           
  2. 解決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,否則将不生效
                 
  2. 增加白名單
    • 在實際的使用中,會有一部分應用需要設定隻可以在辦公場地的網絡使用,之前使用阿裡雲 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/

上查到。

繼續閱讀