Kubernetes wskazówki & triki: spersonalizowane strony błędów w NGINX Ingress

Kubernetes tips & tricks: spersonalizowane strony błędów w NGINX Ingress

W tym artykule chciałbym opowiedzieć o dwóch możliwościach NGINX Ingress związanych z wyświetlaniem spersonalizowanych stron błędów oraz o istniejących w nich ograniczeniach i sposobach ich obejścia.

1. Zmiana domyślnego backendu

Domyślnie w NGINX Ingress używany jest default backend, który pełni odpowiednią funkcję. Oznacza to, że gdy zapytanie Ingressa dotyczy hosta, który nie znajduje się w zasobach Ingress, otrzymujemy stronę z kodem odpowiedzi 404:

Kubernetes tips & tricks: spersonalizowane strony błędów w NGINX Ingress

Jednak coraz częściej nasi klienci przychodzą z prośbą, aby zamiast standardowego 404 pokazać swoją stronę z logo firmy i innymi udogodnieniami. W tym celu NGINX Ingress oferuje wbudowaną możliwość przeoverride'owania default-backend-service. Opcji o tej samej nazwie jako argument przekazujemy wpis w formacie namespace/servicename. Port usługi powinien być równy 80.

Aby to zrealizować, należy stworzyć swój pod (wdrązenie) i usługę z aplikacją (przykład realizacji w YAML z repozytorium ingress-nginx), która zastąpi default backend.

Oto mała ilustracja:

~$ 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>Strona, której szukasz, nie została znaleziona.</span>

W ten sposób wszystkie domeny, które nie zostały wyraźnie stworzone przez YAML z kind: Ingress, trafiają do default-backend. W powyższym wykazie taką domeną stało się sadsdasdas.

2. Obsługa błędów HTTP w aplikacji przez default backend

Inna sytuacja – kończące się błędami HTTP (404, 500, 502…) zapytania do aplikacji, w której takie sytuacje nie są obsługiwane (nie generuje się odpowiednich ładnych stron). Może to również wynikać z chęci programistów do zwracania takich samych stron błędów w wielu aplikacjach.

Aby zrealizować ten przypadek po stronie serwera, musimy:

  1. Wykonać instrukcję powyżej z punktu o default backend;
  2. Do konfiguracji ConfigMap nginx-ingress dodać klucz custom-http-errors, na przykład z wartością 404,503 (oczywiście odpowiada to kodom błędów, na które rozciąga się nowe zasady).

Oczekiwany rezultat osiągnięto: podczas działania aplikacji klienckiej i otrzymania błędu z kodem odpowiedzi 404 lub 503, zapytanie zostanie automatycznie przekierowane do nowego default backend...

Jednak przy tworzeniu aplikacji dla default backend i custom-http-errors trzeba wziąć pod uwagę ważną szczególność:

!!! Ważne Oczekuje się, że niestandardowy backend zwróci poprawny kod statusu HTTP zamiast 200. NGINX nie zmienia odpowiedzi z domyślnego niestandardowego backendu.

Problem polega na tym, że podczas przekierowania żądania w nagłówkach będą znajdować się przydatne informacje z poprzednim kodem odpowiedzi i dodatkowymi informacjami (pełna lista dostępna) tutaj).

Oznacza to, że sam musisz zadbać o poprawny kod odpowiedzi. Oto przykład z dokumentacji, jak to działa.

Różnym aplikacjom - różny default backend

Aby rozwiązanie nie było globalne dla całego klastra, lecz dotyczyło tylko konkretnych aplikacji, najpierw trzeba sprawdzić wersję Ingress. Jeśli odpowiada 0.23 lub wyżej, skorzystaj z "rodzimych" adnotacji Ingress:

  1. Możemy nadpisać default-backend do każdej Ingressu za pomocą adnotacji W wyniku tego zasób Ingress będzie wyglądał mniej więcej tak:;
  2. Możemy nadpisać custom-http-errors do każdej Ingressu za pomocą adnotacji W wyniku tego zasób Ingress będzie wyglądał mniej więcej tak:.

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

W takim przypadku błędy 404 i 502 będą przekierowane do usługi error-pages ze wszystkimi potrzebnymi nagłówkami.

w poprzednich wersjach Ingress taka możliwość nie istniała

W przełomowe zacięcie w 0.23 (). A jeśli w twoim klastrze działają 2 zupełnie różne aplikacje i chcesz dla każdej z nich wskazać różne default-backend-service i obsługę różnych kodów błędów - w tym celu będziesz musiał skorzystać z workaroundów, których mamy dwa.Ingress < 0.23: podejście pierwsze

Ta opcja jest prostsza. Jako aplikację, która zwraca swoje strony, mamy zwykły HTML, który nie potrafi patrzeć na nagłówki i zwracać poprawne kody odpowiedzi. Taka aplikacja jest wdrażana z Ingress z url

, a w katalogu /error-pagesws będzie leżał zwracany HTML. Ilustracja w 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

Usługa dla tego wdrożenia musi być typu ClusterIP.

Przy tym w aplikacji, w której będziemy obsługiwać błąd, w Ingressie dodajemy server-snippet lub configuration-snippet z następującą zawartością:

W aplikacji, w której będziemy obsługiwać błąd, w Ingress dodajemy server-snippet lub configuration-snippet z następującą zawartością:

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: druga opcja

Opcja dla aplikacji, która potrafi obsługiwać nagłówki… W ogóle jest to bardziej poprawny sposób, zapożyczony z custom-http-errors. Jej ręczne użycie (kopiowanie) pozwoli nie zmieniać globalnych ustawień.

Kroki są następujące. Tworzymy taki sam deployment z aplikacją, która potrafi słuchać potrzebnych nagłówków i odpowiadać poprawnie. Dodajemy do Ingress aplikacji server-snippet z następującą zawartością:

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;
      }

Jak widać, dla każdej błędnej sytuacji, którą chcemy obsługiwać, należy utworzyć własny location, w którym będą podstawiane wszystkie niezbędne nagłówki, jak w „rodzimym” custom-error-pages. W ten sposób możemy tworzyć różne spersonalizowane strony błędów nawet dla poszczególnych locationów i serwerów.

P.S.

Inne z cyklu K8s tips & tricks:

Przeczytaj także na naszym blogu:

Źródło: habr.com

Kup solidny hosting stron z ochroną przed DDoS, serwery VPS VDS 🔥 Kup solidny hosting stron z ochroną przed DDoS, serwery VPS VDS | ProHoster