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

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

In questo articolo voglio parlare di due possibilità di NGINX Ingress relative alla visualizzazione di pagine di errore personalizzate, nonché delle limitazioni esistenti e dei modi per superarle.

1. Modificare il backend predefinito

Per impostazione predefinita, in NGINX Ingress viene utilizzato il backend predefinito, che svolge la funzione corrispondente. Ciò significa che quando si richiede un Ingress specificando un host 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 chiedono di mostrare la propria pagina con logo aziendale e altre comodità anziché il consueto 404. A tal fine, NGINX Ingress offre una funzione integrata per sovrascrivere default-backend-service. Per l'opzione omonima, passiamo come argomento una registrazione nel formato namespace/servicename. La porta del servizio deve essere 80.

Per fare ciò, è necessario creare il proprio pod (deployment) e servizio con la propria applicazione (esempio di implementazione in YAML del repository ingress-nginx), che verrà restituita invece del backend predefinito.

Ecco una piccola illustrazione:

~$ 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>La pagina che stai cercando non è stata trovata.</span>

Pertanto, tutti i domini che non sono stati esplicitamente creati tramite YAML con kind: Ingress, vanno a finire nel default-backend. Nell'elenco sopra, tale dominio è diventato sadsdasdas.

2. Gestione degli errori HTTP nell'applicazione tramite il backend predefinito

Un'altra situazione riguarda le richieste all'applicazione che terminano con errori HTTP (404, 500, 502…) e in cui queste situazioni non vengono gestite (non vengono generate pagine belle corrispondenti). Questo può anche essere causato dalla volontà degli sviluppatori di restituire pagine di errore identiche in molte applicazioni.

Per implementare questo caso sul lato server, è necessario:

  1. Eseguire le istruzioni sopra riportate riguardanti il backend predefinito;
  2. Aggiungere la chiave custom-http-errorsal ConfigMap nginx-ingress, ad esempio, con valore 404,503 (ovviamente, corrisponde ai codici di errore a cui si applica la nuova regola).

Il risultato atteso è stato raggiunto: quando l'applicazione client lavora e riceve un errore con codice di risposta 404 o 503, la richiesta verrà automaticamente reindirizzata al nuovo backend predefinito…

Tuttavia, nella sviluppo dell'applicazione per il backend predefinito e custom-http-errors è importante considerare una caratteristica fondamentale:

!!! Importante Il backend personalizzato deve restituire il corretto codice di stato HTTP invece di 200. NGINX non modifica la risposta dal backend predefinito personalizzato.

Il fatto è che, durante il reindirizzamento della richiesta, ci sarà un'informazione utile negli header con il precedente codice di risposta e informazioni aggiuntive (l'elenco completo è disponibile qui).

Questo significa che dovete occupa[vi] del codice di risposta corretto. Ecco un esempio dalla documentazione su come funziona.

Applicazioni diverse - backend predefiniti diversi

Affinché la soluzione non sia globale per l'intero cluster, ma si riferisca solo a specifiche applicazioni, bisogna prima controllare la versione di Ingress. Se corrisponde a 0.23 o superiore, utilizzare le annotazioni "native" di Ingress:

  1. Possiamo sovrascrivere default-backend per ogni di Ingress con l'ausilio di un'annotazione;
  2. Possiamo sovrascrivere custom-http-errors per ogni di Ingress con l'ausilio di un'annotazione.

Di conseguenza, la risorsa Ingress avrà un aspetto simile a questo:

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 questo caso, gli errori 404 e 502 verranno reindirizzati al servizio error-pages con tutti gli header necessari.

In nelle versioni precedenti di Ingress non c'era questa possibilità (il commit decisivo in 0.23). E se nel vostro cluster stanno funzionando 2 applicazioni completamente diverse e volete specificare per ciascuna di esse diversi default-backend-service e gestire diversi codici di errore - dovrete utilizzare workaround, di cui ne abbiamo due.

Ingress < 0.23: primo approccio

Questa opzione è più semplice. Come applicazione che fornisce le proprie pagine, abbiamo un comune HTML, che non è in grado di analizzare gli header e di fornire i codici di risposta corretti. Tale applicazione viene implementata con Ingress con URL /error-pages, mentre nella directory ws ci sarà l'HTML fornito.

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 questa distribuzione deve essere di tipo ClusterIP.

Nel contempo, nell'applicazione in cui gestiremo l'errore, in 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: il secondo approccio

Opzione per un'applicazione in grado di gestire gli header... È anche un percorso più corretto, preso in prestito da custom-http-errors. L'uso manuale (copia) non modificherà le impostazioni globali.

I passi sono i seguenti. Creiamo un deployment identico con un'app che può ascoltare gli header necessari 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 si può vedere, per ogni errore che desideriamo gestire, è necessario creare un proprio location, dove verranno inseriti tutti gli header necessari, come in "native" custom-error-pages. In questo modo possiamo creare diverse pagine personalizzate di errore anche per singoli location e server.

P.S.

Altro dal ciclo K8s tips & tricks:

Leggi 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