Kubernetes nasveti & triki: prilagojene strani z napakami v NGINX Ingress

Kubernetes saveti & trikovi: personalizovane stranice grešaka u NGINX Ingress

V tem članku želim spregovoriti o dveh možnostih NGINX Ingress, povezanih z oblikovanjem personaliziranih strani napak, ter o obstoječih omejitvah in načinov, kako jih obiti.

1. Sprememba privzetega backend-a

Privzeto NGINX Ingress uporablja default backend, ki opravlja ustrezno nalogo. To pomeni, da ob zahtevi Ingress-a z navedbo gostitelja, ki ni v virih Ingress, prejmemo stran s kodo odgovora 404:

Kubernetes saveti & trikovi: personalizovane stranice grešaka u NGINX Ingress

Vendar pa vse pogosteje naši naročniki prihajajo s prošnjo, da namesto standardnega 404 prikažemo svojo stran s logotipom in drugimi udobnostmi. Za to ima NGINX Ingress vgrajeno možnost prekoračiti default-backend-service. Kot argument prehodimo zapis v formatu namespace/servicename. Port storitve mora biti 80.

Zato je potrebno ustvariti svoj pod (deployment) in storitev z vašo aplikacijo (primer implementacije v YAML iz repozitorija ingress-nginx), ki bo prikazana namesto default backend.

Tukaj je majhna ilustracija:

~$ 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>Stran, ki jo iščete, ni bila najdena.</span>

Tako vsi domene, ki niso izrecno ustvarjene preko YAML z kind: Ingress, spadajo v default-backend. V seznamu zgoraj je takšna domena sadsdasdas.

2. Obdelava HTTP napak v aplikaciji z uporabo default backend-a

Druga situacija je, ko zahtevki do aplikacije končajo z HTTP napakami (404, 500, 502…) in v njej takšne situacije niso obdelane (ustrezne lepe strani se ne generirajo). To lahko izhaja tudi iz želje razvijalcev, da vodijo enotne strani napak v več aplikacijah.

Za uresničitev tega primera na strežniški strani moramo:

  1. Izvesti zgornja navodila iz točke o default backend;
  2. V konfiguracijski ConfigMap nginx-ingress dodati ključ custom-http-errors, na primer, z vrednostjo 404,503 (očitno se nanaša na kode napak, na katere se novo pravilo razteza).

Želeni rezultat je dosežen: ob delu odjemalske aplikacije in prejemanju napake s kodo odgovora 404 ali 503 se bo zahteva samodejno preusmerila v nov default backend…

Vendar pa je pri razvoju aplikacije za default backend in custom-http-errors potrebno upoštevati pomembno značilnost:

!!! Pomembno Od prilagojenega backend-a se pričakuje, da vrne pravilno HTTP statusno kodo namesto 200. NGINX ne spremeni odgovora iz prilagojenega default backend-a.

Grese je u tome što će prilikom preusmjeravanja zahtjeva biti korisne informacije u zaglavljima s prethodnim kodom odgovora i dodatnim informacijama (cijeli njihov popis je dostupan ovde).

To znači da se sami morate pobrinuti za ispravan kod odgovora. Evo primjera iz dokumentacije, kako to funkcionira.

Raznim aplikacijama odgovara različiti default backend

Kako rješenje ne bi bilo globalno za cijeli klaster, već se odnosilo samo na određene aplikacije, prvo treba provjeriti verziju Ingress-a. Ako odgovara 0.23 ili novijoj verziji, iskoristite „nativne“ anotacije Ingress-a:

  1. Možemo redefinirati default-backend za svaki Ingress-a pomoću anotacije;
  2. Možemo redefinirati custom-http-errors za svaki Ingress-a pomoću anotacije.

Kao rezultat, resurs Ingress-a će izgledati otprilike ovako:

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

U tom slučaju, greške 404 i 502 će biti preusmjerene na servis error-pages sa svim potrebnim zaglavljima.

V u prethodnim verzijama Ingress-a ta mogućnost nije postojala (sudbonosni commit u 0.23). Ako u vašem klasteru rade 2 potpuno različite aplikacije i želite za svaku od njih odrediti različite default-backend-servise i za obradu različitih kodova grešaka — za to će biti potrebno koristiti workaround-e, kojih imamo dva.

Ingress < 0.23: prvi pristup

Ova opcija je jednostavnija. Kao aplikacija koja isporučuje svoje stranice, imamo običan HTML koji ne može gledati na zaglavlja i vraćati ispravne kodove odgovora. Takva aplikacija se koristi s Ingress-om s url-om /error-pages, a u katalogu ws bit će HTML koji se isporučuje.

Ilustracija u YAML-u:

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

Servis za ovaj deploy treba biti s tipom ClusterIP.

Pri tome, u aplikaciji gdje ćemo obraditi grešku, dodajemo server-snippet ili configuration-snippet s sljedećim sadržajem:

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: druga opcija

Opcija za aplikaciju koja može obraditi zaglavlja… Uostalom, ovo je ispravniji način koji je preuzet iz custom-http-errors. Njegova ručna upotreba (kopiranje) omogućava da se ne menjaju globalne postavke.

Koraci su sledeći. Kreiramo isti deployment s aplikacijom koja može slušati potrebna zaglavlja i pravilno odgovoriti. Dodajemo u Ingress aplikacije server-snippet sa sledećim sadržajem:

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

Kao što se može videti, za svaku grešku koju želimo obraditi, potrebno je napraviti svoj location gde će se ubacivati svi potrebni zaglavlja, kao u "izvornom" custom-error-pages. Tako možemo kreirati različite personalizovane stranice sa greškama čak i za pojedinačne location-e i servere.

P.S.

Još jedan iz serije K8s saveta & trikova:

Preberite tudi na našem blogu:

Izvor: habr.com

Kupite zanesljivo gostovanje za spletne strani z zaščito pred DDoS, VPS VDS strežniki 🔥 Kupite zanesljivo gostovanje za spletne strani z zaščito pred DDoS, VPS VDS strežniki | ProHoster