全部產品
Search
文件中心

:升級Nginx Ingress Controller組件

更新時間:Nov 15, 2024

在升級叢集時,由於叢集API版本的棄用,可能需要同步對Nginx Ingress Controller進行版本升級。此外,考慮到舊版本的組件可能存在穩定性風險以及功能缺失,推薦您及時將Nginx Ingress Controller升級到最新版本。Nginx Ingress Controller使用了分階段升級的方式,需要您在升級過程中及時關注組件狀態以及業務情況,保證業務流量不會受損。

升級流程

Nginx Ingress Controller作為資料面的關鍵組件,對穩定性有較高的要求。

由於新版本對Nginx Ingress Controller所做的自訂修改較多以及升級版本跨度較大,可能會導致部分配置不相容。而且版本跨度大引起的配置不相容,可能不會在升級後立即暴露出來,因此,一次性將組件升級到最新版本的風險較高。

為了確保升級Nginx Ingress Controller後組件以及業務的正常運行,升級將採用分階段的形式進行。升級期間,可以對業務狀況進行檢查,有問題也能夠及時復原。

第一部分:前置檢查

前置檢查將會在組件升級開始之前自動進行,以檢查組件目前狀態是否滿足升級條件。如果組件存在不滿足升級條件的設定,或者處於不健康狀態時,將無法通過健全狀態檢查,在完成問題的手動修複之前,無法繼續進行升級。

第二部分:驗證階段

驗證階段會擴容出1個新版本組件的Pod,驗證新版本組件的運行狀態以及Ingress規則是否符合預期。擴容成功後,一部分流量將會進入該Pod,此時可以通過容器日誌、SLSLog Service或阿里雲Prometheus監控服務來查看流量是否有異常。

驗證Pod擴容成功後,升級流程會被暫停。在確認組件和業務無異常後,即可手動確認繼續進行下一階段。若此時出現問題,也可以選擇復原,刪除新版本Pod,終止升級流程。

該步是通過修改Deployment中的spec.minReadySecondsspec.strategy欄位實現的。

第三部分:發布階段

發布階段將會進行完整的滾動升級流程,將舊版本組件完全替換為新版本。在所有Pod更新完成後,升級流程會暫停,此時可以對組件和業務做最終的確認。當確認無誤後,升級結束。若此時出現問題,也可以選擇復原,將所有Pod重設回舊版本,並結束升級流程。

第四部分:復原(可選)

在驗證階段或者發布階段後的暫停過程中,如果發現組件或業務出現異常,可以通過復原來將組件恢複到升級前的初始狀態。

升級前須知

  • 在組件升級前,請確保擁有對業務流量的監控手段,以便及時發現問題。您可以通過SLSLog Service或阿里雲Prometheus服務來查看業務流量狀況。以上兩種觀測手段的配置,請參見Nginx Ingress訪問日誌分析與監控使用阿里雲Prometheus監控

  • 請確認目前組件健康狀態正常,Pod均為Ready狀態,沒有錯誤記錄檔。

  • 請確認沒有使用HPA等自動擴縮容規則。如存在,請提前刪除,在升級完成後將其恢複。

  • 請確認LoadBalancer Service狀態正常,沒有例外狀況事件透出。

  • 在組件升級過程中,請勿對組件以及Ingress規則進行任何修改。

  • 如果您的Nginx Ingress低於v0.44版本,在升級到高版本時,需要注意首碼匹配的差異,詳細資料請參見升級注意事項

  • 組件升級將採用灰階升級的方式,首先會建立一個升級目標版本的Nginx Ingress Pod執行個體。在經過流量驗證確認無誤後,單擊確認將觸發變換。請確保叢集中有足夠的可調度節點,以便Nginx Ingress Pod能夠正常建立和調度。

