Kubernetes tips & tricks: персаналізаваныя старонкі памылак у NGINX Ingress

Kubernetes tips & tricks: персаналізаваныя старонкі памылак у NGINX Ingress

У дадзеным артыкуле я жадаю распавесці пра дзве магчымасці NGINX Ingress, злучаныя з адлюстраваннем персаналізаваных старонак з памылкамі, а таксама аб існых у іх абмежаваннях і спосабах іх абыйсці.

1. Змена бэкенда па змаўчанні

Па змаўчанні ў NGINX Ingress выкарыстоўваецца default backend, які выконвае адпаведную функцыю. Гэта азначае, што пры запыце Ingress'а з указаннем хаста, якога няма ў Ingress-рэсурсах, мы атрымліваем такую ​​старонку з кодам адказу 404:

Kubernetes tips & tricks: персаналізаваныя старонкі памылак у NGINX Ingress

Аднак усё часцей нашы кліенты прыходзяць з просьбай замест стандартнага 404 паказаць сваю старонку з фірмовым лагатыпам і іншымі выгодамі. Для гэтага ў NGINX Ingress ёсць убудаваная магчымасць перавызначыць default-backend-service. Аднайменнай опцыі ў якасці аргумента перадаем запіс фармату namespace/servicename. Порт у сэрвісу павінен быць 80.

Для гэтага неабходна стварыць свой pod (deployment) і сэрвіс з вашым дадаткам (прыклад рэалізацыі ў YAML з рэпазітара ingress-nginx), якое будзе аддавацца замест default backend.

Вось невялікая ілюстрацыя:

~$ 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>

Такім чынам, усе дамены, якія відавочна не створаны праз YAML з kind: Ingress, трапляюць у default-backend. У лістынгу вышэй такім даменам стаў sadsdasdas.

2. Апрацоўка HTTP-памылак у дадатку сіламі default backend

Іншая сітуацыя - сканчаюцца HTTP-памылкамі (404, 500, 502 ...) запыты да дадатку, у якім не апрацоўваюцца такія сітуацыі (не генеруюцца адпаведныя прыгожыя старонкі). Гэта можа быць таксама выклікана жаданнем распрацоўшчыкаў аддаваць аднолькавыя старонкі памылак у мностве прыкладанняў.

Для рэалізацыі дадзенага кейса на серверным баку нам неабходна:

  1. Выканаць інструкцыю вышэй з пункта пра default backend;
  2. У канфігурацыйны ConfigMap nginx-ingress дадаць ключ custom-http-errors, напрыклад, са значэннем 404,503 (відавочна, адпавядае кодам памылкі, на якія распаўсюджваецца новае правіла).

Чаканы вынік дасягнуты: пры працы кліенцкага прыкладання і атрыманні памылкі з кодам адказу 404 ці 503 запыт будзе аўтаматычна перанакіраваны ў новы default backend…

Аднак пры распрацоўцы дадатку для default backend і custom-http-errors трэба ўлічыць важную асаблівасць:

!!! 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.

Справа ў тым, што пры перанакіраванні запыту ў загалоўках будзе карысная інфармацыя з папярэднім кодам адказу і дадатковай інфармацыяй (поўны іх спіс даступны тут).

Гэта азначае, што вы самі павінны паклапаціцца аб карэктным кодзе адказу. Вось прыклад з дакументацыі, як гэта працуе.

Розным прыкладанням - розны default backend

Каб рашэнне не было глабальным на ўвесь кластар, а ставілася толькі да пэўных прыкладанняў, для пачатку трэба праверыць версію Ingress. Калі яна адпавядае 0.23 або вышэй, скарыстайцеся «роднымі» анатацыямі Ingress:

  1. Мы можам перавызначыць default-backend для кожнага Ingress'а з дапамогай анатацыі;
  2. Мы можам перавызначыць custom-http-errors для кожнага Ingress'а з дапамогай анатацыі.

У выніку, рэсурс Ingress будзе выглядаць прыкладна так:

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

У такім выпадку памылкі 404 і 502 будуць перанакіраваны ў сэрвіс error-pages са ўсімі патрэбнымі загалоўкамі.

В папярэдніх версіях Ingress такой магчымасці не было (лёсавызначальны коміт у 0.23). І калі ў вас у кластары працуе 2 зусім розных прыкладання і вы хочаце для кожнага з іх паказваць розныя default-backend-service і апрацоўку розных кодаў памылак – для гэтага давядзецца скарыстацца workaround'амі, якіх у нас два.

Ingress < 0.23: падыход першы

Гэты варыянт прасцейшы. У якасці дадатку, якое аддае свае старонкі, у нас звычайны HTML, які не ўмее глядзець на загалоўкі і аддаваць карэктныя коды адказу. Такое прыкладанне выкочваецца з Ingress'ом з url /error-pages, а ў каталогу ws будзе ляжаць які аддаецца HTML.

Ілюстрацыя ў 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

Сэрвіс для гэтага дэплою павінен быць з тыпам ClusterIP.

Пры гэтым у прыкладанні, дзе будзем апрацоўваць памылку, у Ingress'е дадаем server-snippet або configuration-snippet са наступным змесцівам:

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: другі падыход

Варыянт для прыкладання, якое ўмее апрацоўваць загалоўкі… Ды і ўвогуле гэта больш карэктны шлях, запазычаны з custom-http-errors. Яго выкарыстанне ўручную (капіраванне) дазволіць не змяняць глабальныя наладкі.

Крокі наступныя. Ствараем такі ж deployment з дадаткам, якое ўмее слухаць патрэбныя загалоўкі і адказваць карэктна. Дадаем у Ingress прыкладанні server-snippet з наступным змесцівам:

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

Як відаць, для кожнай памылкі, якую мы жадаем апрацоўваць, трэба зрабіць свой location, дзе будуць падстаўляцца ўсе неабходныя загалоўкі, як у «роднай» custom-error-pages. Так мы можам ствараць розныя персаналізаваныя старонкі з памылкамі нават для асобных location'аў і сервераў.

PS

Іншае з цыклу K8s tips & tricks:

Чытайце таксама ў нашым блогу:

Крыніца: habr.com

Дадаць каментар