Tipps und Tricks zu Kubernetes: Benutzerdefinierte Fehlerseiten in NGINX Ingress

Tipps und Tricks zu Kubernetes: Benutzerdefinierte Fehlerseiten in NGINX Ingress

In diesem Artikel möchte ich über zwei Funktionen von NGINX Ingress im Zusammenhang mit der Anzeige personalisierter Fehlerseiten sprechen, sowie über die darin bestehenden Einschränkungen und Möglichkeiten, diese zu umgehen.

1. Ändern des Standard-Backends

Standardmäßig verwendet NGINX Ingress das Standard-Backend, das die entsprechende Funktion ausführt. Das heißt, wenn wir einen Ingress anfordern, der einen Host angibt, der sich nicht in den Ingress-Ressourcen befindet, erhalten wir die folgende Seite mit einem 404-Antwortcode:

Tipps und Tricks zu Kubernetes: Benutzerdefinierte Fehlerseiten in NGINX Ingress

Allerdings kommen unsere Kunden immer häufiger mit der Bitte, ihre Seite mit einem Firmenlogo und anderen Annehmlichkeiten anstelle des standardmäßigen 404 anzuzeigen. Zu diesem Zweck verfügt NGINX Ingress über integrierte Funktion neu definieren default-backend-service. Den Formateintrag übergeben wir als Argument an die gleichnamige Option namespace/servicename. Der Port des Dienstes sollte 80 sein.

Dazu müssen Sie Ihren eigenen Pod (Bereitstellung) und Dienst mit Ihrer Anwendung erstellen (Beispielimplementierung in YAML aus dem ingress-nginx-Repository), das anstelle des Standard-Backends angegeben wird.

Hier eine kleine Illustration:

~$ curl -i -XGET http://sadsdasdas.kube-cloud.my/
HTTP/1.1 404 Not Found
Date: Mon, 11 Mar 2019 05:38:15 GMT
Content-Type: */*
Transfer-Encoding: chunked
Connection: keep-alive

<span>The page you're looking for could not be found.</span>

Also alle Domains, die nicht explizit per YAML erstellt werden mit kind: Ingress, fallen in das Standard-Backend. In der obigen Auflistung wurde diese Domain zu sadsdasdas.

2. Behandeln von HTTP-Fehlern in der Anwendung mithilfe des Standard-Backends

Eine andere Situation sind Anfragen, die mit HTTP-Fehlern (404, 500, 502...) enden, an eine Anwendung, die solche Situationen nicht verarbeitet (die entsprechenden schönen Seiten werden nicht generiert). Dies kann auch auf den Wunsch der Entwickler zurückzuführen sein, dieselben Fehlerseiten in mehreren Anwendungen bereitzustellen.

Um diesen Fall serverseitig umzusetzen, benötigen wir:

  1. Befolgen Sie die Anweisungen oben im Abschnitt über das Standard-Backend.
  2. Fügen Sie der Nginx-Ingress-Konfiguration ConfigMap einen Schlüssel hinzu custom-http-errors, zum Beispiel mit dem Wert 404,503 (Entspricht offensichtlich den Fehlercodes, die von der neuen Regel abgedeckt werden).

Das erwartete Ergebnis wurde erreicht: Wenn die Clientanwendung ausgeführt wird und einen Fehler mit dem Antwortcode 404 oder 503 erhält, wird die Anfrage automatisch an das neue Standard-Backend umgeleitet ...

Wenn Sie jedoch eine Anwendung für Standard-Backend- und benutzerdefinierte HTTP-Fehler entwickeln, müssen Sie eine wichtige Funktion berücksichtigen:

!!! Important The custom backend is expected to return the correct HTTP status code instead of 200. NGINX does not change the response from the custom default backend.

Tatsache ist, dass bei der Umleitung einer Anfrage die Header nützliche Informationen mit dem vorherigen Antwortcode und zusätzlichen Informationen enthalten (eine vollständige Liste ist verfügbar). hier).

Das bedeutet, dass Sie es selbst tun müssen Achten Sie auf den richtigen Antwortcode. Hier ist ein Beispiel Aus der Dokumentation erfahren Sie, wie es funktioniert.

Verschiedene Anwendungen haben unterschiedliche Standard-Backends

Um sicherzustellen, dass die Lösung nicht global für den gesamten Cluster gilt, sondern nur für bestimmte Anwendungen gilt, müssen Sie zunächst die Ingress-Version überprüfen. Wenn es passt 0.23 oder höher, verwenden Sie die nativen Ingress-Anmerkungen:

  1. Wir können überschreiben default-backend für jeder Ingress mithilfe von Anmerkungen;
  2. Wir können überschreiben custom-http-errors für jeder Ingress mithilfe von Anmerkungen.

Infolgedessen sieht die Ingress-Ressource etwa so aus:

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 mit allen erforderlichen Headern an den Fehlerseitendienst weitergeleitet.

В Frühere Versionen von Ingress verfügten nicht über diese Funktion (schicksalhaftes Commit bei 0.23). Und wenn in Ihrem Cluster zwei völlig unterschiedliche Anwendungen ausgeführt werden und Sie für jede davon einen anderen Standard-Backend-Dienst und die Verarbeitung unterschiedlicher Fehlercodes festlegen möchten, müssen Sie hierfür Workarounds verwenden, von denen wir zwei haben.

Ingress < 0.23: Annäherung an Eins

Diese Option ist einfacher. Als Anwendung, die ihre Seiten bereitstellt, haben wir normales HTML, das nicht weiß, wie es die Header betrachten und die richtigen Antwortcodes zurückgeben soll. Eine solche Anwendung wird mit Ingress von der URL ausgerollt /error-pages, und im Katalog ws wird der zurückgegebene HTML-Code sein.

Abbildung 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 Dienst für diese Bereitstellung muss vom Typ ClusterIP sein.

Gleichzeitig fügen wir in der Anwendung, in der wir den Fehler verarbeiten, in Ingress ein Server-Snippet oder Konfigurations-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 Option für eine Anwendung, die Header verarbeiten kann ... Und im Allgemeinen ist dies eine korrektere Methode, die von benutzerdefinierten http-Fehlern übernommen wurde. Wenn Sie es manuell verwenden (kopieren), können Sie die globalen Einstellungen nicht ändern.

Die Schritte sind wie folgt. Wir erstellen gleiche Bereitstellung mit einer Anwendung, die auf die notwendigen Schlagzeilen hören und richtig reagieren kann. Fügen Sie der Ingress-Anwendung ein 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 Sie sehen, müssen wir für jeden Fehler, den wir verarbeiten möchten, einen eigenen Speicherort erstellen, in den alle erforderlichen Header eingefügt werden, wie im „nativen“ Header. benutzerdefinierte Fehlerseiten. So können wir auch für einzelne Standorte und Server unterschiedliche personalisierte Fehlerseiten erstellen.

PS

Weiteres aus der K8s-Tipps- und Trickserie:

Lesen Sie auch auf unserem Blog:

Source: habr.com

Kommentar hinzufügen