操作步驟

  1. 登入Container Service管理主控台,在左側導覽列選擇叢集

  2. 叢集列表頁面,單擊目的地組群名稱,然後在左側導覽列,選擇營運管理 > 組件管理

  3. 組件管理頁面,找到Nginx Ingress Controller組件,單擊組件右下方的升級

  4. 在彈出的升級介面中,單擊開始並確認,開始升級流程。

    說明

    您可以在升級過程中的任何時間點退出該頁面,然後通過單擊組件管理頁面中的升級進度重新回到流程中。

  5. 流程的第一階段需要進行前置檢查。在完成前置檢查後,流程會自動進入下一階段。

    若前置檢查不通過,可以通過前置檢查下的查看詳情跳轉到檢查報告頁面。然後根據未通過的檢查點排查問題,詳細資料,請參見前置檢查說明。問題解決後,可以單擊重試以重新開始升級流程。

  6. 驗證階段完成後,升級流程進入暫停狀態。此時,需要對組件運行狀態和業務狀態進行驗證。關於驗證方法,請參見驗證階段說明

    • 若出現擴容不成功的情況,請參見驗證和發布階段Pod擴容失敗怎麼辦?。也可以在叢集中查看Pod啟動失敗的具體原因,並在解決之後單擊重試,重試該階段。

    • 若驗證業務出現問題,可以通過單擊復原進行復原操作。復原完成後,該升級流程將會結束,可以從組件管理中單擊升級重新開始。

  7. 驗證階段確認一切正常後,單擊繼續進入發布階段。發布階段變換完成後,升級流程進入暫停狀態。此時,需要對組件和業務狀態進行最後一次確認。若業務驗證出現問題,可以通過單擊復原進行復原操作。復原完成後,升級流程將會結束,可以從組件管理中單擊升級重新開始。

  8. 確認組件運行狀態和業務狀態均沒有異常後,單擊繼續結束升級流程。

    說明

    請控制整個升級流程的總時間不要超過一周。

前置檢查說明

前置檢查表

檢查項

檢查內容

異常處理

Deployment存在

組件的Deployment(kube-system/nginx-ingress-controller)存在。

-

Deployment健康

組件的Deployment所控制的Pod全部處於Ready狀態,且不處於變換中等不穩定點。

-

Pod錯誤記錄檔

檢查Pod中最近200條日誌,其中不存在Error或者Fatal層級的錯誤記錄檔。

如果有日誌存在,說明組件近期可能因為配置錯誤等原因出現異常報錯,需要在問題解決後重新進行升級流程。根據日誌解決問題,請參見Nginx Ingress異常問題排查

LoadBalancer Service健康

首先檢查Nginx Ingress Controller所對應的LoadBalancer Service(kube-system/nginx-ingress-lb)是否存在。如果存在,會進一步檢查該Service是否存在任何錯誤事件。

請注意,Service不存在也會被認為該Service存在Warning事件。

當Service不存在時,請參考使用須知及高危風險操作說明文檔中 “在安裝Nginx Ingress Controller組件的情況下手動刪除 kube-system命名空間下的nginx-ingress-lbService” 對應修複操作進行修複。

Service存在但被檢查出例外狀況事件時,可以根據事件內容尋找解決方案,詳細資料,請參見Service例外狀況事件及處理方式。當Service不為LoadBalancer時,該項檢查會被跳過。

HPA

組件Deployment沒有使用HPA。使用HPA時,在組件升級過程中,可能會因為HPA的自動擴縮容策略導致升級狀態被打亂。

在升級過程中,需要將HPA資源從叢集中刪除,升級完成後,再重新啟用。

Deployment模板

組件的Deployment模板只能存在相容的修改。

您之前對Nginx Ingress Controller Deployment所做的某些自訂配置或修改,在升級過程中可能無法自動保留。

  • 以下欄位會在升級後得到保留,作為自訂參數填入新的組件模板中:

    • 副本數(replicas)

    • Pod標籤(template.metadata.labels)

    • 節點選取器(template.spec.nodeSelector)

    • 容忍(template.spec.tolerations)

    • Controller容器的資源限制(template.spec.containers[0].resources)

  • 以下欄位不會影響到前置檢查,但會在升級後被丟棄:

    • Pod annotation(template.metadata.annotations)中的redeploy-timestamp。

    • Pod annotation中的kubectl.kubernetes.io/restartedAt。

    • Pod annotation中的scheduler.alpha.kubernetes.io/critical-pod。

    • 鏡像的imagePullPolicy。

    • template.spec.containers.securityContext.procMount為Default時,會被丟棄。

    • Webhook的相關配置(運行參數、掛載卷、連接埠)。

上述模板更改不會導致檢查不通過。除此之外,無論是私自修改模板還是版本過舊、不符合升級條件,都會造成升級過程中的檢查環節無法通過,進而影響升級的成功率。常見的檢查不通過的原因如下:

  • 使用了EDAS等外掛程式掛載了自訂的Volume。您需要在升級過程中暫時停用EDAS的相關功能,在升級完成後恢複。

  • podAntiAffinity與標準模板出現差異,可能是由於組件模板變動(例如由required改為preferred)導致的。您需要先手動將podAntiAffinity修改為與標準模板一致。

  • 在指定獨佔節點時使用了nodeAffinity,您需要更換為nodeSelector。

