
În acest articol vreau să discut despre două posibilități ale NGINX Ingress legate de afișarea paginilor personalizate de eroare, precum și despre limitele existente și modalitățile de a le ocoli.
1. Schimbarea backend-ului implicit
În mod implicit, NGINX Ingress folosește backend-ul default, care îndeplinește funcția corespunzătoare. Aceasta înseamnă că, atunci când se face o solicitare a Ingress-ului cu un host care nu există în resursele Ingress, obținem o astfel de pagină cu codul de răspuns 404:
![]()
Totuși, din ce în ce mai des clienții noștri vin cu cererea de a arăta o pagină personalizată cu logo-ul companiei lor și alte beneficii în locul standardului 404. Pentru aceasta, NGINX Ingress are de a suprascrie default-backend-service. Opțiunii corespunzătoare îi transmit un argument în formatul namespace/servicename. Portul serviciului trebuie să fie 80.
Pentru aceasta, trebuie să creezi propriul pod (deployment) și serviciu cu aplicația ta ( din repository-ul ingress-nginx), care va fi livrat în loc de backend-ul implicit.
Iată o mică ilustrație:
~$ curl -i -XGET http://sadsdasdas.kube-cloud.my/
HTTP/1.1 404 Not Found
Date: Lun, 11 Mar 2019 05:38:15 GMT
Content-Type: *
Transfer-Encoding: chunked
Connection: keep-alive
<span>Pagina pe care o căutați nu a putut fi găsită.</span> Astfel, toate domeniile care nu sunt create explicit prin YAML cu kind: Ingress, ajung în backend-ul implicit. În lista de mai sus, un astfel de domeniu a fost sadsdasdas.
2. Tratarea erorilor HTTP în aplicație prin intermediul backend-ului implicit
O altă situație - cererile la aplicație care se finalizează cu erori HTTP (404, 500, 502...) și în care nu sunt gestionate astfel de situații (nu sunt generate pagini corespunzătoare). Acest lucru poate fi, de asemenea, cauzat de dorința dezvoltatorilor de a livra pagini de eroare identice în mai multe aplicații.
Pentru implementarea acestui caz pe partea serverului, este necesar să:
- Executați instrucțiunile de mai sus din punctul despre backend-ul implicit;
- Adăugați cheia în ConfigMap-ul nginx-ingress
custom-http-errors, de exemplu, cu valoarea404,503(evident, corespunde codurilor de eroare pentru care se aplică noua regulă).
Rezultatul a fost obținut: atunci când aplicația clientului funcționează și primește o eroare cu codul de răspuns 404 sau 503, cererea va fi redirecționată automat către noul backend implicit...
Cu toate acestea, atunci când dezvoltați aplicația pentru backend-ul implicit și custom-http-errors, trebuie să aveți în vedere un aspect important:
!!! Important Backend-ul personalizat este așteptat să returneze codul de stare HTTP corect în loc de 200. NGINX nu schimbă răspunsul din backend-ul implicit personalizat.Este este cazul, deoarece, la redirecționarea cererii, vor fi informații utile în antete cu codul de răspuns anterior și informații suplimentare (lista completă este disponibilă ).
Aceasta înseamnă că trebuie să vă ocupați singuri de un cod corect de răspuns. din documentație, despre cum funcționează.
Pentru aplicații diferite – backend-ul default diferit
Pentru ca soluția să nu fie globală pentru întregul cluster, ci să se refere doar la aplicații specifice, mai întâi trebuie să verificați versiunea Ingress-ului. Dacă aceasta corespunde 0.23 sau mai mare, utilizați anotările „native” Ingress:
- Putem suprascrie
default-backendpentru fiecare al Ingress-ului cu ; - Putem suprascrie
custom-http-errorspentru fiecare al Ingress-ului cu .
În rezultat, resursa Ingress va arăta aproximativ astfel:
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În acest caz, erorile 404 și 502 vor fi redirecționate către serviciul error-pages cu toate anteturile necesare.
În în versiunile anterioare ale Ingress nu exista această posibilitate (). Și dacă aveți în cluster două aplicații complet diferite și doriți să specificați un serviciu backend default diferit și să tratați diverse coduri de eroare – va trebui să utilizați workaround-uri, dintre care avem două.
Ingress < 0.23: prima abordare
Această variantă este mai simplă. Ca aplicație care își oferă paginile, avem un HTML obișnuit, care nu știe să verifice antetele și să ofere coduri de răspuns corespunzătoare. O astfel de aplicație este livrată cu Ingress-ul cu URL /error-pages, iar în directorul ws va fi HTML-ul livrat.
Ilustrație în 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: 80Serviciul pentru această desfășurare trebuie să fie de tip ClusterIP.
În același timp, în aplicația în care vom trata eroarea, adăugăm în Ingress un server-snippet sau un configuration-snippet cu următorul conținut:
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: a doua abordare
O variantă pentru aplicația care poate procesa anteturile… De fapt, aceasta este o cale mai corectă, împrumutată din custom-http-errors. Utilizarea sa manuală (copierea) va permite să nu modifici setările globale.
Pașii sunt următorii. Creăm cu aplicația care poate asculta anteturile necesare și să răspundă corect. Adăugăm în Ingress aplicației server-snippet cu următorul conținut:
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;
}După cum se poate observa, pentru fiecare eroare pe care dorim să o gestionăm, trebuie să creăm propriul location, unde se va insera toate anteturile necesare, ca în «nativ» . Astfel putem crea diferite pagini personalizate de eroare chiar și pentru locații și servere separate.
P.S.
Altceva din ciclul K8s tips & tricks:
- «»;
- «»;
- «»;
- «».
Citiți și în blogul nostru:
- «»;
- «».
Sursa: habr.com
