
В тази статия искам да говоря за две възможности на NGINX Ingress, свързани с показването на персонализирани страници с грешки, както и за съществуващите ограничения и начини за тяхното преодоляване.
1. Промяна на задния план по подразбиране
По подразбиране в NGINX Ingress се използва default backend, който изпълнява съответната функция. Това означава, че при заявка към Ingress с указание за хост, който не е в ресурсите на Ingress, получаваме такава страница с код на отговор 404:
![]()
Все по-често нашите клиенти идват с искане вместо стандартния 404 да покажат своя страница с фирмено лого и други удобства. За това NGINX Ingress разполага с да замени default-backend-service. Като аргумент на съответната опция подаваме записа във формат namespace/servicename. Портът на услугата трябва да бъде 80.
За целта е необходимо да създадете свой pod (deployment) и услуга с вашето приложение ( от хранилището ingress-nginx), което ще се предава вместо default backend.
Ето малка илюстрация:
~$ curl -i -XGET http://sadsdasdas.kube-cloud.my/
HTTP/1.1 404 Не е намерена
Дата: Пон, 11 Мар 2019 05:38:15 GMT
Тип на съдържанието: */*
Кодиране на трансфера: chunked
Връзка: keep-alive
<span>Страницата, която търсите, не може да бъде намерена.</span> Така всички домейни, които явно не са създадени чрез YAML с kind: Ingress, попада в default-backend. В списъка по-горе такъв домейн стана sadsdasdas.
2. Обработка на HTTP-грешки в приложението чрез default backend
Друга ситуация — завършващи с HTTP-грешки (404, 500, 502…) заявки към приложението, в което не се обработват такива ситуации (не се генерират съответните красиви страници). Това може да бъде също предизвикано от желанието на разработчиците да предоставят еднакви страници с грешки в много приложения.
За реализиране на този случай на сървърната страна е необходимо:
- Да изпълните инструкциите по-горе от точката за default backend;
- В конфигурационния ConfigMap nginx-ingress добавете ключ
custom-http-errors, например, със стойност404,503(очевидно, съответстваща на кодовете на грешки, на които се прилага новото правило).
Очакваният резултат е постигнат: при работа на клиентското приложение и получаване на грешка с код на отговор 404 или 503 заявката ще бъде автоматично пренасочена към новия default backend...
Но при разработката на приложението за default backend и custom-http-errors трябва да се има предвид важен аспект:
!!! Важно Очаква се, че персонализираният backend ще върне правилния HTTP статус код, вместо 200. NGINX не променя отговора от персонализирания default backend.Става въпрос за това, че при пренасочване на заявката в заглавките ще има полезна информация с предишния код на отговора и допълнителна информация (пълен списък е наличен ).
Това означава, че трябва сами да се погрижите за коректния код на отговора. от документацията как работи това.
Различните приложения изискват различен default backend
За да решението не е глобално за целия клъстер, а да се отнася само за конкретни приложения, първо трябва да проверите версията на Ingress. Ако тя е 0.23 или по-висока, използвайте „родните“ анотации на Ingress:
- Можем да преопределим
default-backendза всеки на Ingress с ; - Можем да преопределим
custom-http-errorsза всеки на Ingress с .
В резултат, ресурсът 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 ще бъдат пренасочени към услугата error-pages с всички необходими заглавки.
В в предишните версии на Ingress такава възможност не е имало (). И ако в клъстера ви работят 2 напълно различни приложения и искате за всяко от тях да зададете различни default-backend услуги и обработка на различни кодове на грешки — за това ще трябва да използвате workaround-ове, от които имаме два.
Ingress < 0.23: първият подход
Този вариант е по-прост. В качеството на приложение, което предоставя своите страници, имаме обикновен HTML, който не умее да гледа заглавките и да връща коректни кодове на отговор. Такова приложение се разгръща с Ingress с url /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 добавяме server-snippet или configuration-snippet със следното съдържание:
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 на приложението server-snippet със следното съдържание:
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;
}Както се вижда, за всяка грешка, която искаме да обработим, трябва да създадем свой location, където ще бъдат добавени всички необходими заглавия, точно както в "родния" . По този начин можем да създаваме различни персонализирани страници с грешки дори за отделни location'и и сървъри.
P.S.
Друго от цикъла K8s tips & tricks:
- «»;
- «»;
- «»;
- «».
Прочетете също в нашия блог:
- «»;
- «».
Източник: habr.com