如果Deployment模板檢查失敗,您可以通過手動還原模板的方法解決該問題。具體操作,請參見Deployment模板檢查不通過

Ingress配置

叢集內的Ingress只存在相容的特性。

如果叢集內的Ingress中使用了不相容的特性,升級後可能會導致業務無法正常轉寄流量,從而導致停用問題。確認及修改問題,請參見下方升級相容性說明

組件配置

組件ConfigMap(kube-system/nginx-configuration)中存在不相容的配置

如果叢集內ConfigMap中使用了不相容的特性,升級後可能會導致業務無法正常轉寄流量,從而導致停用問題。確認及修改問題,請參見下方升級相容性說明

升級相容性說明

在組件的開發和維護過程中,Nginx Ingress Controller組件的新版本可能會引入新的功能、改進現有功能或者修複安全問題,但同時也可能因為內部架構的調整、依賴庫的變化等原因,導致與之前版本存在相容性差異。關於Nginx Ingress Controller的變更記錄,請參見Nginx Ingress Controller

snippet註解預設禁用

影響版本:v1.9.3-aliyun.1以下(不包括v1.9.3-aliyun.1)。

由於安全原因,自v1.9.3-aliyun.1版本起,Nginx Ingress Controller將預設禁用所有snippet註解,可能包括:

  • nginx.ingress.kubernetes.io/configuration-snippet

  • nginx.ingress.kubernetes.io/server-snippet

  • nginx.ingress.kubernetes.io/stream-snippet

  • nginx.ingress.kubernetes.io/auth-snippet

  • nginx.ingress.kubernetes.io/modsecurity-snippet

出於安全和穩定性風險的考慮,建議您優先使用相關註解或者設定項來實現所需功能。

如您仍需要使用snippet註解能力,請在充分評估風險後,通過在ConfigMapkube-system/nginx-configuration中添加allow-snippet-annotations: "true"手動開啟註解功能。

不支援較低版本的TLS

影響版本:v1.7.0-aliyun.1以下(不包括v1.7.0-aliyun.1)。

由於TLS1.1及以下版本存在安全問題,Nginx Ingress Controller新版本不再預設支援TLS v1.1和TLS v1.0的加密方式。因此,在升級前,請確保您的業務不依賴v1.1及以下版本的TLS,並且在配置中將其移除。修改ConfigMap後會立即生效。

例如,若Nginx Ingress Controller組件的ConfigMap(kube-system/nginx-configuration)配置如下所示:

ssl-protocols: SSLv3 SSLv2 TLSv1 TLSv1.1 TLSv1.2 TLSv1.3

您需要在確認業務不受影響後,可直接將該行設定移除,使用預設選項;或者選擇移除SSLv3、SSLv2、TLSv1、TLSv1.1四項,改為:

ssl-protocols: TLSv1.2 TLSv1.3

若您需要強制使用舊版本的TLS加密方式,請參見Ingress支援哪些SSL/TLS版本?進行配置。

nginx.ingress.kubernetes.io/rewrite-target用法不相容

影響版本:0.22.0以下(不包括0.22.0)。

  • 0.22.0版本對nginx.ingress.kubernetes.io/rewrite-target註解的用法做了修改。在0.22.0及以上版本,使用rewrite-target時,需要顯式指定擷取的群組的使用。

  • 0.22.0版本以下的rewrite-target特性和最新版本的rewrite-target特性不相容,在組件升級前,可以使用configuration-snippet代替rewrite-target註解。

例如,在0.22.0以下版本,規則為:

展開查看完整YAML範例程式碼

apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  annotations:
    nginx.ingress.kubernetes.io/rewrite-target: /
  name: rewrite
  namespace: default
spec:
  rules:
  - host: rewrite.bar.com
    http:
      paths:
      - path: /something/
        pathType: Prefix
        backend:
          service:
            name: http-svc
            port:
              number: 80
      - path: /something123/
        pathType: Prefix
        backend:
          service:
            name: http-svc-1
            port:
              number: 80

需修改為:

展開查看完整YAML範例程式碼

apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  annotations:
    # 使用rewrite指令,/something為path中路徑(不包含尾部的斜杠)。
    # Ingress中包含多個路徑,需要添加多條rewrite指令。
    nginx.ingress.kubernetes.io/configuration-snippet: |
      rewrite "(?i)/something(/|$)(.*)" /$2 break;
      rewrite "(?i)/something123(/|$)(.*)" /$2 break;
  name: rewrite
  namespace: default
