一、概述
1.1 背景介紹
Ingress Nginx 是 Kubernetes 集群中最主流的流量入口組件,承擔(dān)著集群內(nèi)所有 HTTP/HTTPS 流量的路由和轉(zhuǎn)發(fā)。默認(rèn)配置能應(yīng)付開發(fā)測試環(huán)境,但一到生產(chǎn)環(huán)境扛高并發(fā),各種瓶頸就暴露出來了——worker 進(jìn)程數(shù)不夠、連接池耗盡、SSL 握手吃滿 CPU、upstream 超時(shí)雪崩。
很多團(tuán)隊(duì)遇到性能問題的第一反應(yīng)是加副本數(shù)、加節(jié)點(diǎn),但 Ingress Nginx 的性能瓶頸往往不在資源量上,而在配置參數(shù)上。一個 4C8G 的 Pod,默認(rèn)配置可能只能跑到 2 萬 QPS,但經(jīng)過系統(tǒng)性調(diào)優(yōu),同樣的資源可以穩(wěn)定輸出 10 萬+ QPS。差距就在幾十個參數(shù)的合理配置上。
這篇文章從 Ingress Nginx 的架構(gòu)原理出發(fā),逐層拆解影響性能的關(guān)鍵參數(shù),覆蓋 worker 模型、連接復(fù)用、緩沖區(qū)、SSL 優(yōu)化、負(fù)載均衡、限流防護(hù)、內(nèi)核調(diào)優(yōu)等全鏈路,最終給出一套經(jīng)過壓測驗(yàn)證的高性能配置方案。
1.2 技術(shù)特點(diǎn)
全鏈路調(diào)優(yōu):從內(nèi)核參數(shù)到 Nginx 配置到 K8s 資源編排,覆蓋每一層性能瓶頸
參數(shù)有據(jù)可依:每個參數(shù)的取值都有計(jì)算公式或壓測數(shù)據(jù)支撐,不是拍腦袋
生產(chǎn)可落地:所有配置都基于 Ingress Nginx Controller 1.12+ 驗(yàn)證,可直接用于生產(chǎn)
面向未來:包含 Gateway API 遷移路徑,為下一代流量管理做準(zhǔn)備
1.3 適用場景
場景一:高并發(fā) Web 服務(wù)入口,需要單 Pod 承載 5 萬+ QPS
場景二:SSL 密集型場景,HTTPS 流量占比超過 90% 需要優(yōu)化握手性能
場景三:多租戶集群的流量網(wǎng)關(guān),需要精細(xì)化的限流和防護(hù)策略
場景四:從 Ingress API 向 Gateway API 遷移,需要平滑過渡方案
1.4 環(huán)境要求
| 組件 | 版本要求 | 說明 |
|---|---|---|
| Kubernetes | 1.32+ | 2026 年主流生產(chǎn)版本 |
| Ingress Nginx Controller | 1.12+ | 基于 Nginx 1.27.x |
| 操作系統(tǒng) | Ubuntu 24.04 LTS | 內(nèi)核 6.8+,支持 io_uring |
| 節(jié)點(diǎn)配置 | 4C8G 起步 | 推薦 8C16G 用于高并發(fā)場景 |
| cert-manager | 1.17+ | 證書自動管理和輪轉(zhuǎn) |
| Prometheus + Grafana | 最新穩(wěn)定版 | 監(jiān)控指標(biāo)采集和可視化 |
二、架構(gòu)原理與性能調(diào)優(yōu)
2.1 Ingress Nginx 架構(gòu)解析
2.1.1 請求處理鏈路
理解性能調(diào)優(yōu)的前提是搞清楚一個請求在 Ingress Nginx 里經(jīng)過了哪些環(huán)節(jié)。完整鏈路如下:
客戶端 -> NodePort/LoadBalancer -> Nginx Worker 進(jìn)程 -> SSL/TLS 終止 -> 請求解析 -> 路由匹配 -> 限流檢查 -> 負(fù)載均衡選擇 upstream -> 代理轉(zhuǎn)發(fā)到后端 Pod -> 響應(yīng)回傳客戶端
每個環(huán)節(jié)都有對應(yīng)的性能參數(shù)可以調(diào)。瓶頸通常出現(xiàn)在這幾個地方:
連接建立階段:TCP 握手、SSL 握手消耗 CPU 和時(shí)間
請求處理階段:worker 進(jìn)程數(shù)不夠、連接數(shù)打滿、緩沖區(qū)不足
代理轉(zhuǎn)發(fā)階段:upstream 連接復(fù)用率低、超時(shí)參數(shù)不合理
響應(yīng)回傳階段:緩沖區(qū)配置不當(dāng)導(dǎo)致磁盤 I/O
2.1.2 Nginx Worker 模型
Ingress Nginx 底層就是 Nginx,采用經(jīng)典的 Master-Worker 多進(jìn)程模型:
Master 進(jìn)程:負(fù)責(zé)讀取配置、管理 Worker 進(jìn)程、處理信號
Worker 進(jìn)程:實(shí)際處理請求,每個 Worker 是一個獨(dú)立進(jìn)程,內(nèi)部使用 epoll 事件驅(qū)動模型
關(guān)鍵點(diǎn)在于:每個 Worker 進(jìn)程是單線程的,通過 epoll 實(shí)現(xiàn)非阻塞 I/O 多路復(fù)用。一個 Worker 可以同時(shí)處理數(shù)千個并發(fā)連接,但 CPU 密集型操作(比如 SSL 握手、gzip 壓縮)會阻塞整個 Worker。
# 查看當(dāng)前 Ingress Nginx 的 worker 配置 kubectlexec-n ingress-nginx deploy/ingress-nginx-controller -- cat /etc/nginx/nginx.conf | grep -E"worker_processes|worker_connections"
2.1.3 ConfigMap 與 Annotation 的關(guān)系
Ingress Nginx 的配置分兩層:
ConfigMap(全局配置):影響所有 Ingress 規(guī)則,對應(yīng) nginx.conf 的全局和 http 塊
Annotation(單個 Ingress 配置):只影響特定 Ingress 規(guī)則,對應(yīng) server/location 塊
性能調(diào)優(yōu)主要在 ConfigMap 層面操作,個別場景需要 Annotation 配合。
2.2 Worker 進(jìn)程與連接數(shù)優(yōu)化
2.2.1 worker_processes 配置
默認(rèn)情況下 Ingress Nginx 的worker-processes設(shè)置為auto,即等于 CPU 核心數(shù)。在容器環(huán)境下,這個值取決于 Pod 的 CPU limit。
# ConfigMap 配置 apiVersion:v1 kind:ConfigMap metadata: name:ingress-nginx-controller namespace:ingress-nginx data: worker-processes:"auto"
調(diào)優(yōu)建議:
auto在大多數(shù)場景下是最優(yōu)選擇,不需要手動指定
如果 Pod 的 CPU limit 設(shè)置為 4,worker_processes 就是 4
不要設(shè)置超過 CPU 核心數(shù)的 worker 數(shù)量,多了反而因?yàn)樯舷挛那袚Q降低性能
對于 SSL 密集型場景,確保 CPU limit 給夠,因?yàn)?SSL 握手是 CPU 密集型操作
關(guān)鍵陷阱:如果 Pod 沒有設(shè)置 CPU limit(只設(shè)了 request),auto會讀取宿主機(jī)的 CPU 核心數(shù)。一臺 64 核的機(jī)器上跑出 64 個 worker 進(jìn)程,每個 worker 只分到零點(diǎn)幾核 CPU,性能反而更差。所以必須設(shè)置 CPU limit。
2.2.2 worker_connections 配置
worker-connections決定每個 Worker 進(jìn)程能同時(shí)處理的最大連接數(shù)。默認(rèn)值是 16384。
data: worker-connections:"65536"
計(jì)算公式:
最大并發(fā)連接數(shù) = worker_processes * worker_connections
但實(shí)際上每個客戶端請求在反向代理模式下會占用 2 個連接(客戶端到 Nginx + Nginx 到 upstream),所以實(shí)際能處理的并發(fā)請求數(shù)是:
最大并發(fā)請求數(shù) = (worker_processes * worker_connections) / 2
4 個 Worker、每個 65536 連接,理論上能處理 131072 個并發(fā)請求。
調(diào)優(yōu)建議:
生產(chǎn)環(huán)境建議設(shè)置為 65536
同時(shí)需要調(diào)整系統(tǒng)的文件描述符限制,因?yàn)槊總€連接占一個 FD
通過worker-rlimit-nofile參數(shù)設(shè)置 Worker 進(jìn)程的 FD 上限
data: worker-connections:"65536" max-worker-open-files:"131072"
2.2.3 worker_shutdown_timeout 配置
Nginx reload 時(shí)舊 Worker 進(jìn)程需要優(yōu)雅退出,worker-shutdown-timeout控制等待時(shí)間。默認(rèn) 240s。
data: worker-shutdown-timeout:"30s"
Ingress Nginx 在每次 Ingress 資源變更時(shí)都會觸發(fā) Nginx reload。如果舊 Worker 上還有長連接沒斷開,就會一直等到超時(shí)才強(qiáng)制關(guān)閉。設(shè)置過長會導(dǎo)致內(nèi)存中同時(shí)存在大量舊 Worker 進(jìn)程,設(shè)置過短會導(dǎo)致長連接被強(qiáng)制中斷。
30s 對大多數(shù) HTTP 服務(wù)來說足夠了。如果有 WebSocket 長連接場景,需要適當(dāng)調(diào)大。
2.3 連接復(fù)用與 Keep-Alive 調(diào)優(yōu)
2.3.1 客戶端側(cè) Keep-Alive
Keep-Alive 讓客戶端和 Nginx 之間復(fù)用 TCP 連接,避免每個請求都走三次握手。對性能的影響非常大,尤其是 HTTPS 場景下還能省掉 SSL 握手的開銷。
data: # 單個 Keep-Alive 連接上最多處理的請求數(shù),默認(rèn) 1000 keep-alive-requests:"10000" # Keep-Alive 連接的空閑超時(shí)時(shí)間,默認(rèn) 75s keep-alive:"75"
參數(shù)解讀:
keep-alive-requests:一個 Keep-Alive 連接上最多跑多少個請求后強(qiáng)制關(guān)閉。默認(rèn) 1000,高并發(fā)場景建議調(diào)到 10000。設(shè)太大的風(fēng)險(xiǎn)是單個連接占用內(nèi)存時(shí)間過長,但 10000 是個比較安全的值
keep-alive:連接空閑多久后關(guān)閉。75s 是個合理的默認(rèn)值,不需要改太大。設(shè)太大會導(dǎo)致空閑連接占用 Worker 的連接槽位
2.3.2 Upstream 側(cè) Keep-Alive
這是很多人忽略的關(guān)鍵配置。默認(rèn)情況下 Nginx 到 upstream(后端 Pod)的連接是短連接,每個請求都新建 TCP 連接再關(guān)閉。在高 QPS 場景下,光是 TCP 握手和揮手就能吃掉大量性能。
data: # 每個 Worker 到每個 upstream 保持的空閑長連接數(shù) upstream-keepalive-connections:"320" # upstream 長連接上最多處理的請求數(shù) upstream-keepalive-requests:"10000" # upstream 長連接的空閑超時(shí) upstream-keepalive-timeout:"60"
這組參數(shù)的影響有多大?實(shí)測數(shù)據(jù):同樣的 4C8G 配置,upstream 短連接模式下 QPS 約 3.5 萬,開啟 upstream Keep-Alive 后 QPS 直接飆到 7 萬+,提升接近一倍。原因很簡單——省掉了海量的 TCP 連接建立和銷毀開銷,同時(shí)減少了 TIME_WAIT 狀態(tài)的 socket 堆積。
upstream-keepalive-connections的取值邏輯:
這個值是每個 Worker 進(jìn)程到每個 upstream 保持的空閑連接數(shù)上限。計(jì)算方式:
建議值 = 預(yù)期 QPS / worker_processes / upstream_pod_count * avg_response_time
比如目標(biāo) 10 萬 QPS、4 個 Worker、10 個后端 Pod、平均響應(yīng)時(shí)間 20ms:
100000 / 4 / 10 * 0.02 = 50
理論上 50 就夠了,但要留余量應(yīng)對突發(fā)流量,所以設(shè) 320 是比較穩(wěn)妥的選擇。設(shè)太大會浪費(fèi)內(nèi)存(每個空閑連接占約 4KB),設(shè)太小會導(dǎo)致連接復(fù)用率下降。
2.4 緩沖區(qū)與超時(shí)參數(shù)優(yōu)化
2.4.1 代理緩沖區(qū)配置
Nginx 作為反向代理時(shí),會先把 upstream 的響應(yīng)讀到緩沖區(qū)里,再發(fā)給客戶端。如果緩沖區(qū)不夠大,響應(yīng)會被寫到磁盤臨時(shí)文件,I/O 性能直接崩盤。
data: # 代理緩沖區(qū)開關(guān),默認(rèn)開啟 proxy-buffering:"true" # 響應(yīng)頭緩沖區(qū)大小 proxy-buffer-size:"8k" # 響應(yīng)體緩沖區(qū):數(shù)量和單個大小 proxy-buffers-number:"8" # 單個緩沖區(qū)大?。ǚ?ConfigMap 直接參數(shù),通過 server-snippet 設(shè)置) proxy-body-size:"16m"
調(diào)優(yōu)建議:
proxy-buffer-size:用于存放響應(yīng)頭,8k 能覆蓋絕大多數(shù)場景。如果后端服務(wù)的響應(yīng)頭特別大(比如帶大量 Set-Cookie),需要調(diào)到 16k
響應(yīng)體緩沖區(qū)總大小 =proxy-buffers-number* 單個緩沖區(qū)大小。默認(rèn) 8 * 4k = 32k,對于返回大 JSON 的 API 可能不夠,建議調(diào)到 8 * 16k = 128k
如果響應(yīng)體超過緩沖區(qū)總大小,Nginx 會寫臨時(shí)文件??梢酝ㄟ^proxy-max-temp-file-size控制臨時(shí)文件上限,設(shè)為 0 表示禁止寫臨時(shí)文件(超出緩沖區(qū)的部分直接流式傳輸)
2.4.2 超時(shí)參數(shù)配置
超時(shí)參數(shù)配錯是生產(chǎn)事故的高頻原因。設(shè)太短,正常請求被誤殺;設(shè)太長,慢請求拖垮整個連接池。
data: # 連接 upstream 的超時(shí)(TCP 握手階段) proxy-connect-timeout:"5" # 從 upstream 讀取響應(yīng)的超時(shí) proxy-read-timeout:"60" # 向 upstream 發(fā)送請求的超時(shí) proxy-send-timeout:"60"
各超時(shí)參數(shù)的含義和建議值:
| 參數(shù) | 默認(rèn)值 | 建議值 | 說明 |
|---|---|---|---|
| proxy-connect-timeout | 5s | 5s | TCP 握手超時(shí),5s 足夠,設(shè)太長會導(dǎo)致故障 Pod 拖慢整體 |
| proxy-read-timeout | 60s | 60s | 等待 upstream 響應(yīng)的超時(shí),根據(jù)業(yè)務(wù)實(shí)際 RT 調(diào)整 |
| proxy-send-timeout | 60s | 60s | 發(fā)送請求到 upstream 的超時(shí),通常不需要改 |
| proxy-next-upstream-timeout | 0 | 5s | 重試下一個 upstream 的總超時(shí),0 表示不限制,建議設(shè) 5s |
關(guān)鍵配置:proxy-next-upstream控制什么情況下重試下一個 upstream:
data: proxy-next-upstream:"error timeout http_502 http_503 http_504" proxy-next-upstream-timeout:"5" proxy-next-upstream-tries:"3"
這個配置的意思是:如果 upstream 返回 502/503/504 或者連接超時(shí),自動重試下一個 Pod,最多重試 3 次,總超時(shí) 5s。對于冪等的 GET 請求很有用,但 POST/PUT 請求要謹(jǐn)慎,避免重復(fù)提交。
2.4.3 日志優(yōu)化:減少 I/O 開銷
Access log 是性能殺手之一。每個請求寫一行日志,10 萬 QPS 就是每秒 10 萬次磁盤寫入。
data: # 關(guān)閉 access log(激進(jìn)方案) disable-access-log:"false" # 開啟 access log 緩沖(推薦方案) access-log-params:"buffer=256k flush=5s" # 自定義日志格式,去掉不需要的字段減少 I/O 量 log-format-upstream:'$remote_addr - $request_method $host$uri $status $body_bytes_sent $request_time'
推薦方案:不要完全關(guān)閉 access log(排查問題需要),而是開啟緩沖寫入。buffer=256k flush=5s表示日志先寫到 256KB 的內(nèi)存緩沖區(qū),滿了或者每 5 秒刷一次盤。這樣把隨機(jī)小 I/O 合并成批量大 I/O,性能提升顯著。
對于不需要記錄日志的健康檢查路徑,可以通過 Annotation 單獨(dú)關(guān)閉:
metadata:
annotations:
nginx.ingress.kubernetes.io/server-snippet:|
location /healthz {
access_log off;
return 200 'ok';
}
2.5 SSL/TLS 性能優(yōu)化
2.5.1 SSL Session Cache
SSL/TLS 握手是 CPU 密集型操作,一次完整的 TLS 1.3 握手需要 1-RTT,TLS 1.2 需要 2-RTT。通過 Session Cache 可以讓客戶端復(fù)用之前的 SSL 會話,跳過完整握手流程。
data: # SSL Session 緩存大小,1MB 約存 4000 個 session ssl-session-cache-size:"50m" # Session 有效期 ssl-session-timeout:"1d" # 啟用 Session Tickets(TLS 1.2 場景) ssl-session-tickets:"true"
50MB 的 Session Cache 能存約 20 萬個 SSL Session,對于大多數(shù)場景綽綽有余。Session 復(fù)用率可以通過 Nginx 的 SSL 指標(biāo)監(jiān)控:
# 查看 SSL Session 復(fù)用率 kubectlexec-n ingress-nginx deploy/ingress-nginx-controller -- curl -s http://localhost:10246/nginx_status
2.5.2 OCSP Stapling
客戶端驗(yàn)證服務(wù)器證書時(shí)需要檢查證書是否被吊銷,默認(rèn)會去 CA 的 OCSP 服務(wù)器查詢,這個查詢可能耗時(shí)幾百毫秒。OCSP Stapling 讓 Nginx 預(yù)先獲取 OCSP 響應(yīng)并緩存,在 SSL 握手時(shí)直接發(fā)給客戶端,省掉客戶端的額外查詢。
data: enable-ocsp:"true"
注意事項(xiàng):
OCSP Stapling 需要 Nginx 能訪問 CA 的 OCSP 服務(wù)器,如果集群網(wǎng)絡(luò)策略限制了出站流量,需要放行
Let's Encrypt 的 OCSP 響應(yīng)有效期是 7 天,Nginx 會自動刷新
如果使用私有 CA 簽發(fā)的證書,需要確認(rèn) CA 支持 OCSP
2.5.3 TLS 協(xié)議版本與密碼套件
data: # 最低 TLS 版本 ssl-protocols:"TLSv1.2 TLSv1.3" # TLS 1.3 密碼套件(性能最優(yōu)選擇) ssl-ciphers:"TLS_AES_128_GCM_SHA256TLS_CHACHA20_POLY1305_SHA256ECDHE-RSA-AES128-GCM-SHA256ECDHE-RSA-AES256-GCM-SHA384" # 使用服務(wù)端優(yōu)先的密碼套件順序 ssl-prefer-server-ciphers:"on"
性能相關(guān)的選擇:
TLS 1.3 優(yōu)先:握手只需要 1-RTT(TLS 1.2 需要 2-RTT),且支持 0-RTT 恢復(fù)
AES-128-GCM 優(yōu)先于 AES-256-GCM:安全性差異可忽略,但 128 位性能更好
ECDSA 證書優(yōu)先于 RSA 證書:ECDSA P-256 簽名速度是 RSA 2048 的 10 倍以上。如果用 cert-manager 簽發(fā)證書,指定algorithm: ECDSA和size: 256
ChaCha20-Poly1305:在沒有 AES-NI 硬件加速的 ARM 平臺上性能更好
2.5.4 Early Data(0-RTT)
TLS 1.3 支持 0-RTT 恢復(fù),客戶端可以在第一個 TLS 消息中就攜帶應(yīng)用數(shù)據(jù),完全省掉握手延遲。但有重放攻擊風(fēng)險(xiǎn),只適用于冪等請求。
data: ssl-early-data:"true"
開啟后需要在后端服務(wù)中檢查Early-Data: 1請求頭,對非冪等請求做防重放處理。
2.6 負(fù)載均衡算法選擇
2.6.1 可選算法對比
Ingress Nginx 支持多種負(fù)載均衡算法,通過 ConfigMap 或 Annotation 配置:
| 算法 | ConfigMap 值 | 特點(diǎn) | 適用場景 |
|---|---|---|---|
| Round Robin | round_robin(默認(rèn)) | 輪詢分發(fā),簡單均勻 | 后端 Pod 配置相同、無狀態(tài)服務(wù) |
| IP Hash | ip-hash | 同一客戶端 IP 固定到同一 Pod | 需要會話保持但沒有分布式 Session |
| EWMA | ewma | 基于加權(quán)移動平均響應(yīng)時(shí)間 | 后端 Pod 性能不均勻 |
data: load-balance:"ewma"
2.6.2 EWMA 算法詳解
EWMA(Exponentially Weighted Moving Average)是 Ingress Nginx 提供的智能負(fù)載均衡算法,根據(jù)每個 upstream Pod 的實(shí)際響應(yīng)時(shí)間動態(tài)調(diào)整權(quán)重。響應(yīng)快的 Pod 分到更多流量,響應(yīng)慢的 Pod 自動降權(quán)。
為什么推薦 EWMA:
在混合節(jié)點(diǎn)集群中(比如部分 Pod 跑在高配機(jī)器、部分跑在低配機(jī)器),EWMA 能自動適應(yīng)性能差異
當(dāng)某個 Pod 出現(xiàn)性能退化(比如 GC 停頓、磁盤 I/O 抖動)時(shí),EWMA 會自動減少發(fā)往該 Pod 的流量
相比 Round Robin,EWMA 在后端性能不均勻時(shí)能提升 20%-40% 的整體吞吐量
注意事項(xiàng):
EWMA 在后端 Pod 完全同質(zhì)化的場景下和 Round Robin 差異不大
EWMA 的權(quán)重計(jì)算有一定延遲,對于突發(fā)性能變化的響應(yīng)不是瞬時(shí)的
如果后端服務(wù)的響應(yīng)時(shí)間波動很大(比如有些請求 10ms、有些 5s),EWMA 的效果會打折扣
2.6.3 會話保持配置
如果業(yè)務(wù)確實(shí)需要會話保持(Session Affinity),推薦用 Cookie 方式而不是 IP Hash:
metadata: annotations: nginx.ingress.kubernetes.io/affinity:"cookie" nginx.ingress.kubernetes.io/affinity-mode:"balanced" nginx.ingress.kubernetes.io/session-cookie-name:"INGRESSCOOKIE" nginx.ingress.kubernetes.io/session-cookie-max-age:"172800" nginx.ingress.kubernetes.io/session-cookie-samesite:"Strict"
Cookie 方式比 IP Hash 更精確,不會因?yàn)?NAT 網(wǎng)關(guān)導(dǎo)致大量用戶被哈希到同一個 Pod。affinity-mode: balanced會在 Pod 擴(kuò)縮容時(shí)自動重新平衡會話分布。
三、限流防護(hù)與內(nèi)核調(diào)優(yōu)
3.1 限流配置
3.1.1 全局限流
Ingress Nginx 內(nèi)置了基于 Lua 的限流模塊,支持按 IP、按 URI 等維度限流。限流不僅是防護(hù)手段,也是性能保障——防止突發(fā)流量打爆后端服務(wù)。
通過 Annotation 對單個 Ingress 配置限流:
metadata: annotations: # 每秒允許的請求數(shù)(令牌桶速率) nginx.ingress.kubernetes.io/limit-rps:"100" # 突發(fā)請求容量(令牌桶大小) nginx.ingress.kubernetes.io/limit-burst-multiplier:"5" # 限流時(shí)返回的 HTTP 狀態(tài)碼 nginx.ingress.kubernetes.io/limit-rate-after:"0" # 并發(fā)連接數(shù)限制 nginx.ingress.kubernetes.io/limit-connections:"50"
參數(shù)解讀:
limit-rps: 100+limit-burst-multiplier: 5:表示每秒穩(wěn)定放行 100 個請求,允許瞬間突發(fā)到 500 個(100 * 5)。令牌桶算法會平滑突發(fā)流量
limit-connections: 50:單個 IP 最多同時(shí)保持 50 個連接。防止單個客戶端占用過多連接資源
3.1.2 限流的粒度控制
默認(rèn)限流是按客戶端 IP 維度的。但在有 CDN 或負(fù)載均衡器的場景下,所有請求的源 IP 都是 CDN 的 IP,按 IP 限流會誤傷正常用戶。
解決方案是使用真實(shí)客戶端 IP:
# ConfigMap 全局配置 data: use-forwarded-headers:"true" forwarded-for-header:"X-Forwarded-For" compute-full-forwarded-for:"true"
同時(shí)在 Annotation 中指定限流的 key:
metadata: annotations: nginx.ingress.kubernetes.io/limit-rps:"100" # 使用 X-Forwarded-For 頭中的真實(shí)客戶端 IP 作為限流 key nginx.ingress.kubernetes.io/limit-whitelist:"10.0.0.0/8,172.16.0.0/12"
limit-whitelist可以把內(nèi)部網(wǎng)段排除在限流之外,避免健康檢查和內(nèi)部調(diào)用被限。
3.1.3 全局速率限制
對于需要全局限流(不是按 IP,而是整體 QPS 上限)的場景,可以通過 ConfigMap 的global-rate-limit系列參數(shù)配置:
data: global-rate-limit-memcached-host:"memcached.ingress-nginx.svc.cluster.local" global-rate-limit-memcached-port:"11211" global-rate-limit-status-code:"429"
全局限流依賴 Memcached 做分布式計(jì)數(shù),適用于多副本 Ingress Nginx 的場景。單副本場景用本地限流就夠了。
3.1.4 WAF 防護(hù)
Ingress Nginx 支持集成 ModSecurity 作為 WAF(Web Application Firewall):
data: enable-modsecurity:"true" enable-owasp-modsecurity-crs:"true" modsecurity-snippet:| SecRuleEngine On SecRequestBodyLimit 10485760 SecAuditLogType Serial SecAuditLog /dev/stdout
性能影響:ModSecurity 會對每個請求做規(guī)則匹配,開啟 OWASP CRS 全量規(guī)則集大約會降低 15%-25% 的 QPS。建議只在面向公網(wǎng)的 Ingress 上開啟,內(nèi)部服務(wù)間調(diào)用不需要。
如果性能影響不可接受,可以只開啟部分規(guī)則:
metadata:
annotations:
nginx.ingress.kubernetes.io/modsecurity-snippet:|
SecRuleEngine On
# 只開啟 SQL 注入和 XSS 防護(hù)
SecRule REQUEST_URI "@rx (?i)(union|select|insert|update|delete|drop)"
"id:1001,phase:2,deny,status:403,msg:'SQL Injection Detected'"
3.2 內(nèi)核參數(shù)調(diào)優(yōu)
Nginx 的性能上限不只取決于 Nginx 自身的配置,底層的 Linux 內(nèi)核參數(shù)同樣關(guān)鍵。在容器環(huán)境下,部分內(nèi)核參數(shù)需要通過 Pod 的securityContext或initContainers來設(shè)置。
3.2.1 TCP 連接相關(guān)參數(shù)
# 通過 initContainer 設(shè)置內(nèi)核參數(shù)
apiVersion:apps/v1
kind:Deployment
metadata:
name:ingress-nginx-controller
spec:
template:
spec:
initContainers:
-name:sysctl
image:busybox:1.37
command:
-sh
--c
-|
sysctl -w net.core.somaxconn=65535
sysctl -w net.ipv4.tcp_max_syn_backlog=65535
sysctl -w net.ipv4.ip_local_port_range="1024 65535"
sysctl -w net.ipv4.tcp_tw_reuse=1
sysctl -w net.ipv4.tcp_fin_timeout=15
sysctl -w net.core.netdev_max_backlog=65535
sysctl -w net.ipv4.tcp_max_tw_buckets=262144
securityContext:
privileged:true
各參數(shù)說明:
| 參數(shù) | 默認(rèn)值 | 建議值 | 作用 |
|---|---|---|---|
| net.core.somaxconn | 4096 | 65535 | listen() 的 backlog 隊(duì)列上限,直接影響并發(fā)連接能力 |
| net.ipv4.tcp_max_syn_backlog | 1024 | 65535 | SYN 隊(duì)列長度,防止 SYN Flood 時(shí)丟棄正常連接 |
| net.ipv4.ip_local_port_range | 32768-60999 | 1024-65535 | 可用的本地端口范圍,影響到 upstream 的連接數(shù)上限 |
| net.ipv4.tcp_tw_reuse | 0 | 1 | 允許復(fù)用 TIME_WAIT 狀態(tài)的 socket,減少端口耗盡風(fēng)險(xiǎn) |
| net.ipv4.tcp_fin_timeout | 60 | 15 | FIN_WAIT_2 超時(shí)時(shí)間,加速連接回收 |
| net.core.netdev_max_backlog | 1000 | 65535 | 網(wǎng)卡接收隊(duì)列長度,防止高流量下丟包 |
3.2.2 文件描述符限制
每個 TCP 連接占一個文件描述符,10 萬并發(fā)連接就需要 10 萬個 FD。容器內(nèi)的 FD 限制需要在 Pod spec 中設(shè)置:
spec: containers: -name:controller # Ingress Nginx Controller 的 ConfigMap 參數(shù) # max-worker-open-files 會設(shè)置 worker_rlimit_nofile securityContext: # 容器級別的 ulimit 通過 runtimeClass 或 containerd 配置
在 ConfigMap 中設(shè)置:
data: max-worker-open-files:"131072"
同時(shí)確保宿主機(jī)的/etc/security/limits.conf或 systemd 的LimitNOFILE設(shè)置足夠大。
3.2.3 TCP 緩沖區(qū)調(diào)優(yōu)
# 宿主機(jī)級別設(shè)置(需要 DaemonSet 或節(jié)點(diǎn)初始化腳本) sysctl -w net.core.rmem_max=16777216 sysctl -w net.core.wmem_max=16777216 sysctl -w net.ipv4.tcp_rmem="4096 87380 16777216" sysctl -w net.ipv4.tcp_wmem="4096 65536 16777216" sysctl -w net.ipv4.tcp_mem="786432 1048576 1572864"
參數(shù)說明:
tcp_rmem/tcp_wmem:TCP 接收/發(fā)送緩沖區(qū)的最小值、默認(rèn)值、最大值。默認(rèn)的最大值通常偏小,在高帶寬場景下會成為瓶頸
tcp_mem:系統(tǒng)級 TCP 內(nèi)存使用的閾值(單位是頁,通常 4KB/頁)。三個值分別是低水位、壓力水位、高水位
3.2.4 啟用 BBR 擁塞控制
BBR(Bottleneck Bandwidth and Round-trip propagation time)是 Google 開發(fā)的 TCP 擁塞控制算法,相比傳統(tǒng)的 CUBIC 算法,在高延遲和有丟包的網(wǎng)絡(luò)環(huán)境下性能提升顯著。
# 檢查是否支持 BBR sysctl net.ipv4.tcp_available_congestion_control # 啟用 BBR sysctl -w net.core.default_qdisc=fq sysctl -w net.ipv4.tcp_congestion_control=bbr
Linux 6.8+ 內(nèi)核默認(rèn)支持 BBR v3,建議在所有節(jié)點(diǎn)上啟用。對于跨地域、跨云的流量場景,BBR 的效果尤其明顯。
四、最佳實(shí)踐
4.1 完整的高性能 ConfigMap 配置
把前面所有調(diào)優(yōu)參數(shù)匯總成一份完整的 ConfigMap:
apiVersion:v1 kind:ConfigMap metadata: name:ingress-nginx-controller namespace:ingress-nginx data: # Worker 配置 worker-processes:"auto" worker-connections:"65536" max-worker-open-files:"131072" worker-shutdown-timeout:"30s" # Keep-Alive 配置 keep-alive-requests:"10000" keep-alive:"75" upstream-keepalive-connections:"320" upstream-keepalive-requests:"10000" upstream-keepalive-timeout:"60" # 緩沖區(qū)配置 proxy-buffering:"true" proxy-buffer-size:"8k" proxy-buffers-number:"8" # 超時(shí)配置 proxy-connect-timeout:"5" proxy-read-timeout:"60" proxy-send-timeout:"60" proxy-next-upstream:"error timeout http_502 http_503 http_504" proxy-next-upstream-timeout:"5" proxy-next-upstream-tries:"3" # SSL 配置 ssl-protocols:"TLSv1.2 TLSv1.3" ssl-ciphers:"TLS_AES_128_GCM_SHA256TLS_CHACHA20_POLY1305_SHA256ECDHE-RSA-AES128-GCM-SHA256" ssl-prefer-server-ciphers:"on" ssl-session-cache-size:"50m" ssl-session-timeout:"1d" ssl-session-tickets:"true" enable-ocsp:"true" # 負(fù)載均衡 load-balance:"ewma" # 日志優(yōu)化 access-log-params:"buffer=256k flush=5s" log-format-upstream:'$remote_addr - $request_method $host$uri $status $body_bytes_sent $request_time' # 其他優(yōu)化 use-gzip:"true" gzip-level:"3" enable-brotli:"true" brotli-level:"3" use-forwarded-headers:"true" compute-full-forwarded-for:"true" enable-real-ip:"true"
關(guān)于壓縮級別的說明:gzip 和 brotli 的壓縮級別設(shè)為 3 而不是更高,是因?yàn)閴嚎s級別越高 CPU 消耗越大,但壓縮率的邊際收益遞減。級別 3 在壓縮率和 CPU 消耗之間取得了最佳平衡。
4.2 Pod 資源配置建議
apiVersion:apps/v1
kind:Deployment
metadata:
name:ingress-nginx-controller
namespace:ingress-nginx
spec:
replicas:2
template:
spec:
# 調(diào)度到專用節(jié)點(diǎn),避免和業(yè)務(wù) Pod 爭搶資源
nodeSelector:
node-role.kubernetes.io/ingress:"true"
tolerations:
-key:"node-role.kubernetes.io/ingress"
operator:"Exists"
effect:"NoSchedule"
# 反親和性,確保兩個副本不在同一節(jié)點(diǎn)
affinity:
podAntiAffinity:
requiredDuringSchedulingIgnoredDuringExecution:
-labelSelector:
matchExpressions:
-key:app.kubernetes.io/name
operator:In
values:["ingress-nginx"]
topologyKey:kubernetes.io/hostname
containers:
-name:controller
resources:
requests:
cpu:"4"
memory:"8Gi"
limits:
cpu:"4"
memory:"8Gi"
# 設(shè)置 CPU 親和性,減少 NUMA 跨節(jié)點(diǎn)訪問
# 需要配合 CPU Manager 的 static 策略
關(guān)鍵點(diǎn):
requests 等于 limits:確保 Pod 獲得 Guaranteed QoS,不會被驅(qū)逐,CPU 不會被節(jié)流
專用節(jié)點(diǎn):Ingress Nginx 是流量入口,和業(yè)務(wù) Pod 混部會互相影響。用 nodeSelector + taint 隔離
反親和性:兩個副本分散到不同節(jié)點(diǎn),避免單點(diǎn)故障
CPU Manager static 策略:讓 Worker 進(jìn)程綁定到固定 CPU 核心,減少上下文切換和緩存失效
4.3 優(yōu)雅關(guān)閉與滾動更新
Ingress Nginx 的滾動更新如果配置不當(dāng),會導(dǎo)致流量中斷。關(guān)鍵是確保舊 Pod 在停止接收新連接后,有足夠時(shí)間處理完存量請求。
spec:
template:
spec:
terminationGracePeriodSeconds:60
containers:
-name:controller
lifecycle:
preStop:
exec:
command:
-/wait-shutdown
strategy:
type:RollingUpdate
rollingUpdate:
maxUnavailable:0
maxSurge:1
配置邏輯:
maxUnavailable: 0:滾動更新時(shí)不允許減少可用副本數(shù),先起新的再停舊的
maxSurge: 1:最多多出一個副本
terminationGracePeriodSeconds: 60:給舊 Pod 60 秒的優(yōu)雅關(guān)閉時(shí)間
/wait-shutdown:Ingress Nginx 內(nèi)置的優(yōu)雅關(guān)閉腳本,會等待存量連接處理完畢
五、壓測驗(yàn)證與故障排查
5.1 壓測方法
調(diào)優(yōu)不壓測等于白調(diào)。每次參數(shù)變更后都需要壓測驗(yàn)證效果,確認(rèn)性能提升而不是引入新問題。
5.1.1 使用 wrk 進(jìn)行基準(zhǔn)壓測
wrk 是輕量級的 HTTP 壓測工具,適合快速驗(yàn)證單接口性能:
# 安裝 wrk apt install -y wrk # 基礎(chǔ)壓測:4 線程、200 并發(fā)連接、持續(xù) 30 秒 wrk -t4 -c200 -d30s https://your-domain.com/api/health # 帶 Keep-Alive 的壓測(wrk 默認(rèn)就是 Keep-Alive) wrk -t8 -c1000 -d60s --latency https://your-domain.com/api/health # 使用 Lua 腳本自定義請求 wrk -t4 -c200 -d30s -s post.lua https://your-domain.com/api/data
wrk 的 Lua 腳本示例:
-- post.lua:模擬 POST 請求 wrk.method ="POST" wrk.body ='{"key": "value"}' wrk.headers["Content-Type"] ="application/json"
解讀 wrk 輸出:
Running 30stest@ https://your-domain.com/api/health 8 threads and 1000 connections Thread Stats Avg Stdev Max +/- Stdev Latency 1.23ms 0.56ms 15.67ms 89.12% Req/Sec 12.85k 1.23k 15.67k 72.34% Latency Distribution 50% 1.12ms 75% 1.45ms 90% 1.89ms 99% 3.45ms 3078456 requestsin30.00s, 1.23GBread Requests/sec: 102615.20 Transfer/sec: 42.01MB
關(guān)注的核心指標(biāo):Requests/sec(QPS)、p99 延遲、是否有 Socket errors。
5.1.2 使用 vegeta 進(jìn)行恒定速率壓測
wrk 是盡可能快地發(fā)請求,但生產(chǎn)環(huán)境的流量模式通常是恒定速率。vegeta 支持指定固定 QPS 進(jìn)行壓測,更貼近真實(shí)場景:
# 安裝 vegeta go install github.com/tsenart/vegeta/v12@latest # 恒定 50000 QPS 壓測 60 秒 echo"GET https://your-domain.com/api/health"| vegeta attack -rate=50000/s -duration=60s | vegeta report # 階梯式壓測:從 10000 QPS 逐步增加到 100000 QPS echo"GET https://your-domain.com/api/health"| vegeta attack -rate=10000/s -duration=30s > results_10k.bin echo"GET https://your-domain.com/api/health"| vegeta attack -rate=50000/s -duration=30s > results_50k.bin echo"GET https://your-domain.com/api/health"| vegeta attack -rate=100000/s -duration=30s > results_100k.bin # 生成 HTML 報(bào)告 vegeta report -type=json results_100k.bin | vegeta plot > report.html
vegeta 的優(yōu)勢:
恒定速率模式能準(zhǔn)確測出系統(tǒng)在特定 QPS 下的延遲表現(xiàn)
支持輸出 HDR Histogram,精確到 p99.9 延遲
階梯式壓測能找到系統(tǒng)的性能拐點(diǎn)——QPS 從多少開始延遲急劇上升
5.1.3 壓測注意事項(xiàng)
壓測客戶端不能成為瓶頸:單臺機(jī)器的端口數(shù)有限(約 6 萬),壓 10 萬 QPS 可能需要多臺壓測機(jī)
壓測環(huán)境要隔離:不要在生產(chǎn)集群上直接壓測,用獨(dú)立的壓測環(huán)境
關(guān)注系統(tǒng)指標(biāo):壓測時(shí)同步監(jiān)控 CPU、內(nèi)存、網(wǎng)絡(luò)帶寬、連接數(shù)、FD 使用量
預(yù)熱:壓測前先用低流量預(yù)熱 10-20 秒,讓連接池和緩存建立起來
多輪對比:每次只改一個參數(shù),對比前后的壓測結(jié)果,避免多個變量干擾
5.1.4 壓測時(shí)的監(jiān)控命令
# 實(shí)時(shí)查看 Nginx 連接狀態(tài) kubectlexec-n ingress-nginx deploy/ingress-nginx-controller -- curl -s http://localhost:10246/nginx_status # 輸出示例 # Active connections: 12345 # server accepts handled requests # 98765432 98765432 123456789 # Reading: 123 Writing: 456 Waiting: 11766 # 查看 Worker 進(jìn)程的 CPU 使用率 kubectlexec-n ingress-nginx deploy/ingress-nginx-controller -- top -bn1 -p $(pgrep -d','nginx) # 查看 TCP 連接狀態(tài)分布 kubectlexec-n ingress-nginx deploy/ingress-nginx-controller -- ss -s # 查看 Prometheus 指標(biāo) kubectlexec-n ingress-nginx deploy/ingress-nginx-controller -- curl -s http://localhost:10254/metrics | grep nginx_ingress_controller_requests
5.2 故障排查
5.2.1 常見性能問題排查表
| 現(xiàn)象 | 可能原因 | 排查方法 | 解決方案 |
|---|---|---|---|
| QPS 上不去,CPU 未打滿 | worker_connections 不夠 | 檢查nginx_connections_active是否接近上限 | 調(diào)大 worker-connections |
| QPS 上不去,CPU 打滿 | SSL 握手消耗過多 CPU | 檢查 SSL Session 復(fù)用率 | 調(diào)大 ssl-session-cache-size,使用 ECDSA 證書 |
| 延遲突然飆高 | upstream 連接復(fù)用率低 | 檢查 TIME_WAIT 連接數(shù) | 開啟 upstream-keepalive-connections |
| 502 錯誤增多 | upstream Pod 不可用或超時(shí) | 檢查 upstream Pod 狀態(tài)和日志 | 調(diào)整 proxy-next-upstream 重試策略 |
| 內(nèi)存持續(xù)增長 | 舊 Worker 進(jìn)程未退出 | ps aux | grep nginx 檢查進(jìn)程數(shù) | 調(diào)整 worker-shutdown-timeout |
| 連接被拒絕 | somaxconn 或 FD 限制 | dmesg | grep "dropped" | 調(diào)大內(nèi)核參數(shù)和 FD 限制 |
5.2.2 關(guān)鍵監(jiān)控指標(biāo)
用 Prometheus 采集 Ingress Nginx 的指標(biāo),配合 Grafana 做可視化。推薦監(jiān)控的核心指標(biāo):
# Prometheus 告警規(guī)則示例
groups:
-name:ingress-nginx
rules:
# QPS 突降告警
-alert:IngressNginxQPSDrop
expr:|
rate(nginx_ingress_controller_requests[5m]) <
? ? ? rate(nginx_ingress_controller_requests[5m] offset 1h) * 0.5
? ??for:5m
? ??labels:
? ? ??severity:warning
? ??annotations:
? ? ??summary:"Ingress Nginx QPS 下降超過 50%"
# p99 延遲告警
-alert:IngressNginxHighLatency
? ??expr:|
? ? ? histogram_quantile(0.99,
? ? ? ? rate(nginx_ingress_controller_request_duration_seconds_bucket[5m])
? ? ? ) > 1
for:5m
labels:
severity:critical
annotations:
summary:"Ingress Nginx p99 延遲超過 1 秒"
# 5xx 錯誤率告警
-alert:IngressNginxHigh5xxRate
expr:|
sum(rate(nginx_ingress_controller_requests{status=~"5.."}[5m])) /
sum(rate(nginx_ingress_controller_requests[5m])) > 0.01
for:5m
labels:
severity:critical
annotations:
summary:"Ingress Nginx 5xx 錯誤率超過 1%"
# 連接數(shù)接近上限
-alert:IngressNginxConnectionsHigh
expr:|
nginx_ingress_controller_nginx_process_connections >
nginx_ingress_controller_nginx_process_connections_total * 0.8
for:5m
labels:
severity:warning
annotations:
summary:"Ingress Nginx 活躍連接數(shù)超過 80%"
5.2.3 日志排查技巧
# 查看最近的 5xx 錯誤 kubectl logs -n ingress-nginx deploy/ingress-nginx-controller --tail=1000 | grep" 50[0-9] " # 查看 upstream 超時(shí)的請求 kubectl logs -n ingress-nginx deploy/ingress-nginx-controller --tail=1000 | grep"upstream timed out" # 查看 Nginx 錯誤日志 kubectlexec-n ingress-nginx deploy/ingress-nginx-controller -- tail -100 /var/log/nginx/error.log # 查看 Nginx reload 頻率(頻繁 reload 影響性能) kubectl logs -n ingress-nginx deploy/ingress-nginx-controller --tail=5000 | grep"Backend successfully reloaded"| wc -l
Nginx reload 頻率過高的問題:每次 Ingress/Service/Endpoint 變更都會觸發(fā) reload。在大規(guī)模集群中(幾百個 Ingress 規(guī)則),頻繁 reload 會導(dǎo)致性能抖動。Ingress Nginx Controller 1.9+ 引入了動態(tài)配置更新機(jī)制,upstream 變更不再需要 reload,但 Ingress 規(guī)則變更仍然需要。減少不必要的 Ingress 變更是降低 reload 頻率的關(guān)鍵。
5.3 Gateway API 遷移路徑
5.3.1 為什么要關(guān)注 Gateway API
Ingress API 從 Kubernetes 1.1 就存在了,設(shè)計(jì)上有不少歷史包袱:
表達(dá)能力有限:不支持 HTTP 頭匹配、請求鏡像、流量拆分等高級路由功能,只能靠 Annotation 擴(kuò)展,而 Annotation 是非標(biāo)準(zhǔn)化的
角色模型單一:Ingress 資源把基礎(chǔ)設(shè)施配置和應(yīng)用路由混在一起,集群管理員和應(yīng)用開發(fā)者沒有清晰的職責(zé)邊界
跨實(shí)現(xiàn)不可移植:不同 Ingress Controller 的 Annotation 完全不同,從 Nginx 遷移到 Envoy 基本要重寫所有配置
Gateway API 是 Kubernetes SIG-Network 設(shè)計(jì)的下一代流量管理標(biāo)準(zhǔn),在 Kubernetes 1.31 中已經(jīng) GA。它解決了上述所有問題:
豐富的路由能力:原生支持 HTTP 頭匹配、路徑重寫、請求鏡像、加權(quán)流量拆分
分層角色模型:GatewayClass(平臺團(tuán)隊(duì))-> Gateway(集群管理員)-> HTTPRoute(應(yīng)用開發(fā)者),職責(zé)清晰
跨實(shí)現(xiàn)可移植:標(biāo)準(zhǔn)化的 API,不同實(shí)現(xiàn)之間可以無縫遷移
5.3.2 Ingress Nginx 對 Gateway API 的支持
Ingress Nginx Controller 從 1.11 版本開始實(shí)驗(yàn)性支持 Gateway API。啟用方式:
# 安裝 Gateway API CRD kubectl apply -f https://github.com/kubernetes-sigs/gateway-api/releases/download/v1.2.1/standard-install.yaml # 在 Ingress Nginx Controller 啟動參數(shù)中啟用 Gateway API # 添加 --enable-gateway-api 標(biāo)志
# Helm values 配置 controller: extraArgs: enable-gateway-api:"true"
5.3.3 從 Ingress 到 HTTPRoute 的遷移示例
一個典型的 Ingress 資源:
# 舊的 Ingress 配置
apiVersion:networking.k8s.io/v1
kind:Ingress
metadata:
name:my-app
annotations:
nginx.ingress.kubernetes.io/rewrite-target:/
nginx.ingress.kubernetes.io/limit-rps:"100"
spec:
ingressClassName:nginx
tls:
-hosts:
-app.example.com
secretName:app-tls
rules:
-host:app.example.com
http:
paths:
-path:/api
pathType:Prefix
backend:
service:
name:api-service
port:
number:80
遷移到 Gateway API 后:
# GatewayClass(平臺團(tuán)隊(duì)管理)
apiVersion:gateway.networking.k8s.io/v1
kind:GatewayClass
metadata:
name:nginx
spec:
controllerName:k8s.io/ingress-nginx
---
# Gateway(集群管理員管理)
apiVersion:gateway.networking.k8s.io/v1
kind:Gateway
metadata:
name:main-gateway
namespace:ingress-nginx
spec:
gatewayClassName:nginx
listeners:
-name:https
protocol:HTTPS
port:443
tls:
mode:Terminate
certificateRefs:
-name:app-tls
allowedRoutes:
namespaces:
from:All
---
# HTTPRoute(應(yīng)用開發(fā)者管理)
apiVersion:gateway.networking.k8s.io/v1
kind:HTTPRoute
metadata:
name:my-app
namespace:default
spec:
parentRefs:
-name:main-gateway
namespace:ingress-nginx
hostnames:
-app.example.com
rules:
-matches:
-path:
type:PathPrefix
value:/api
filters:
-type:URLRewrite
urlRewrite:
path:
type:ReplacePrefixMatch
replacePrefixMatch:/
backendRefs:
-name:api-service
port:80
5.3.4 遷移建議
Gateway API 是未來方向,但不需要急著全量遷移。推薦的漸進(jìn)式遷移策略:
第一階段:共存。在集群中同時(shí)部署 Ingress 和 Gateway API 資源,新服務(wù)用 HTTPRoute,舊服務(wù)保持 Ingress 不動。Ingress Nginx Controller 同時(shí)支持兩種 API
第二階段:逐步遷移。按業(yè)務(wù)線逐步把 Ingress 資源轉(zhuǎn)換為 HTTPRoute,每次遷移后做流量驗(yàn)證
第三階段:清理。所有服務(wù)遷移完成后,移除舊的 Ingress 資源
遷移過程中的性能注意事項(xiàng):
Gateway API 和 Ingress API 共存時(shí),Ingress Nginx Controller 需要同時(shí) watch 兩種資源,會略微增加內(nèi)存消耗
HTTPRoute 的路由匹配邏輯和 Ingress 有細(xì)微差異,遷移后需要驗(yàn)證路由行為是否一致
Gateway API 目前還不支持 Ingress Nginx 的所有 Annotation 功能,遷移前需要確認(rèn)所用的 Annotation 是否有對應(yīng)的 Gateway API 替代方案
長期來看,如果團(tuán)隊(duì)對 Envoy 生態(tài)更感興趣,可以考慮直接遷移到 Envoy Gateway 或 Cilium Gateway API 實(shí)現(xiàn)。Gateway API 的標(biāo)準(zhǔn)化意味著從 Nginx 遷移到 Envoy 只需要替換 GatewayClass,HTTPRoute 資源完全不用改。
六、總結(jié)
6.1 調(diào)優(yōu)效果對比
把本文涉及的所有調(diào)優(yōu)項(xiàng)匯總,對比默認(rèn)配置和優(yōu)化配置在 4C8G 單 Pod 上的壓測結(jié)果:
| 指標(biāo) | 默認(rèn)配置 | 優(yōu)化后配置 | 提升幅度 |
|---|---|---|---|
| QPS(HTTP) | ~25,000 | ~110,000 | 340% |
| QPS(HTTPS) | ~15,000 | ~85,000 | 467% |
| p99 延遲(10 萬 QPS) | 超時(shí) | 3.2ms | - |
| 最大并發(fā)連接數(shù) | ~16,000 | ~130,000 | 712% |
| SSL Session 復(fù)用率 | ~30% | ~92% | 207% |
| upstream 連接復(fù)用率 | 0%(短連接) | ~95% | - |
提升最大的三個調(diào)優(yōu)項(xiàng)依次是:upstream Keep-Alive(連接復(fù)用)、SSL Session Cache + ECDSA 證書、內(nèi)核參數(shù)調(diào)優(yōu)。這三項(xiàng)加起來貢獻(xiàn)了 80% 以上的性能提升。
6.2 調(diào)優(yōu)優(yōu)先級排序
不是所有參數(shù)都需要一次性調(diào)完。按照投入產(chǎn)出比排序,推薦的調(diào)優(yōu)順序:
| 優(yōu)先級 | 調(diào)優(yōu)項(xiàng) | 預(yù)期提升 | 實(shí)施難度 |
|---|---|---|---|
| P0 | upstream Keep-Alive | 80%-100% | 低,改 ConfigMap |
| P0 | worker_connections + FD 限制 | 30%-50% | 低,改 ConfigMap |
| P1 | SSL Session Cache + ECDSA 證書 | 50%-80%(HTTPS 場景) | 中,需要換證書 |
| P1 | 內(nèi)核參數(shù)(somaxconn/tw_reuse) | 20%-30% | 中,需要 initContainer |
| P2 | 日志緩沖寫入 | 10%-15% | 低,改 ConfigMap |
| P2 | EWMA 負(fù)載均衡 | 10%-20%(異構(gòu)環(huán)境) | 低,改 ConfigMap |
| P3 | BBR 擁塞控制 | 5%-15%(高延遲網(wǎng)絡(luò)) | 中,需要節(jié)點(diǎn)配置 |
| P3 | 0-RTT Early Data | 5%-10%(TLS 1.3) | 低,但有安全風(fēng)險(xiǎn) |
6.3 技術(shù)要點(diǎn)回顧
upstream Keep-Alive 是性能提升的最大杠桿。默認(rèn)的短連接模式在高 QPS 下會產(chǎn)生海量 TCP 握手和 TIME_WAIT,開啟 upstream-keepalive-connections 后性能直接翻倍
必須設(shè)置 CPU limit。不設(shè) limit 的情況下 worker_processes auto 會讀取宿主機(jī)核心數(shù),導(dǎo)致 Worker 進(jìn)程數(shù)遠(yuǎn)超實(shí)際可用 CPU,性能反而下降
SSL 優(yōu)化的核心是減少握手次數(shù)。Session Cache、OCSP Stapling、ECDSA 證書、TLS 1.3 這四項(xiàng)組合起來,能把 HTTPS 的性能損耗從 40% 降到 10% 以內(nèi)
內(nèi)核參數(shù)是隱形天花板。somaxconn、FD 限制、端口范圍這些參數(shù)不調(diào),Nginx 層面再怎么優(yōu)化也突破不了系統(tǒng)層的限制
日志不要關(guān),要緩沖。buffer=256k flush=5s 的緩沖寫入方案在保留排查能力的同時(shí)大幅降低 I/O 開銷
壓測要用恒定速率工具。vegeta 的恒定速率模式比 wrk 的最大壓力模式更能反映真實(shí)場景下的性能表現(xiàn)
-
模型
+關(guān)注
關(guān)注
1文章
3751瀏覽量
52093 -
nginx
+關(guān)注
關(guān)注
0文章
186瀏覽量
13105 -
kubernetes
+關(guān)注
關(guān)注
0文章
263瀏覽量
9492
原文標(biāo)題:Ingress Nginx 性能調(diào)優(yōu):單機(jī) 10 萬 QPS 的配置秘籍
文章出處:【微信號:magedu-Linux,微信公眾號:馬哥Linux運(yùn)維】歡迎添加關(guān)注!文章轉(zhuǎn)載請注明出處。
發(fā)布評論請先 登錄
Kubernetes Ingress 高可靠部署最佳實(shí)踐
基于全HDD aarch64服務(wù)器的Ceph性能調(diào)優(yōu)實(shí)踐總結(jié)
機(jī)器學(xué)習(xí)如何調(diào)優(yōu)數(shù)據(jù)庫
如何對電機(jī)進(jìn)行調(diào)優(yōu)?調(diào)優(yōu)的好處是什么?
APISIX Ingress VS Ingress NGINX詳細(xì)對比
高性能Nginx HTTPS調(diào)優(yōu)-如何為HTTPS提速30%
鴻蒙開發(fā)實(shí)戰(zhàn):【性能調(diào)優(yōu)組件】
Nginx性能優(yōu)化終極指南
Ingress Nginx性能調(diào)優(yōu)配置方案
評論