全部產品
Search
文件中心

Container Service for Kubernetes:部署高負載情境的Nginx Ingress Controller

更新時間:Jan 11, 2025

在Kubernetes叢集中,Ingress對叢集服務(Service)中外部可訪問的API對象進行管理,提供七層負載平衡能力。Nginx Ingress Controller負責實現Ingress的功能,根據規則配置負載平衡並提供訪問入口。在高負載情境下,CPU資源和網路連接數的不足會影響應用的效能。本文介紹如何通過部署Nginx Ingress Controller來支撐高負載應用。

前提條件

部署說明

部署高負載情境下的Nginx Ingress Controller需要考慮以下三個方面。

硬體選型

在高並發情境下,Ingress對CPU資源和網路連接數佔用都非常高,建議您選擇增強型ECS執行個體,例如:

  • 計算型執行個體:ecs.c6e.8xlarge(32 Core 64 GB,600萬PPS)

  • 網路型執行個體:ecs.g6e.8xlarge(32 Core 128 GB,600萬PPS)

關於ECS執行個體規格的更多資訊,請參見執行個體規格類型系列

K8s配置

  • 設定Ingress Pod獨佔節點資源,添加汙點和節點標籤:

    kubectl label nodes $node_name ingress-pod="yes"
    kubectl taint nodes $node_name ingress-pod="yes":NoExecute
  • 設定CPU Policy為static

  • 推薦調整ingress-controller service對應的SLB規格為超強型(slb.s3.large)。

  • 推薦叢集使用Terway網路外掛程式及配置獨佔ENI。

Ingress配置

  • 設定Ingress Pod為Guaranteed類型。

    • 設定nginx-ingress-controller container的資源限制requestslimits:30Core 40GiB。

    • 設定initContainer init-sysctl的資源限制requestslimits:100m 70MiB。

  • 調整Deployment Replicas數為新增節點數。

  • 設定ConfigMap的worker-processes數為28(預留部分給系統使用)。

  • 調整ConfigMap的keepalive連結最大請求數。

  • 關閉日誌訪問記錄。

步驟一:添加節點

選擇指定叢集,建立新的節點池並添加2台節點。

建立節點池需要配置的主要參數如下所示。具體操作,請參見建立和管理節點池

  • 選擇作業系統Alibaba Cloud Linux3

  • 配置節點標籤汙點(Taints)

    • 設定汙點(Taints)ingress-podyesEffectNoExecute

    • 設定節點標籤ingress-podyes

  • 選擇CPU PolicyStatic

步驟二:配置Nginx Ingress Controller

執行kubectl edit deploy nginx-ingress-controller -n kube-system命令開啟Ingress Controller的設定檔,根據以下內容更新Ingress Controller的配置:

  1. 刪除Pod反親和性配置。

    podAntiAffinity:
      requiredDuringSchedulingIgnoredDuringExecution:
      - labelSelector:
          matchExpressions:
          - key: app
          operator: In
          values:
          - ingress-nginx
       topologyKey: kubernetes.io/hostname
  2. 配置InitContainer的requestslimits

    resources:
      limits:
        cpu: 100m
        memory: 70Mi
      requests:
        cpu: 100m
        memory: 70Mi
  3. 修改nginx-ingress-controller container的requestslimits都為30Core 40GiB。

    resources:
      limits:
        cpu: "30"
        memory: 40Gi
      requests:
        cpu: "30"
        memory: 40Gi
  4. 設定節點親和性和容忍性。

    nodeSelector:
      ingress-pod: "yes"
    tolerations:
    - effect: NoExecute
      key: ingress-pod
      operator: Equal
      value: "yes"
  5. 調整Replicas數為新增節點數。

  6. 關閉Metrics採集,修改啟動參數,添加--enable-metrics=false

    說明

    如果不需要擷取Metrics資訊,建議關閉Metrics採集。對於v1.9.3以上版本的Nginx Ingress Controller,您還可以通過配置啟動參數 --exclude-socket-metrics來排除相關的指標, 例如nginx_ingress_controller_ingress_upstream_latency_seconds。這樣做可以協助減輕對系統效能的影響。

    containers:
    - args:
      - /nginx-ingress-controller
      - --configmap=$(POD_NAMESPACE)/nginx-configuration
      - --tcp-services-configmap=$(POD_NAMESPACE)/tcp-services
      - --udp-services-configmap=$(POD_NAMESPACE)/udp-services
      - --annotations-prefix=nginx.ingress.kubernetes.io
      - --publish-service=$(POD_NAMESPACE)/nginx-ingress-lb
      - --enable-metrics=false
      - --v=1

