Suggerimenti e trucchi per Kubernetes: pagine di errore personalizzate in NGINX Ingress

Kubernetes tips & tricks: pagine di errore personalizzate in NGINX Ingress

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:

Kubernetes tips & tricks: pagine di errore personalizzate in NGINX Ingress

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 una funzionalità integrata 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 (esempio di implementazione in YAML 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:

  1. Eseguire l'istruzione sopra dal punto riguardante default backend;
  2. Nel ConfigMap di configurazione nginx-ingress, aggiungere la chiave custom-http-errors, ad esempio, con il valore 404,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 qui).

Questo significa che dovete occupaRvi del codice di risposta corretto.. Ecco un esempio 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:

  1. Possiamo sovrascrivere il backend predefinito per ogni di Ingress con l'annotazione;
  2. Possiamo sovrascrivere custom-http-errors per ogni di Ingress con l'annotazione.

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: 80

In 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. (commit determinante in 0.23). 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: 80

Il 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 un deployment identico 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" custom-error-pages. 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

Acquista hosting affidabile per siti web con protezione DDoS, VPS VDS server 🔥 Acquista hosting affidabile per siti web con protezione DDoS, VPS VDS server | ProHoster