
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:
![]()
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 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ą ( 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:
- Wykonać instrukcję powyżej z punktu o default backend;
- 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) ).
Oznacza to, że sam musisz zadbać o poprawny kod odpowiedzi. 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:
- Możemy nadpisać
default-backenddo każdej Ingressu za pomocą adnotacji ; - Możemy nadpisać
custom-http-errorsdo każdej Ingressu za pomocą adnotacji .
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 (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 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” . 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