步驟三:配置Nginx Ingress ConfigMap

  1. 使用kubectl edit cm -n kube-system nginx-configuration更新ConfigMap,可參考以下程式碼範例:

    apiVersion: v1
    kind: ConfigMap
    metadata:
      name: nginx-configuration
      namespace: kube-system
    data:
      allow-backend-server-header: "true"
      enable-underscores-in-headers: "true"
      generate-request-id: "true"
      ignore-invalid-headers: "true"
      log-format-upstream: $remote_addr - [$remote_addr] - $remote_user [$time_local] "$request" $status $body_bytes_sent "$http_referer" "$http_user_agent" $request_length $request_time [$proxy_upstream_name] $upstream_addr $upstream_response_length $upstream_response_time $upstream_status $req_id $host [$proxy_alternative_upstream_name]
      max-worker-connections: "65536"
      proxy-body-size: 20m
      proxy-connect-timeout: "3"
      proxy-read-timeout: "5"
      proxy-send-timeout: "5"
      reuse-port: "true"
      server-tokens: "false"
      ssl-redirect: "false"
      upstream-keepalive-timeout: "900"
      worker-processes: "28" # 設定啟動的Nginx進程數,請根據您的node節點規格進行實際調整,建議調整為cpu核心數-2。
      worker-cpu-affinity: auto
      upstream-keepalive-connections: "300"
      upstream-keepalive-requests: "1000" # 設定單個長串連最多可以發送多個。
      keep-alive: "900"
      keep-alive-requests: "10000"
  2. 採用檔案方式記錄訪問日誌並對日誌輪轉。

    預設的日誌訪問記錄輸出到/dev/stdout,在高並發情境下,會佔用大量CPU,故採用檔案方式記錄訪問日誌並對日誌設定輪轉。

    1. 以SSH方式登入部署ingress-controller Pod的ECS節點。具體操作,請參見通過密鑰認證登入Linux執行個體

    2. /etc/crontab檔案結尾添加以下內容:

      */15 * * * *  root /root/nginx-log-rotate.sh
      說明

      此處以每隔15分鐘對日誌輪轉一次為例,可根據實際需求進行調整。

    3. /root目錄下添加檔案nginx-log-rotate.sh

      Docker叢集

      #!/bin/bash
      # 最多保留記錄檔個數,可根據需求進行調整。
      keep_log_num=5
      ingress_nginx_container_ids=$(docker ps | grep nginx-ingress-controller | grep -v pause | awk '{print $1}')
      if [[ -z "$ingress_nginx_container_ids" ]]; then
       echo "error: failed to get ingress nginx container ids"
       exit 1
      fi
      # 隨機睡眠5~10秒。
      sleep $(( RANDOM % (10 - 5 + 1 ) + 5 ))
      for id in $ingress_nginx_container_ids; do
       docker exec $id bash -c "cd /var/log/nginx; if [[ \$(ls access.log-* | wc -l) -gt $keep_log_num ]]; then rm -f \$(ls -t access.log-* | tail -1); fi ; mv access.log access.log-\$(date +%F:%T) ; kill -USR1 \$(cat /tmp/nginx/nginx.pid)"
      done	
      	

      containerd叢集

      #!/bin/bash
      # 最多保留記錄檔個數,可根據需求進行調整。
      keep_log_num=5
      ingress_nginx_container_ids=$(crictl ps | grep nginx-ingress-controller | grep -v pause | awk '{print $1}')
      if [[ -z "$ingress_nginx_container_ids" ]]; then
       echo "error: failed to get ingress nginx container ids"
       exit 1
      fi
      # 隨機睡眠5~10秒。
      sleep $(( RANDOM % (10 - 5 + 1 ) + 5 ))
      for id in $ingress_nginx_container_ids; do
       crictl exec $id bash -c "cd /var/log/nginx; if [[ \$(ls access.log-* | wc -l) -gt $keep_log_num ]]; then rm -f \$(ls -t access.log-* | tail -1); fi ; mv access.log access.log-\$(date +%F:%T) ; kill -USR1 \$(cat /tmp/nginx/nginx.pid)"
      done	
      	
    4. 執行以下命令,對nginx-log-rotate.sh檔案添加可執行許可權。

      chmod 755 /root/nginx-log-rotate.sh

