Kubernetes tips & tricks: personlige fejlsider i NGINX Ingress

Kubernetes tips & tricks: personlige fejlsider i NGINX Ingress

I denne artikel vil jeg tale om to muligheder i NGINX Ingress, der vedrører visningen af personlige fejlmeddelelser samt de eksisterende begrænsninger og måder at omgå dem på.

1. Ændring af standard backend

Som standard bruger NGINX Ingress en default backend, der udfører den tilsvarende funktion. Det betyder, at når der anmodes om Ingress med en vært, der ikke findes i Ingress-ressourcerne, får vi en side med svarkoden 404:

Kubernetes tips & tricks: personlige fejlsider i NGINX Ingress

Men i stigende grad henvender vores kunder sig med anmodninger om, at i stedet for standard 404, vise deres egen side med firmalogo og andre bekvemmeligheder. Til dette har NGINX Ingress en indbygget mulighed til at overskrive default-backend-service. Den samme optionsparameter modtager en post i formatet namespace/servicename. Porten for servicen skal være 80.

For dette er det nødvendigt at oprette sin egen pod (deployment) og service med din applikation (eksempel på implementering i YAML fra ingress-nginx-repositoriet), som vil blive brugt i stedet for default backend.

Her er en lille illustration:

~$ curl -i -XGET http://sadsdasdas.kube-cloud.my/
HTTP/1.1 404 Not Found
Dato: Man, 11 Mar 2019 05:38:15 GMT
Indholdstype: */*
Overførselskodning: chunked
Forbindelse: hold-alive

<span>Den side, du leder efter, kunne ikke findes.</span>

Dermed vil alle domæner, der ikke eksplicit er oprettet gennem YAML med kind: Ingress, ramme default-backend. I listen ovenfor blev et sådant domæne sadsdasdas.

2. Håndtering af HTTP-fejl i applikationen via default backend

En anden situation er anmodninger til applikationen, der afsluttes med HTTP-fejl (404, 500, 502…) og hvor sådanne situationer ikke håndteres (dvs. der genereres ikke tilsvarende pæne sider). Dette kan også være forårsaget af udviklernes ønske om at returnere ensartede fejlmeddelelser i mange applikationer.

For at implementere dette tilfælde på serversiden er vi nødt til:

  1. At udføre instruktionen ovenfor fra punktet om default backend;
  2. I konfigurations ConfigMap nginx-ingress tilføje nøglen custom-http-errors, for eksempel med værdien 404,503 (åbenlyst svarende til fejl koderne, der gælder for den nye regel).

Det ønskede resultat er opnået: når klientapplikationen fungerer og modtager en fejl med svarkoden 404 eller 503, vil anmodningen automatisk blive omdirigeret til den nye default backend…

Men når man udvikler applikationen til default backend og custom-http-errors, skal en vigtig funktion tages i betragtning:

!!! Vigtigt Den tilpassede backend forventes at returnere den korrekte HTTP-statuskode i stedet for 200. NGINX ændrer ikke svaret fra den tilpassede default backend.

Det er sådan, at når en forespørgsel omdirigeres, vil der være nyttig information i headerne med den tidligere svarkode og yderligere oplysninger (den fulde liste er tilgængelig her).

Det betyder, at du selv skal tage sig af den korrekte svarkode. Her er et eksempel fra dokumentationen om, hvordan det fungerer.

Forskellige applikationer — forskellig default backend

For at løsningen ikke skal være global for hele klyngen, men kun gælde for specifikke applikationer, skal vi først kontrollere versionen af Ingress. Hvis den svarer til 0.23 eller højere, kan du bruge de "native" Ingress-annoteringer:

  1. Vi kan overskrive default-backend for hver for Ingress med hjælp af en annotering;
  2. Vi kan overskrive custom-http-errors for hver for Ingress med hjælp af en annotering.

Som et resultat vil Ingress-ressourcen se nogenlunde sådan ud:

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

I dette tilfælde vil fejl 404 og 502 blive omdirigeret til service error-pages med alle nødvendige headers.

I I tidligere versioner af Ingress var denne mulighed ikke tilgængelig (den skæbnesvangre commit i 0.23). Og hvis du har 2 helt forskellige applikationer kørende i din klynge, og du vil angive forskellige default-backend-services og håndtere forskellige fejlkoder for hver af dem — skal du bruge workarounds, som vi har to af.

Ingress < 0.23: tilgang nummer et

Denne mulighed er den enklere. Som applikation, der leverer sine sider, har vi almindelig HTML, der ikke kan se på headerne og returnere korrekte svarkoder. En sådan applikation implementeres med Ingress med url /error-pages, og i kataloget ws vil den leverede HTML være.

Illustration i 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

Servicen til denne deployment skal have typen ClusterIP.

I applikationen, hvor vi skal håndtere fejlen, tilføjer vi server-snippet eller configuration-snippet i Ingress med følgende indhold:

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: den anden tilgang

En mulighed for en applikation, der kan håndtere headers... Generelt er det en mere korrekt metode, overtaget fra custom-http-errors. Dens manuelle brug (kopiering) vil ikke ændre de globale indstillinger.

Trinene er som følger. Vi opretter den samme deployment med en applikation, der kan lytte på de nødvendige headers og svare korrekt. Vi tilføjer i Ingress-applikationen server-snippet med følgende indhold:

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

Som det fremgår, skal hver fejl, vi ønsker at håndtere, have sin egen location, hvor alle nødvendige headers indsættes, ligesom i "oprindelige" custom-error-pages. På den måde kan vi oprette forskellige personlige fejlsider selv for enkelte location'er og servere.

P.S.

En anden fra K8s tips & tricks:

Læs også på vores blog:

Kilde: habr.com

Køb pålidelig webhosting med DDoS-beskyttelse, VPS VDS-servere 🔥 Køb pålidelig webhosting med DDoS-beskyttelse, VPS VDS-servere | ProHoster