本文主要為您介紹Nginx Ingress常見問題的處理方法。
Ingress支援哪些SSL/TLS版本?
Ingress-Nginx預設支援TLS V1.2及V1.3版本,對於部分舊版本的瀏覽器,或者移動用戶端TLS版本低於1.2時,會導致用戶端在與Ingress-Nginx服務SSL版本協商時報錯。
修改kube-system/nginx-configuration configmap
添加以下配置,以啟用Ingress-Nginx對更多TLS版本的支援。具體操作,請參見TLS/HTTPS。
Nginx Ingress Controller 1.7.0及以後版本,如要啟用TLS v1.0與TLS v1.1,需要將@SECLEVEL=0
添加到ssl-ciphers
中。
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:DHE-RSA-CHACHA20-POLY1305:ECDHE-ECDSA-AES128-SHA256:ECDHE-RSA-AES128-SHA256:ECDHE-ECDSA-AES128-SHA:ECDHE-RSA-AES128-SHA:ECDHE-ECDSA-AES256-SHA384:ECDHE-RSA-AES256-SHA384:ECDHE-ECDSA-AES256-SHA:ECDHE-RSA-AES256-SHA:DHE-RSA-AES128-SHA256:DHE-RSA-AES256-SHA256:AES128-GCM-SHA256:AES256-GCM-SHA384:AES128-SHA256:AES256-SHA256:AES128-SHA:AES256-SHA:DES-CBC3-SHA"
ssl-protocols: "TLSv1 TLSv1.1 TLSv1.2 TLSv1.3"
Ingress L7要求標頭預設是透傳的嗎?
Ingress-Nginx預設透傳用戶端的要求標頭,有些不符合HTTP規則的要求標頭(例如Mobile Version),在轉寄到後端服務前會被過濾掉。為了不過濾掉這類要求標頭,您可以執行kubectl edit cm -n kube-system nginx-configuration
命令在ConfigMap中添加配置。更多資訊,請參見ConfigMap。
enable-underscores-in-headers: true
後端服務為HTTPS服務訪問時是否可以通過Ingress-Nginx轉寄?
對於後端業務是HTTPS服務,但同樣希望可以通過Ingress-Nginx轉寄時,執行以下命令,在Ingress資源配置中添加以下Annotation。
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: xxxx
annotations:
# 注意這裡:必須指定後端服務為HTTPS服務。
nginx.ingress.kubernetes.io/backend-protocol: "HTTPS"
Ingress L7透傳用戶端IP嗎?
Ingress-Nginx預設會通過X-Forwarded-For和X-Real-IP來透傳用戶端IP,但是當用戶端主動在要求標頭裡指定了X-Forwarded-For和X-Real-IP時,會導致服務端無法擷取到真實的用戶端IP。
您可以執行kubectl edit cm -n kube-system nginx-configuration
命令在ConfigMap中添加配置,以實現Ingress,L7透傳用戶端IP。
compute-full-forwarded-for: "true"
forwarded-for-header: "X-Forwarded-For"
use-forwarded-headers: "true"
如果在Nginx ingress之前有多層代理,您需要根據proxy-real-ip-cidr參數對配置進行調整,將前置代理的IP地址以CIDR格式添加到proxy-real-ip-cidr
中,多個CIDR之間用逗號分隔。詳細資料請參見使用WAF或透明WAF。
proxy-real-ip-cidr: "0.0.0.0/0,::/0"
在IPv6情境下,如果Nginx Ingress收到的X-Forwarded-For
頭為空白,並且前置有CLB可以啟用CLB 的Proxy Protocol來擷取用戶端IP。關於Proxy Protocol詳細資料請參見通過CLB四層監聽擷取用戶端真實IP。
Nginx Ingress Controller組件支援HSTS嗎?
nginx-ingress-controller組件預設是開啟HSTS的,有些瀏覽器第一次基於PLAIN HTTP訪問時,服務端(開啟HSTS)會在返回給用戶端的回應標頭裡攜帶Non-Authoritative-Reason: HSTS
欄位,說明服務端支援HSTS,當用戶端也支援的情況下下次會直接以HTTPS方式訪問服務端。服務端返回的回應標頭訊息體中包含有307 Internal Redirect
狀態代碼,具體如下圖所示。
當用戶端不希望支援自動轉到HTTPS訪問服務端時,您可以關閉nginx-ingress-controller組件的HSTS。具體操作,請參見HSTS。
在瀏覽器端HSTS預設是有緩衝的,當關閉nginx-ingress-controller組件的HSTS後,請您清理緩衝。
Ingress-Nginx支援哪些Rewrite配置?
目前Ingress-Nginx支援一些簡單的Rewrite配置,具體請參見Rewrite。但是,對於一些進階的特別的Rewrite需求,您可以通過下面方式來配置。
configuration-snippet:請參見Configuration snippet,擴充一些配置到Location章節中。
server-snippet:請參見Server snippet,擴充一些配置到Server章節中。
同時,snippet也支援一些全域配置,具體如下圖所示。更多相關資訊,請參見main-snippet。
在ACK組件管理中升級Nginx Ingress Controller組件時,系統會有哪些更新?
Nginx Ingress Controller組件在0.44之前的版本,包含以下資源:
serviceaccount/ingress-nginx
configmap/nginx-configuration
configmap/tcp-services
configmap/udp-services
clusterrole.rbac.authorization.k8s.io/ingress-nginx
clusterrolebinding.rbac.authorization.k8s.io/ingress-nginx
role.rbac.authorization.k8s.io/ingress-nginx
rolebinding.rbac.authorization.k8s.io/ingress-nginx
service/nginx-ingress-lb
deployment.apps/nginx-ingress-controller
Nginx Ingress Controller組件在0.44版本及其之後的版本,額外包含以下資源:
validatingwebhookconfiguration.admissionregistration.k8s.io/ingress-nginx-admission
service/ingress-nginx-controller-admission
serviceaccount/ingress-nginx-admission
clusterrole.rbac.authorization.k8s.io/ingress-nginx-admission
clusterrolebinding.rbac.authorization.k8s.io/ingress-nginx-admission
role.rbac.authorization.k8s.io/ingress-nginx-admission
rolebinding.rbac.authorization.k8s.io/ingress-nginx-admission
job.batch/ingress-nginx-admission-create
job.batch/ingress-nginx-admission-patch
在ACK的組件管理頁面對Nginx Ingress Controller組件進行升級時,系統保留以下資源配置不變更:
configmap/nginx-configuration
configmap/tcp-services
configmap/udp-services
service/nginx-ingress-lb
所有其他資源的配置都會被覆蓋成預設配置。以deployment.apps/nginx-ingress-controller
資源配置為例,其預設的replicas參數為2。如果您升級Nginx Ingress Controller組件之前的replicas為5,但是通過組件管理升級Ingress後,其replicas將會變為2,和預設配置一致。
如何將Ingress-nginx的監聽由四層改為七層(HTTPS/HTTP)?
Ingress Pod的負載平衡預設是TCP 443 和TCP 80,您可以建立一個HTTPS/HTTP類型的負載平衡,將Ingress-nginx的監聽由四層改為七層。
修改監聽時服務會有短暫中斷,建議在業務低穀期進行修改監聽操作。
建立認證,並記錄cert-id。具體操作,請參見選擇阿里雲簽發認證。
通過Annotation將Ingress所用負載平衡的監聽由四層改為七層。
登入Container Service管理主控台,在左側導覽列選擇叢集。
在叢集列表頁面,單擊目的地組群名稱,然後在左側導覽列,選擇 。
在服務頁面頂部設定命名空間為kube-system,單擊ingress-nginx-lb右側操作列下的YAML 編輯。
在查看YAML對話方塊中,將
ports
中443連接埠的targetPort
改為80。- name: https port: 443 protocol: TCP targetPort: 80 # 將443連接埠的targetPort改為80
在
annotations
參數下添加以下內容,然後單擊更新。service.beta.kubernetes.io/alibaba-cloud-loadbalancer-protocol-port: "http:80,https:443" service.beta.kubernetes.io/alibaba-cloud-loadbalancer-cert-id: "${YOUR_CERT_ID}"
結果驗證。
在服務頁面,單擊ingress-nginx-lb服務類型列的。
單擊監聽頁簽,可以看到監聽的前端協議/連接埠顯示HTTP:80和HTTPS:443,說明通過Annotation將負載平衡的監聽由四層改為七層成功。
應用市場部署的ack-ingress-nginx如何使用已有SLB?
登入Container Service管理主控台,在左側導覽列選擇 。
在應用目錄頁面搜尋ack-ingress-nginx或ack-ingress-nginx-v1。
1.20以下叢集選中ack-ingress-nginx。
1.20以上叢集選中ack-ingress-nginx-v1。
部署Ingress Controller。詳細資料,請參見部署多個Ingress Controller。
在部署過程中的參數頁面,刪除舊註解,添加新註解。
刪除controller.service.annotations下的所有註解。
添加新的註解。
# 指定SLB service.beta.kubernetes.io/alibaba-cloud-loadbalancer-id: "${YOUR_LOADBALANCER_ID}" # 強制覆蓋監聽 service.beta.kubernetes.io/alibaba-cloud-loadbalancer-force-override-listeners: "true"
單擊確定,繼續部署。
部署成功後,配置對應的IngressClass,使用Ingress Controller。詳細資料,請參見部署多個Ingress Controller。
如何擷取多個Ingress Controller對應的訪問日誌?
前提條件
安裝日誌組件。叢集建立時,預設會安裝日誌組件,如未安裝。具體操作,請參見步驟一:安裝Logtail組件進行手動安裝。
預設的Ingress Controller組件已經開啟Nginx Ingress日誌採集配置。
已擷取其他Ingress Controller組件容器的Label。具體操作,請參見如何擷取容器的Label和環境變數。
操作步驟:
登入Container Service管理主控台,在左側導覽列選擇叢集。
在叢集列表頁面,單擊目的地組群名稱,然後在左側導覽列,選擇叢集資訊。
在叢集資訊頁面,單擊叢集資源。然後在叢集資源的列表中單擊Log ServiceProject的右側ID。
跳轉到目的地組群的SLSLog Service,在日誌庫頁面建立Logstore。具體操作,請參見管理Logstore。為確保日誌不會重複採集,一個Logstore只採集一個Ingress Controller組件日誌。
Logstore名稱可以參考不同的Ingress Controller的組件名稱。
建立成功後,在彈出的資料接入嚮導框中,單擊取消。
在日誌庫左側列表欄,單擊
,然後在Logtail配置列表下,單擊k8s-nginx-ingress進入配置頁面。在Logtail配置頁面,單擊複製。然後在Logtail複製頁面,單擊下拉框,選擇新建立的Logstore名稱,在容器過濾中,單擊容器Label白名單列的添加,並以索引值對的方式添加Ingress Controller組件容器Label。在Logtail複製頁面,單擊提交。
在日誌庫左側列表欄,單擊新建立的Logstore名稱。在右側欄頂部,單擊開啟索引,然後在查詢分析頁面,單擊確定。即可完成對Logstore的配置。
在日誌庫左側列表欄,選擇
。在Logtail配置頁面中,單擊右側操作列下的管理Logtail配置。在配置詳情頁面,單擊處理外掛程式名稱列下的提前欄位(正則模式),查看Tlog欄位。在Logtail配置頁面,單擊切換為編輯器配置。在Logtail配置下,單擊編輯。在外掛程式配置中,配置對應日誌欄位Keys和Regex。配置完成,單擊儲存。
說明若不同的Nginx Ingress Controller日誌格式定義有所區別,需要對應地修改Logtail配置下的
processors
部分。
如何開啟nginx-ingress-controller的TCP協議?
ACK叢集中的Ingress資源預設僅支援路由外部HTTP和HTTPS流量至服務內,通過修改ingress-nginx組件的配置,可以實現來自非HTTP協議的外部TCP流量通過在ConfigMap中定義的TCP連接埠映射,路由至叢集內的服務。
操作步驟如下:
按tcp-echo服務範本部署Service、Deployment服務。
部署以下模板ConfigMap。
編輯tcp-services-cm.yaml,儲存退出。
apiVersion: v1 kind: ConfigMap metadata: name: tcp-services namespace: kube-system data: 9000: "default/tcp-echo:9000" # 表示任何通過連接埠9000接收到的外部TCP流量都將被路由到default命名空間下名為tcp-echo的服務上,該服務監聽的是內部連接埠9000。 9001:"default/tcp-echo:9001"
使用如下命令部署ConfigMap。
kubectl apply -f tcp-services-cm.yaml
新增nginx-ingress-controller組件的Service TCP連接埠,儲存退出。
kubectl edit svc nginx-ingress-lb -n kube-system
apiVersion: v1 kind: Service metadata: labels: app: nginx-ingress-lb name: nginx-ingress-lb namespace: kube-system spec: allocateLoadBalancerNodePorts: true clusterIP: 192.168.xx.xx ipFamilies: - IPv4 ports: - name: http nodePort: 30xxx port: 80 protocol: TCP targetPort: 80 - name: https nodePort: 30xxx port: 443 protocol: TCP targetPort: 443 - name: tcp-echo-9000 # 新增 port: 9000 # 新增 protocol: TCP # 新增 targetPort: 9000 # 新增 - name: tcp-echo-9001 # 新增 port: 9001 # 新增 protocol: TCP # 新增 targetPort: 9001 selector: app: ingress-nginx sessionAffinity: None type: LoadBalancer
測試組態生效。
執行以下命令,查看Ingress服務,擷取Ingress SLB的地址。
kubectl get svc -n kube-system| grep nginx-ingress-lb
預期輸出。
nginx-ingress-lb LoadBalancer 192.168.xx.xx 172.16.xx.xx 80:31246/TCP,443:30298/TCP,9000:32545/TCP,9001:31069/TCP
使用
nc
命令給Ingress IP的9000連接埠發送helloworld
。無返回資料則表示測試正常。echo "helloworld" | nc <172.16.xx.xx> 9000 echo "helloworld" | nc <172.16.xx.xx> 9001
Nginx Ingress認證匹配邏輯是什嗎?
當在Ingress資源配置中指定TLS認證時,認證的配置位於spec.tls
欄位下,但實際使用的網域名稱則引用spec.rules.host
欄位。而在Nginx Ingress Controller中,Controller會以Lua Table的形式儲存網域名稱到認證的映射關係。
當用戶端向Nginx發起HTTPS請求時,會通過SNI攜帶請求的網域名稱host
資訊,Nginx ingress採用certificate.call()
來尋找對應的網域名稱是否存在配置的認證,若不存在則返回fake
認證。
相關的Nginx配置如下:
## start server _
server {
server_name _ ;
listen 80 default_server reuseport backlog=65535 ;
listen [::]:80 default_server reuseport backlog=65535 ;
listen 443 default_server reuseport backlog=65535 ssl http2 ;
listen [::]:443 default_server reuseport backlog=65535 ssl http2 ;
set $proxy_upstream_name "-";
ssl_reject_handshake off;
ssl_certificate_by_lua_block {
certificate.call()
}
...
}
## start server www.example.com
server {
server_name www.example.com ;
listen 80 ;
listen [::]:80 ;
listen 443 ssl http2 ;
listen [::]:443 ssl http2 ;
set $proxy_upstream_name "-";
ssl_certificate_by_lua_block {
certificate.call()
}
...
}
Ingress Nginx支援OCSP Stapling技術功能,可以改進認證狀態的驗證過程。基於此功能,用戶端無需直接向CA網站查詢認證狀態,從而減少認證驗證時間,提升訪問速度。更多資訊,請參見配置OCSP Stapling。
Nginx Ingress認證為什麼不匹配?
找到您配置的認證Secret下對應的認證內容儲存為檔案(需要BASE64解碼後的內容),然後使用openssl
命令進行解碼查看。
kubectl get secret <YOUR-SECRET-NAME> -n <SECRET-NAMESPACE> -o jsonpath={.data."tls\.crt"} |base64 -d | openssl x509 -text -noout
查看CN(Common Name)欄位中是否包含您請求的網域名稱,如果不符,您需要重建認證
流量高負載情況下健全狀態檢查失敗怎麼辦?
健全狀態檢查將通過訪問Nginx在10246連接埠上監聽的/healthz
路徑,以驗證Nginx的狀態是否健康且服務正常運行。
健全狀態檢查失敗時,預期如下:
I0412 11:01:52.581960 7 healthz.go:261] nginx-ingress-controller check failed: healthz
[-]nginx-ingress-controller failed: the ingress controller is shutting down
2024/04/12 11:01:55 Get "http://127.0.0.1:10246/nginx_status": dial tcp 127.0.0.1:10246: connect: connection refused
W0412 11:01:55.895683 7 nginx_status.go:171] unexpected error obtaining nginx status info: Get "http://127.0.0.1:10246/nginx_status": dial tcp 127.0.0.1:10246: connect: connection refused
I0412 11:02:02.582247 7 healthz.go:261] nginx-ingress-controller check failed: healthz
[-]nginx-ingress-controller failed: the ingress controller is shutting down
2024/04/12 11:02:05 Get "http://127.0.0.1:10246/nginx_status": dial tcp 127.0.0.1:10246: connect: connection refused
W0412 11:02:05.896126 7 nginx_status.go:171] unexpected error obtaining nginx status info: Get "http://127.0.0.1:10246/nginx_status": dial tcp 127.0.0.1:10246: connect: connection refused
I0412 11:02:12.582687 7 healthz.go:261] nginx-ingress-controller check failed: healthz
[-]nginx-ingress-controller failed: the ingress controller is shutting down
2024/04/12 11:02:15 Get "http://127.0.0.1:10246/nginx_status": dial tcp 127.0.0.1:10246: connect: connection refused
W0412 11:02:15.895719 7 nginx_status.go:171] unexpected error obtaining nginx status info: Get "http://127.0.0.1:10246/nginx_status": dial tcp 127.0.0.1:10246: connect: connection refused
I0412 11:02:22.582516 7 healthz.go:261] nginx-ingress-controller check failed: healthz
[-]nginx-ingress-controller failed: the ingress controller is shutting down
2024/04/12 11:02:25 Get "http://127.0.0.1:10246/nginx_status": dial tcp 127.0.0.1:10246: connect: connection refused
W0412 11:02:25.896955 7 nginx_status.go:171] unexpected error obtaining nginx status info: Get "http://127.0.0.1:10246/nginx_status": dial tcp 127.0.0.1:10246: connect: connection refused
I0412 11:02:28.983016 7 nginx.go:408] "NGINX process has stopped"
I0412 11:02:28.983033 7 sigterm.go:44] Handled quit, delaying controller exit for 10 seconds
I0412 11:02:32.582587 7 healthz.go:261] nginx-ingress-controller check failed: healthz
[-]nginx-ingress-controller failed: the ingress controller is shutting down
2024/04/12 11:02:35 Get "http://127.0.0.1:10246/nginx_status": dial tcp 127.0.0.1:10246: connect: connection refused
W0412 11:02:35.895853 7 nginx_status.go:171] unexpected error obtaining nginx status info: Get "http://127.0.0.1:10246/nginx_status": dial tcp 127.0.0.1:10246: connect: connection refused
I0412 11:02:38.986048 7 sigterm.go:47] "Exiting" code=0
當Nginx背景工作處理序負載過高時,會消耗大量CPU資源,有時甚至導致CPU資源接近100%。這種情況可能引發健全狀態檢查失敗。建議增加Pod副本數量,以便分散負載,確保健全狀態檢查能夠成功執行。
cert-manager不符合預期,導致認證簽發失敗怎麼辦?
如果您使用的認證管理工具Cert-manager未能按預期工作,導致認證簽發失敗,原因可能是啟動了Web應用程式防火牆(WAF)。WAF在開啟狀態下可能會干擾HTTP01請求,妨礙認證的簽發流程。建議關閉WAF,從而消除對認證簽發過程的影響。關閉WAF前,需充分評估其他因素,避免帶來不必要的影響。
Nginx大壓力流量下為什麼佔用大量記憶體?
如果發現Nginx在處理大流量時記憶體佔用異常增高,導致OOM事件,可以進入Pod內部重點檢查Controller進程的記憶體佔用較多,應該是Metrics相關效能指標導致記憶體流失。這個問題為Nginx Ingress Controller v1.6.4的已知問題,推薦您將Nginx Ingress Controller升級至最新版本,關閉Metrics採集,修改啟動參數,添加--enable-metrics=false。特別注意那些會顯著影響記憶體的指標,比如nginx_ingress_controller_ingress_upstream_latency_seconds
。更多詳情,請參見Ingress Controller高壓測試和Prometheus Metric記憶體流失及相關的Metrics PR。
修正Nginx Ingress Controller到期的升級狀態
當Nginx Ingress Controller灰階升級過程中,如果遇到卡在驗證階段的情況,無法繼續操作(出現提示“Operation is forbidden for task in failed state”),這通常是因為組件升級任務由於超出預定的4天有效期間而被系統清除導致的。在這種情況下,您需要手動調整組件的灰階狀態以糾正問題。
如果組件的升級進度已經達到發布階段,那麼無需執行升級操作。直到當前的任務因超過預設的到期時間(4天)而自動終止即可。
操作步驟
完成修改後,組件升級將自動繼續,替換舊版本Pod以完成灰階升級。不過,在控制台的組件管理介面中將依然會顯示升級中的狀態,該狀態將在大約兩周后消失恢複正常。
執行以下命令,編輯nginx-ingress-controller的Deployment。
kubectl edit deploy -n kube-system nginx-ingress-controller
將以下參數修正回指定值。
spec.minReadySeconds: 0
spec.progressDeadlineSeconds: 600
spec.strategy.rollingUpdate.maxSurge: 25%
spec.strategy.rollingUpdate.maxUnavailable: 25%
編輯完成後儲存退出。
從控制器v1.10版本起,為什麼分塊傳輸(Transfer-Encoding: chunked)無法正常工作?
如果您的代碼設定了HTTP頭部Transfer-Encoding: chunked
,並且控制器的日誌中出現關於重複頭部的錯誤資訊,這可能與Nginx的更新有關,關於更新記錄請參見Nginx的更新日誌。v1.10起的Nginx版本強化了對HTTP響應的校正,導致後端返回多個Transfer-Encoding: chunked
頭部時被視為無效響應。因此,需要確保您的後端服務僅返回一個Transfer-Encoding: chunked
頭。更多詳情,請參見GitHub Issue #11162。
Nginx Ingress如何配置IP黑白名單存取控制
Nginx Ingress支援在ConfigMap中添加索引值對或在Ingress路由中添加Annotation的方式配置IP黑白名單存取控制。ConfigMap為全域生效,Ingress在路由維度生效,Ingress路由維度優先順序高於全域維度。如需在Ingress中添加Annotation,請參見下表。更多資訊,請參見Denylist Source Range和Whitelist Source Range。
Annotation | 說明 |
nginx.ingress.kubernetes.io/denylist-source-range | IP黑名單,支援IP地址或CIDR地址塊,以英文半形逗號(,)分隔。 |
nginx.ingress.kubernetes.io/whitelist-source-range | IP白名單,支援IP地址或CIDR地址塊,以英文半形逗號(,)分隔。 |
Nginx Ingress v1.2.1已知問題
在Ingress資源中配置defaultBackend時,可能會覆蓋預設server的defaultBackend設定。更多詳情請參見GitHub Issue #8823。為瞭解決這個問題,建議將Nginx Ingress Controller組件升級至v1.3或更高版本。關於如何升級組件的操作步驟,請參見升級Nginx Ingress Controller組件。
使用curl命令訪問公網服務時出現串連重設
在使用curl
命令通過HTTP協議訪問境外公網服務時,可能會遇到錯誤提示:curl: (56) Recv failure: Connection reset by peer
。通常是由於HTTP明文請求中可能包含敏感詞,這些敏感詞導致請求被阻斷或響應被重設。您可以為路由規則配置HTTPS認證,確保使用加密方式進行通訊。