Trucs et astuces Kubernetes : pages d'erreur personnalisées dans NGINX Ingress

Trucs et astuces Kubernetes : pages d'erreur personnalisées dans NGINX Ingress

Dans cet article, je souhaite parler de deux fonctionnalités de NGINX Ingress liées à l'affichage de pages d'erreur personnalisées, ainsi que des limitations qui existent et des moyens de les contourner.

1. Changer le backend par défaut

Par défaut, NGINX Ingress utilise le backend par défaut, qui exécute la fonction correspondante. Cela signifie que lors d'une demande d'entrée spécifiant un hôte qui ne figure pas dans les ressources Ingress, nous recevons la page suivante avec un code de réponse 404 :

Trucs et astuces Kubernetes : pages d'erreur personnalisées dans NGINX Ingress

Cependant, de plus en plus souvent, nos clients nous demandent d'afficher leur page avec un logo d'entreprise et d'autres commodités au lieu du standard 404. Pour ce faire, NGINX Ingress a capacité intégrée redéfinir default-backend-service. On passe l'entrée de format en argument à l'option du même nom namespace/servicename. Le port du service doit être 80.

Pour ce faire, vous devez créer votre propre pod (déploiement) et service avec votre application (exemple d'implémentation dans YAML du référentiel ingress-nginx), qui sera donné à la place du backend par défaut.

Voici une petite 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>

Ainsi, tous les domaines qui ne sont pas explicitement créés via YAML avec kind: Ingress, tombe dans le backend par défaut. Dans la liste ci-dessus, ce domaine est devenu sadsdasdas.

2. Gestion des erreurs HTTP dans l'application à l'aide du backend par défaut

Une autre situation est celle des requêtes se terminant par des erreurs HTTP (404, 500, 502...) vers une application qui ne traite pas de telles situations (les belles pages correspondantes ne sont pas générées). Cela peut également être dû au désir des développeurs de diffuser les mêmes pages d'erreur dans plusieurs applications.

Pour implémenter ce cas côté serveur, nous avons besoin de :

  1. Suivez les instructions ci-dessus dans le paragraphe sur le backend par défaut ;
  2. Ajouter une clé à la configuration nginx-ingress ConfigMap custom-http-errors, par exemple, avec la valeur 404,503 (correspond évidemment aux codes d'erreur couverts par la nouvelle règle).

Le résultat attendu a été atteint : lorsque l'application client est en cours d'exécution et reçoit une erreur avec un code de réponse de 404 ou 503, la requête sera automatiquement redirigée vers le nouveau backend par défaut...

Cependant, lors du développement d'une application pour le backend par défaut et les erreurs http personnalisées, vous devez prendre en compte une fonctionnalité importante :

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

Le fait est que lorsqu'une requête est redirigée, les en-têtes contiendront des informations utiles avec le code de réponse précédent et des informations complémentaires (leur liste complète est disponible ici).

Cela signifie que vous devez vous-même faites attention au code de réponse correct. Voici un exemple à partir de la documentation comment cela fonctionne.

Différentes applications ont différents backends par défaut

Pour vous assurer que la solution n'est pas globale pour l'ensemble du cluster, mais s'applique uniquement à des applications spécifiques, vous devez d'abord vérifier la version Ingress. Si ça correspond 0.23 ou plus, utilisez les annotations Ingress natives :

  1. Nous pouvons passer outre default-backend pour chaque Entrée utiliser des annotations;
  2. Nous pouvons passer outre custom-http-errors pour chaque Entrée utiliser des annotations.

En conséquence, la ressource Ingress ressemblera à ceci :

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

Dans ce cas, les erreurs 404 et 502 seront redirigées vers le service error-pages avec tous les en-têtes nécessaires.

В les versions précédentes d'Ingress n'avaient pas cette fonctionnalité (commit fatidique à 0.23). Et si vous avez 2 applications complètement différentes en cours d'exécution dans votre cluster et que vous souhaitez spécifier un service backend par défaut différent et un traitement de codes d'erreur différents pour chacune d'elles, pour cela, vous devrez utiliser des solutions de contournement, dont nous en avons deux.

Entrée < 0.23 : approche XNUMX

Cette option est plus simple. En tant qu'application qui dessert ses pages, nous avons du HTML classique, qui ne sait pas comment regarder les en-têtes et renvoyer les codes de réponse corrects. Une telle application est déployée avec Ingress depuis l'url /error-pages, et dans le catalogue ws sera le HTML renvoyé.

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

Le service pour ce déploiement doit être de type ClusterIP.

En même temps, dans l'application où nous traiterons l'erreur, dans Ingress, nous ajoutons un extrait de serveur ou un extrait de configuration avec le contenu suivant :

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

Entrée < 0.23 : deuxième approche

Une option pour une application capable de traiter les en-têtes... Et en général, c'est une manière plus correcte, empruntée aux erreurs http personnalisées. L'utiliser manuellement (copie) vous permettra de ne pas modifier les paramètres globaux.

Les étapes sont les suivantes. Nous créons même déploiement avec une application capable d'écouter les gros titres nécessaires et de répondre correctement. Ajoutez un extrait de serveur à l'application Ingress avec le contenu suivant :

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

Comme vous pouvez le voir, pour chaque erreur que nous voulons traiter, nous devons créer notre propre emplacement, où tous les en-têtes nécessaires seront insérés, comme dans celui « natif ». pages d'erreur personnalisées. De cette façon, nous pouvons créer différentes pages d'erreur personnalisées, même pour des emplacements et des serveurs individuels.

PS

Autres trucs et astuces de la série K8s :

A lire aussi sur notre blog :

Source: habr.com

Ajouter un commentaire