spec:
  rules:
  - host: rewrite.bar.com
    http:
      paths:
      - path: /something/ # 和舊版本Ingress資源的路徑保持一致。
        pathType: Prefix
        backend:
          service:
            name: http-svc
            port:
              number: 80
      - path: /something123/ # 和舊版本Ingress資源的路徑保持一致。
        pathType: Prefix
        backend:
          service:
            name: http-svc-1
            port:
              number: 80

修改為上述格式後,即可正常進行升級流程。升級完成後,將Ingress修改為新版的用法即可。

YAML

apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  annotations:
    # 引用匹配的內容。
    nginx.ingress.kubernetes.io/rewrite-target: /$2
  name: rewrite
  namespace: default
spec:
  rules:
  - host: rewrite.bar.com
    http:
      paths:
      # 使用擷取的群組。
      - path: /something(/|$)(.*)
        pathType: Prefix
        backend:
          service:
            name: http-svc
            port:
              number: 80
      # 使用擷取的群組。
      - path: /something123(/|$)(.*)
        pathType: Prefix
        backend:
          service:
            name: http-svc-1
            port:
              number: 80

驗證階段說明

驗證組件及業務狀態

除自身所擁有的業務監控能力外,ACK也提供了SLS日誌、阿里雲Prometheus大盤和容器自身的日誌來觀測Nginx Ingress Controller的運行狀態。開啟上述服務,請參見Nginx Ingress訪問日誌分析與監控使用阿里雲Prometheus監控

SLSLog Service

您可以在Container Service控制台查看通過SLS收集的日誌。

  1. 登入Container Service管理主控台,在左側導覽列單擊叢集

  2. 叢集列表頁面,單擊目的地組群名稱,然後在左側導覽列,選擇營運管理 > 日誌中心

  3. 選擇應用日誌頁簽,在日誌庫下拉框中選擇nginx-ingress,單擊選擇日誌庫

    說明

    若您的日誌庫中沒有nginx-ingress條目,請確認是否配置了組件的日誌收集功能。詳細資料,請參見Nginx Ingress訪問日誌分析與監控

在展示的日誌中,可以看到應用的訪問日誌,也可以在查詢語句中指定對應的Pod(如新版本組件的Pod)來只查看該Pod的訪問日誌。需要注意新Pod的請求成功率是否異常,以及請求數對比舊Pod是否一致。若資料差距較大,可選擇復原操作。

說明

當請求沒有命中任何Ingress規則,返回404時,預設將不會記錄訪問日誌。

阿里雲Prometheus大盤

您可以通過阿里雲Prometheus服務提供的大盤,來觀測組件整體的請求情況。

  1. 登入Container Service管理主控台,在左側導覽列單擊叢集

  2. 叢集列表頁面,單擊目的地組群名稱,然後在左側導覽列,選擇營運管理 > Prometheus監控

  3. 單擊網路監控頁簽,然後單擊叢集ingress流量監控

    說明

    若監控中沒有叢集ingress流量監控,請確認是否配置了組件的Prometheus Metrics搜集功能。詳細資料,請參見使用阿里雲Prometheus監控

在大盤中可以看到Ingress的各項運行指標,也可以通過選擇對應的Pod來查看該Pod的指標。同樣,需要注意的是新的Pod請求成功率是否有異常,以及請求數與舊Pod是否一致。若資料差距較大,可選擇復原操作。

說明

Ingress規則中沒有指定Host(預設為萬用字元“*”)的規則預設不會記錄Metrics。

Pod日誌

您可以通過kubectl,以命令列的形式訪問Pod日誌,來查看是否存在錯誤。

  • 執行以下命令,查看Pod中Nginx的錯誤記錄檔,包括warn、error和crit三個層級。

    kubectl logs -n kube-system <Pod名稱> | grep -e warn -e error -e crit
  • 執行以下命令,查看Pod中Controller的錯誤記錄檔。

    kubectl logs -n kube-system <Pod名稱> | grep "^[EF]"

升級注意事項

在低版本的Nginx Ingress Controller升級到高版本時,由於高版本在首碼匹配邏輯上有所變化,需要關注路徑path配置與實際請求URL的是否一致,否則可能會導致原本正常的請求出現404錯誤。

已知問題

在Nginx Ingress Controller的不同版本中,首碼匹配邏輯可能存在差異,這可能導致服務訪問問題。

  • 在低版本(v0.44之前)的Nginx Ingress Controller中,首碼匹配的規則較為寬鬆,允許如/aaa/bbb的配置,可以匹配請求的URL/aaa/bbbbb

  • 升級到高版本後,首碼匹配的邏輯可能會變得更加嚴格,只匹配精確的請求路徑,這可能導致原本應匹配的路徑/aaa/bbbbb不再匹配,從而引發404錯誤。

