Kubernetes Tipps & Tricks: personalisierte Fehlerseiten im NGINX Ingress

Kubernetes Tipps & Tricks: Personalisierte Fehlerseiten im NGINX Ingress

In diesem Artikel möchte ich zwei Funktionen von NGINX Ingress vorstellen, die mit der Anzeige von personalisierten Fehlerseiten verbunden sind, sowie die bestehenden Einschränkungen und mögliche Lösungen dafür.

1. Änderung des Standard-Backends

Standardmäßig verwendet NGINX Ingress ein Default-Backend, das diese Funktion erfüllt. Das bedeutet, dass bei einer Anfrage an den Ingress mit einem Host, der nicht in den Ingress-Ressourcen vorhanden ist, eine Seite mit dem Antwortcode 404 angezeigt wird:

Kubernetes Tipps & Tricks: Personalisierte Fehlerseiten im NGINX Ingress

Immer häufiger kommen jedoch unsere Kunden mit der Bitte, anstelle des standardmäßigen 404 eine eigene Seite mit ihrem Logo und weiteren Annehmlichkeiten anzuzeigen. Dafür bietet NGINX Ingress eine integrierte Möglichkeit das default-backend-service. Als Argument für die gleichnamige Option übergeben wir den Eintrag im Format namespace/servicename. Der Port des Dienstes muss 80 sein.

Dazu ist es notwendig, einen eigenen Pod (Deployment) und einen Service mit Ihrer Anwendung zu erstellen (Beispielimplementierung in YAML aus dem Repository ingress-nginx), das anstelle des Default-Backends ausgegeben wird.

Hier ist eine kleine Illustration:

~$ curl -i -XGET http://sadsdasdas.kube-cloud.my/
HTTP/1.1 404 Nicht gefunden
Datum: Mo, 11. Mär 2019 05:38:15 GMT
Content-Type: */*
Transfer-Encoding: chunked
Verbindung: keep-alive

<span>Die angeforderte Seite konnte nicht gefunden werden.</span>

So gelangen alle Domains, die nicht ausdrücklich über YAML mit kind: Ingresserstellt wurden, ins Default-Backend. Im obigen Listing wurde somit diese Domain. sadsdasdas.

2. Verarbeitung von HTTP-Fehlern in der Anwendung durch das Default-Backend

Ein weiteres Szenario sind HTTP-Fehler (404, 500, 502...), die bei Anfragen an eine Anwendung auftreten, die solche Fälle nicht behandelt (es werden keine entsprechenden schönen Seiten generiert). Dies kann auch durch den Wunsch der Entwickler verursacht werden, identische Fehlerseiten in mehreren Anwendungen bereitzustellen.

Um diesen Anwendungsfall auf der Serverseite zu realisieren, benötigen wir:

  1. Führen Sie die oben genannte Anweisung zum Default-Backend aus;
  2. Fügen Sie dem ConfigMap nginx-ingress den Schlüssel custom-http-errors, beispielsweise mit dem Wert 404,503 (offensichtlich entsprechend den Fehlercodes, auf die die neue Regel zutrifft).

Das erwartete Ergebnis wurde erreicht: Bei der Nutzung der Clientanwendung und dem Auftreten eines Fehlers mit dem Antwortcode 404 oder 503 wird die Anfrage automatisch an das neue Default-Backend umgeleitet...

Bei der Entwicklung der Anwendung für das Default-Backend und custom-http-errors muss jedoch eine wichtige Besonderheit berücksichtigt werden:

!!! Wichtig: Das benutzerdefinierte Backend wird erwartet, dass es den korrekten HTTP-Statuscode anstelle von 200 zurückgibt. NGINX ändert die Antwort des benutzerdefinierten Default-Backends nicht.

Das Problem ist, dass bei der Weiterleitung einer Anfrage im Header nützliche Informationen mit dem vorherigen Antwortcode und zusätzlichen Informationen vorhanden sind (eine vollständige Liste finden Sie in der Dokumentation). hier).

Das bedeutet, dass Sie selbst für den korrekten Antwortcode sorgen müssen.. Hier ist ein Beispiel aus der Dokumentation, wie das funktioniert.

Für verschiedene Anwendungen gibt es unterschiedliche Standard-Backends.

Damit die Lösung nicht global für das gesamte Cluster gilt, sondern nur für spezifische Anwendungen, sollten Sie zunächst die Version von Ingress überprüfen. Wenn sie 0.23 oder höher ist,verwenden Sie die "native" Annotationen von Ingress:

  1. Wir können den default-backend für jede von Ingress mit Hilfe der Annotation;
  2. Wir können den custom-http-errors für jede von Ingress mit Hilfe der Annotation.

In der Folge wird die Ingress-Ressource etwa so aussehen:

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 diesem Fall werden die Fehler 404 und 502 an den Dienst error-pages mit allen erforderlichen Headers weitergeleitet.

In In früheren Versionen von Ingress gab es diese Möglichkeit nicht. (entscheidender Commit in 0.23). Und wenn in Ihrem Cluster zwei völlig verschiedene Anwendungen laufen und Sie für jede von ihnen unterschiedliche default-backend-service und die Verarbeitung verschiedener Fehlercodes angeben möchten – müssen Sie dafür Workarounds nutzen, von denen wir zwei haben.

Ingress < 0.23: erster Ansatz

Diese Option ist einfacher. Für die Anwendung, die ihre Seiten bereitstellt, haben wir normales HTML, das nicht auf Header schauen und korrekte Antwortcodes zurückgeben kann. Eine solche Anwendung wird mit Ingress unter der URL /error-pages, und im Verzeichnis ws wird das ausgelieferte HTML liegen.

Illustration 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

Der Service für dieses Deployment sollte vom Typ ClusterIP sein.

In der Anwendung, in der wir den Fehler behandeln, fügen wir im Ingress server-snippet oder configuration-snippet mit folgendem Inhalt hinzu:

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: zweiter Ansatz

Eine Variante für Anwendungen, die Header verarbeiten können... Im Übrigen ist dies der korrekteste Weg, abgeleitet aus custom-http-errors. Die manuelle Verwendung (Kopieren) erlaubt es, globale Einstellungen nicht zu ändern.

Die Schritte sind folgende: Wir erstellen einen identischen Deployment mit einer Anwendung, die in der Lage ist, die erforderlichen Header zu lauschen und korrekt zu antworten. Fügen Sie im Ingress der Anwendung den server-snippet mit folgendem Inhalt hinzu:

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;
      }

Wie zu sehen ist, muss für jeden Fehler, den wir behandeln möchten, eine eigene Location erstellt werden, in der alle notwendigen Header wie im „Original“ eingesetzt werden. custom-error-pages. So können wir verschiedene personalisierte Fehlerseiten sogar für einzelne Standorte und Server erstellen.

P.S.

Weitere aus der Reihe K8s Tipps & Tricks:

Lesen Sie auch in unserem Blog:

Quelle: habr.com

Kaufen Sie zuverlässiges Hosting für Websites mit DDoS-Schutz, VPS VDS-Server 🔥 Kaufen Sie zuverlässiges Hosting für Websites mit DDoS-Schutz, VPS VDS-Server | ProHoster