步驟四: 可選配置調優

以下為核心相關參數、應用設定、壓縮功能和HTTPS效能最佳化的建議配置。

  • 核心相關參數調優

    在對核心參數進行調優之前,務必確保對這些參數有深刻的理解,並謹慎操作。

    • 調整TIME_WAIT

      為了最佳化Nginx Ingress的效能,可以通過調整系統參數來開啟TIME_WAIT複用,並減少FIN_WAIT2和TIME_WAIT狀態的逾時時間。

      • net.ipv4.tcp_fin_timeout=15:減少FIN_WAIT2狀態的逾時時間,以更快釋放串連資源。

      • net.netfilter.nf_conntrack_tcp_timeout_time_wait=30:縮短TIME_WAIT狀態下的串連保持時間,加速資源釋放。

    • 配置操作

      1. 通過以下命令編輯Nginx Ingress Controller的Deployment。

        kubectl edit deployments -n kube-system nginx-ingress-controller
      2. init container部分新增sysctl -w net.ipv4.tcp_fin_timeout=15sysctl -w net.netfilter.nf_conntrack_tcp_timeout_time_wait=30參數,儲存並退出。

        initContainers:
              - command:   # 新增sysctl -w net.ipv4.tcp_fin_timeout=15和sysctl -w net.netfilter.nf_conntrack_tcp_timeout_time_wait=30參數。
                - /bin/sh
                - -c
                - |
                  if [ "$POD_IP" != "$HOST_IP" ]; then
                  mount -o remount rw /proc/sys
                  sysctl -w net.core.somaxconn=65535
                  sysctl -w net.ipv4.ip_local_port_range="1024 65535"
                  sysctl -w kernel.core_uses_pid=0
                  sysctl -w net.ipv4.tcp_fin_timeout=15 
                  sysctl -w net.netfilter.nf_conntrack_tcp_timeout_time_wait=30   
                  fi
  • 應用程式層配置調優

    您可以通過以下命令和配置對業務從應用程式層面配置調優。

    1. 使用以下命令編輯Nginx Ingress Controller的ConfigMap。

       kubectl edit cm -n kube-system nginx-configuration
    2. 根據下述配置參數,結合您的實際業務情境進行配置調優。

      配置項

      配置參數

      描述

      下遊keepalive

      keep-alive: "60"

      指定keepalive串連的逾時時間,單位為秒。

      keep-alive-requests: "10000"

      指定keepalive請求的最大數量。

      上遊keepalive

      upstream-keepalive-connections: "1000"

      最大keepalive串連數。

      upstream-keepalive-requests: "2147483647"

      允許的最大keepalive請求數。

      upstream-keepalive-time: 1h

      上遊keepalive串連的最大保持時間。

      upstream-keepalive-timeout: "150"

      指定上遊keepalive串連的空閑逾時時間,單位為秒。

      單個Worker最大串連

      max-worker-connections: "65536"

      單個Worker支援的最大串連數。

      逾時配置

      說明

      可根據實際業務情境調整,按需配置。

      proxy-connect-timeout: "3"

      建立TCP串連的逾時時間,單位為秒。

      proxy-read-timeout: "5"

      讀取資料的逾時時間,單位為秒。

      proxy-send-timeout: "5"

      發送資料的逾時時間,單位為秒。

      最佳化重試機制

      說明

      當後端服務異常情況下,多級重試的過多請求可能加重後端服務的負載引發雪崩問題。更多詳情請參見Ingress-nginx官方文檔

      proxy-next-upstream-tries:"3"

      失敗後的重試次數,預設為3次,包括1次初始請求和2次重試。

      proxy-next-upstream:"off"

      指定重試條件,設定為off則關閉重試功能。

      proxy-next-upstream-timeout

      指定請求重試的逾時時間,單位為秒,根據實際應用情境進行調整。

  • 啟用Brotli壓縮

    壓縮是一種通過犧牲CPU時間來節省大量網路頻寬的通用方法,能夠提升輸送量。Brotli是Google開發的一種壓縮演算法。相較於常用的gzip壓縮演算法(Nginx Ingress Controller預設使用gzip),Brotli的壓縮率據稱要高出20%~30%。Ingress-nginx中啟用Brotli壓縮,需要配置以下參數,更多詳情請參見Ingress-nginx官方文檔

    • enable-brotli: 是否啟用Brotli壓縮演算法,取值為 true 或 false

    • brotli-level: 壓縮層級,範圍是1到11,預設是4。層級越高,CPU效能消耗越大。

    • brotli-types: 指定使用Brotli即時壓縮的MIME類型。

    您可以使用以下命令啟用Brotli壓縮。

     kubectl edit cm -n kube-system nginx-configuration

    配置樣本:

    enable-brotli: "true"
    brotli-level: "6"
    brotli-types: "text/xml image/svg+xml application/x-font-ttf image/vnd.microsoft.icon application/x-font-opentype application/json font/eot application/vnd.ms-fontobject application/javascript font/otf application/xml application/xhtml+xml text/javascript application/x-javascript text/plain application/x-font-truetype application/xml+rss image/x-icon font/opentype text/css image/x-win-bitmap"
  • HTTPS效能最佳化

    為了提升HTTPS的效能,可以使用kubectl edit cm -n kube-system nginx-configuration命令編輯ConfigMap,並配置以下參數:SSL 會話緩衝、OCSP Stapling、TLS 1.3 早期資料以及調整密碼套件優先順序。

    • SSL會話緩衝與逾時

      設定SSL 共用工作階段緩衝的大小以及重用緩衝中儲存的會話參數的時間,可以減少SSL握手的開銷。

      • ConfigMap配置:

        ssl-session-cache-size:"10m"
        ssl-session-timeout:"10m"
      • 對應Nginx側的nginx.conf配置,可以根據實際情境需求調整。

        ssl_session_cache shared:SSL:120m;   # 1m 4000個。
        ssl_session_timeout 1h;              # 會話逾時時間為1小時。
    • 啟用OCSP Stapling

      使用OCSP Stapling可以減少用戶端認證驗證的時間。

      enable-ocsp: "true"
    • 支援TLS 1.3早期資料(0-RTT)

      啟用TLS 1.3的0-RTT功能可以允許用戶端在握手完成之前就發送資料,從而減少串連建立的延遲。

      ssl-early-data: "true"
      ssl-protocols: "TLSv1.3"
    • 調整Cipher優先順序(無需手動調優)

      通過調整加密套件的優先順序,可以有效降低延遲。Nginx Ingress Controller的預設配置已進行了最佳化。

      ssl_ciphers 'ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:DHE-RSA-AES128-GCM-SHA256:DHE-RSA-AES256-GCM-SHA384';
      ssl_prefer_server_ciphers on;    # 優先使用伺服器端的Cipher配置。