Kubernetes 提示和技巧:NGINX Ingress 中的自定義錯誤頁面

Kubernetes 提示和技巧:NGINX Ingress 中的自定義錯誤頁面

在本文中,我想談談 NGINX Ingress 與顯示個人化錯誤頁面相關的兩個功能,以及它們存在的限制以及解決方法。

1. 更改預設後端

預設情況下,NGINX Ingress 使用預設後端,執行對應的功能。 這表示當請求 Ingress 指定的主機不在 Ingress 資源中時,我們會收到以下帶有 404 回應代碼的頁面:

Kubernetes 提示和技巧:NGINX Ingress 中的自定義錯誤頁面

然而,我們的客戶越來越多地要求顯示帶有公司徽標和其他設施的頁面,而不是標準的 404。 為此,NGINX Ingress 有 內建功能 重新定義 default-backend-service。 我們將格式條目作為參數傳遞給同名選項 namespace/servicename。 該服務的連接埠應為 80。

為此,您需要使用應用程式建立自己的 pod(部署)和服務(YAML 中的範例實現 來自 ingress-nginx 儲存庫),它將取代預設後端。

這是一個小例子:

~$ curl -i -XGET http://sadsdasdas.kube-cloud.my/
HTTP/1.1 404 Not Found
Date: Mon, 11 Mar 2019 05:38:15 GMT
Content-Type: */*
Transfer-Encoding: chunked
Connection: keep-alive

<span>The page you're looking for could not be found.</span>

因此,所有未透過 YAML 明確建立的域 kind: Ingress,落入default-backend。 在上面的列表中,該域名變成了 sadsdasdas.

2. 使用預設後端處理應用程式中的 HTTP 錯誤

另一種情況是以 HTTP 錯誤(404、500、502...)結尾的請求,發送到不處理此類情況的應用程式(不會產生相應的漂亮頁面)。 這也可能是由於開發人員希望在多個應用程式中提供相同的錯誤頁面。

為了在伺服器端實作這個案例,我們需要:

  1. 按照上面有關預設後端的段落中的說明進行操作;
  2. 在 nginx-ingress 設定 ConfigMap 中新增一個鍵 custom-http-errors,例如,值為 404,503 (顯然對應於新規則涵蓋的錯誤代碼)。

預期結果已經達到:當客戶端應用程式運行並收到回應代碼 404 或 503 的錯誤時,請求將自動重定向到新的預設後端...

但是,在開發預設後端和自訂 http 錯誤的應用程式時,您需要考慮一個重要功能:

!!! Important The custom backend is expected to return the correct HTTP status code instead of 200. NGINX does not change the response from the custom default backend.

事實上,當請求重定向時,標頭將包含有用的信息以及先前的回應代碼和附加資訊(它們的完整清單可用 這裡).

這意味著你自己必須 注意正確的回應代碼. 這是一個例子。 從文件中可以看出它是如何工作的。

不同的應用程式有不同的預設後端

為了確保該方案不是針對整個叢集全域性的,而是只適用於特定應用,首先需要檢查Ingress版本。 如果匹配的話 0.23 或更高,使用原生 Ingress 註解:

  1. 我們可以重寫 default-backend每個 入口的 使用註釋;
  2. 我們可以重寫 custom-http-errors每個 入口的 使用註釋.

結果,Ingress 資源將如下所示:

apiVersion: extensions/v1beta1
kind: Ingress
metadata:
  name: {{ .Chart.Name }}-app2
  annotations:
    kubernetes.io/ingress.class: "nginx"
    nginx.ingress.kubernetes.io/custom-http-errors: "404,502"
    nginx.ingress.kubernetes.io/default-backend: error-pages
spec:
  tls:
  - hosts:
    - app2.example.com
    secretName: wildcard-tls
  rules:
  - host: app2.example.com
    http:
      paths:
      - path: /
        backend:
          serviceName: {{ .Chart.Name }}-app2
          servicePort: 80

在這種情況下,錯誤 404 和 502 將被重新導向到具有所有必要標頭的錯誤頁面服務。

В 之前版本的Ingress沒有這個功能 (0.23 的致命承諾)。 如果您的叢集中運行著2 個完全不同的應用程序,並且您想要為每個應用程式指定不同的預設後端服務並處理不同的錯誤代碼,為此您將必須使用解決方法,我們有兩個解決方法。

Ingress < 0.23:方法一

這個選項比較簡單。 作為為其頁面提供服務的應用程序,我們有常規的 HTML,它不知道如何查看標頭並返回正確的回應代碼。 這樣的應用程式是透過 url 中的 Ingress 推出的 /error-pages,並在目錄中 ws 將是傳回的 HTML。

YAML 中的插圖:

apiVersion: extensions/v1beta1
kind: Ingress
metadata:
  name: {{ .Chart.Name }}-app2
  annotations:
    kubernetes.io/ingress.class: "nginx"
    ingress.kubernetes.io/server-snippet: |
      proxy_intercept_errors on;
      error_page 500 501 502 503 504 @error_pages;
      location @error_pages {
        rewrite ^ /error-pages/other/index.html break;
        proxy_pass http://error-pages.prod.svc.cluster.local;
      }
spec:
  tls:
  - hosts:
    - app2.example.com
    secretName: wildcard-tls
  rules:
  - host: app2.example.com
    http:
      paths:
      - path: /
        backend:
          serviceName: {{ .Chart.Name }}-app2
          servicePort: 80

此部署的服務必須是 ClusterIP 類型。

同時,在我們將處理錯誤的應用程式中,我們在 Ingress 中新增包含以下內容的伺服器片段或設定片段:

nginx.ingress.kubernetes.io    /server-snippet: |
      proxy_intercept_errors on;
      error_page 500 501 502 503 504 @error_pages;
      location @error_pages {
        rewrite ^ /error-pages/ws/index.html break;
        proxy_pass http://error-pages.prod.svc.cluster.local;
      }

Ingress < 0.23:第二種方法

可以處理標頭的應用程式的選項...一般來說,這是一種更正確的方法,借鑒自 custom-http-errors。 手動使用它(複製)將允許您不更改全域設定。

步驟如下。 我們創造 相同的部署 具有可以收聽必要的標題並正確回應的應用程式。 將包含以下內容的伺服器片段新增至 Ingress 應用程式:

nginx.ingress.kubernetes.io    /server-snippet: |
      proxy_intercept_errors off;
      error_page 404 = @custom_404;
      error_page 503 = @custom_503;
      location @custom_404 {
        internal;
        proxy_intercept_errors off;
        proxy_set_header       X-Code             404;
        proxy_set_header       X-Format           $http_accept;
        proxy_set_header       X-Original-URI     $request_uri;
        proxy_set_header       X-Namespace        $namespace;
        proxy_set_header       X-Ingress-Name     $ingress_name;
        proxy_set_header       X-Service-Name     $service_name;
        proxy_set_header       X-Service-Port     $service_port;
        proxy_set_header       Host               $best_http_host;
        rewrite ^ /error-pages/ws/index.html break;
        proxy_pass http://error-pages.prod.svc.cluster.local;
      }
      location @custom_503 {
        internal;
        proxy_intercept_errors off;
        proxy_set_header       X-Code             503;
        proxy_set_header       X-Format           $http_accept;
        proxy_set_header       X-Original-URI     $request_uri;
        proxy_set_header       X-Namespace        $namespace;
        proxy_set_header       X-Ingress-Name     $ingress_name;
        proxy_set_header       X-Service-Name     $service_name;
        proxy_set_header       X-Service-Port     $service_port;
        proxy_set_header       Host               $best_http_host;
        rewrite ^ /error-pages/ws/index.html break;
        proxy_pass http://error-pages.prod.svc.cluster.local;
      }

正如您所看到的,對於我們想要處理的每個錯誤,我們需要創建自己的位置,其中將插入所有必要的標頭,就像「本機」標頭一樣。 自訂錯誤頁面。 透過這種方式,我們甚至可以為各個位置和伺服器創建不同的個人化錯誤頁面。

聚苯乙烯

K8s 提示和技巧系列中的其他內容:

另請閱讀我們的博客:

來源: www.habr.com

添加評論