
In questo articolo voglio discutere due funzionalità di NGINX Ingress relative alla visualizzazione di pagine di errore personalizzate, insieme alle relative limitazioni e ai modi per aggirarle.
1. Modifica del backend predefinito
Per impostazione predefinita, NGINX Ingress utilizza un default backend che svolge la relativa funzione. Questo significa che, quando viene effettuata una richiesta all'Ingress specificando un host che non è presente nelle risorse Ingress, otteniamo una pagina con codice di risposta 404:
![]()
Tuttavia, sempre più spesso i nostri clienti ci chiedono di mostrare la propria pagina con il logo aziendale e altre comodità invece del standard 404. Per questo NGINX Ingress ha per sovrascrivere default-backend-service. Passiamo come argomento alla relativa opzione un'entrata nel formato namespace/servicename. La porta del servizio deve essere 80.
Per fare ciò, è necessario creare il proprio pod (deployment) e servizio con la vostra applicazione ( dal repository ingress-nginx), che sarà restituito al posto del default backend.
Ecco una piccola illustrazione:
~$ curl -i -XGET http://sadsdasdas.kube-cloud.my/
HTTP/1.1 404 Non trovato
Data: Lun, 11 Mar 2019 05:38:15 GMT
Tipo di contenuto: */*
Trasferimento dati: chunked
Connessione: keep-alive
<span>La pagina che stai cercando non può essere trovata.</span> Pertanto, tutti i domini che non sono stati esplicitamente creati tramite YAML con tipo: Ingress, viene indirizzato a default-backend. Nel listing sopra, questo dominio è diventato sadsdasdas.
2. Gestione degli errori HTTP nell'applicazione tramite default backend
Un'altra situazione riguarda le richieste all'applicazione che terminano con errori HTTP (404, 500, 502…) e per le quali non vengono gestite tali situazioni (non vengono generate le corrispondenti pagine di errore carine). Questo può essere causato anche dal desiderio degli sviluppatori di restituire le stesse pagine di errore in numerose applicazioni.
Per attuare questo caso lato server, è necessario:
- Eseguire l'istruzione sopra dal punto riguardante default backend;
- Nel ConfigMap di configurazione nginx-ingress, aggiungere la chiave
custom-http-errors, ad esempio, con il valore404,503(ovviamente, corrisponde ai codici di errore a cui si applica la nuova regola).
Risultato atteso raggiunto: durante il funzionamento dell'applicazione cliente e ricevendo un errore con codice di risposta 404 o 503, la richiesta sarà automaticamente reindirizzata al nuovo default backend…
Tuttavia, durante lo sviluppo dell'applicazione per default backend e custom-http-errors, è importante considerare una caratteristica essenziale:
!!! Importante Il backend personalizzato deve restituire il codice di stato HTTP corretto invece di 200. NGINX non modifica la risposta dal backend personalizzato predefinito.Il punto è che quando si reindirizza la richiesta, ci saranno informazioni utili nelle intestazioni con il codice di risposta precedente e ulteriori dettagli (l'elenco completo è disponibile ).
Questo significa che dovete occupaRvi del codice di risposta corretto.. dalla documentazione su come funziona.
App diverse - backend predefinito diverso.
Per evitare che la soluzione sia globale per l'intero cluster e si applichi solo ad applicazioni specifiche, prima di tutto verificate la versione di Ingress. Se corrisponde a 0.23 o superiore, utilizzate le annotazioni 'native' di Ingress:
- Possiamo sovrascrivere
il backend predefinitoper ogni di Ingress con ; - Possiamo sovrascrivere
custom-http-errorsper ogni di Ingress con .
Il risultato, la risorsa Ingress apparirà più o meno così:
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: 80In tal caso, gli errori 404 e 502 saranno reindirizzati al servizio error-pages con tutte le intestazioni necessarie.
In nella versione precedente di Ingress non era possibile. (). Se nel vostro cluster sono in esecuzione 2 applicazioni completamente diverse e volete specificare un default-backend-service diverso per ciascuna di esse e gestire vari codici di errore — dovrete utilizzare workaround, di cui ne abbiamo due.
Ingress < 0.23: prima opzione
Questa opzione è più semplice. Come applicazione che restituisce le proprie pagine, abbiamo un normale HTML, che non riesce a controllare gli header e restituire i codici di risposta corretti. Questa applicazione viene disposta con Ingress con l'url /error-pages, e nella directory ws si troverà l'HTML restituito.
Illustrazione in 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: 80Il servizio per questo deployment deve essere di tipo ClusterIP.
Inoltre, nell'applicazione in cui gestiremo l'errore, nell'Ingress aggiungiamo server-snippet o configuration-snippet con il seguente contenuto:
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: secondo approccio
Opzione per un'applicazione in grado di gestire le intestazioni… E in effetti è un modo più corretto, derivato da custom-http-errors. Il suo utilizzo manuale (copia) eviterà di modificare le impostazioni globali.
I passi sono i seguenti. Creiamo con un'applicazione in grado di ascoltare le intestazioni richieste e rispondere correttamente. Aggiungiamo nel server-snippet dell'Ingress dell'applicazione il seguente contenuto:
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;
}Come puoi vedere, per ogni errore che desideriamo gestire, è necessario creare un proprio location, dove verranno impostati tutti i necessari header, come nel "nativo" . Così possiamo creare diverse pagine di errore personalizzate anche per singole location e server.
P.S.
Altro dal ciclo K8s tips & tricks:
- «»;
- «»;
- «»;
- «».
Leggete anche nel nostro blog:
- «»;
- «».
Fonte: habr.com