影響範圍

受影響的版本為Nginx Ingress版本低於v0.44。關於Nginx Ingress Controller版本記錄,請參見Nginx Ingress Controller。相關PR資訊請參見kubernetes/ingress-nginx #6443

樣本配置

您可以根據以下的YAML配置比較低版本(如v0.22.0.5-552e0db-aliyun)和高版本(如v1.2.1-aliyun.1+)渲染出Nginx配置之間的差異。

  apiVersion: extensions/v1beta1
  kind: Ingress
  metadata:
    labels:
      ingress-controller: nginx
    name: test
    namespace: default
  spec:
    ingressClassName: nginx
    rules:
    - host: www.example.com
      http:
        paths:
        - backend:
            service:
              name: api-resources-svc
              port:
                number: 8080
          path: /api/resource
  • 低版本行為

    在低版本Nginx Ingress(如v0.22.0.5-552e0db-aliyun)中,對應的Nginx配置:

    Location /api/resource   ## 沒有結尾的 "/"

    在上面的配置中,使用的路徑/api/resource在低版本Nginx中允許通過http://www.example.com/api/resources進行訪問。

    說明

    實際訪問路徑是resources而不是resource。

  • 高版本行為

    若將Nginx Ingress Controller升級到高版本(如v1.2.1-aliyun.1+),對應的Nginx配置:

    Location /api/resource/  # 增加了結尾的 "/"
    {
    }
    ...
    Location = /api/resource  # 增加了一個 Location 進行精確匹配
    {
    }

    訪問http://www.example.com/api/resources將返回404錯誤。

常見問題

Nginx Ingress Controller是否支援升級至指定的版本?升級成功後,還能回退到之前的某個版本嗎?

Nginx Ingress Controller組件不支援升級到指定版本,採用分階段的形式進行升級,直至將組件升級到最新的版本。升級成功後無法回退。

驗證和發布階段Pod擴容失敗怎麼辦?

問題原因

解決方案

新版本Pod啟動時出現錯誤(如配置載入失敗等),導致一直處於crash狀態。

根據上方Pod日誌部分提供的方法,查看對應Pod錯誤記錄檔。定位及解決問題,請參見Nginx Ingress異常問題排查

常見於使用專屬節點部署Nginx Ingress Controller的情況。當新的Pod擴容時,會因為所配置的資源限制和節點選取器,導致無可用節點能夠調度新的Pod。

臨時擴容節點,或在業務低峰期縮容Nginx Ingress Controller再進行升級,使得在升級時Pod能夠正常調度。

Deployment模板檢查不通過怎麼辦?

如果在前置檢查過程中,您的Deployment模板檢查不通過,請單擊異常原因右側的連結,進入組件差異展示頁面,查看檢查不通過的欄位。

  1. Nginx Ingress Controller 組件升級頁面的前置檢查下方,單擊查看詳情

  2. 檢查報告頁面的叢集組件檢查結果地區,單擊①處的紅色方框查看檢查結果,然後在檢查結果頁面單擊Deployment 模板,最後單擊②處異常原因右側的連結。

    image..png

  3. 進入組件差異展示頁面,查看檢查不通過的欄位。

    在組件差異頁面,會展示出該版本組件的標準模板(左側)和當前叢集中的組件模板(右側)的對比展示。組件差異頁面會標出兩者之間的全部差異,包括相容和不相容的欄位,並在差異展示的下方標出叢集中組件是否通過差異檢查,以及不相容的差異欄位的具體路徑。

    如下圖所示,下方提示存在一處差異,差異欄位為.spec.template.spec.containers.(nginx-ingress-controller).args(括弧中的內容為數組中元素的name欄位)。通過組件差異對比,發現args中--v=2被修改為了--v=3,需要在升級前進行修正。

    image..png

  4. 修改差異欄位。

    選擇工作負載>無狀態,找到Nginx Ingress Controller組件,單擊更多>查看YAML,在編輯YAML頁面中將args欄位中的--v=3修改為--v=2

  5. 將差異欄位修改後,您也可以重新進入或重新整理組件差異展示頁面,查看最新的對比結果。當頁面底部提示組件可通過差異檢測時,即可通過Deployment模板檢查點。

    說明

    修改叢集內Deployment過程中,Nginx Ingress Controller Pod會重啟,建議您在業務低峰期進行相關操作。

    image..png

相關文檔