Dicas e truques do Kubernetes: páginas de erro personalizadas no NGINX Ingress

Dicas e truques do Kubernetes: páginas de erro personalizadas no NGINX Ingress

Neste artigo, quero falar sobre dois recursos do NGINX Ingress relacionados à exibição de páginas de erro personalizadas, bem como as limitações que existem nelas e maneiras de contorná-las.

1. Alterando o back-end padrão

Por padrão, o NGINX Ingress usa o back-end padrão, que executa a função correspondente. Isso significa que ao solicitar um Ingress especificando um host que não está nos recursos do Ingress, recebemos a seguinte página com um código de resposta 404:

Dicas e truques do Kubernetes: páginas de erro personalizadas no NGINX Ingress

No entanto, cada vez mais nossos clientes chegam com um pedido para mostrar sua página com um logotipo corporativo e outras comodidades em vez do padrão 404. Para fazer isso, o NGINX Ingress tem capacidade integrada redefinir default-backend-service. Passamos a entrada do formato como argumento para a opção de mesmo nome namespace/servicename. A porta do serviço deve ser 80.

Para fazer isso, você precisa criar seu próprio pod (implantação) e serviço com seu aplicativo (exemplo de implementação em YAML do repositório ingress-nginx), que será fornecido em vez do back-end padrão.

Aqui está uma pequena ilustração:

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

Portanto, todos os domínios que não são criados explicitamente via YAML com kind: Ingress, caia no back-end padrão. Na listagem acima, este domínio tornou-se sadsdasdas.

2. Tratamento de erros HTTP no aplicativo usando o back-end padrão

Outra situação são as solicitações que terminam em erros HTTP (404, 500, 502...) para uma aplicação que não processa tais situações (as belas páginas correspondentes não são geradas). Isso também pode ser devido ao desejo dos desenvolvedores de exibir as mesmas páginas de erro em vários aplicativos.

Para implementar este caso no lado do servidor, precisamos:

  1. Siga as instruções acima do parágrafo sobre backend padrão;
  2. Adicione uma chave ao ConfigMap de configuração do nginx-ingress custom-http-errors, por exemplo, com o valor 404,503 (corresponde obviamente aos códigos de erro abrangidos pela nova regra).

O resultado esperado foi alcançado: quando a aplicação cliente estiver em execução e receber um erro com código de resposta 404 ou 503, a solicitação será redirecionada automaticamente para o novo backend padrão...

No entanto, ao desenvolver um aplicativo para back-end padrão e erros de http personalizados, você precisa levar em consideração um recurso 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.

O fato é que quando uma solicitação é redirecionada, os cabeçalhos conterão informações úteis com o código de resposta anterior e informações adicionais (a lista completa está disponível aqui).

Isso significa que você mesmo deve cuide do código de resposta correto. Aqui está um exemplo. da documentação como funciona.

Aplicativos diferentes têm back-ends padrão diferentes

Para garantir que a solução não seja global para todo o cluster, mas se aplique apenas a aplicativos específicos, primeiro é necessário verificar a versão do Ingress. Se corresponder 0.23 ou superior, use as anotações nativas do Ingress:

  1. Podemos substituir default-backend para cada Entrada usando anotações;
  2. Podemos substituir custom-http-errors para cada Entrada usando anotações.

Como resultado, o recurso do Ingress será parecido com isto:

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

Neste caso, os erros 404 e 502 serão redirecionados para o serviço de páginas de erro com todos os cabeçalhos necessários.

В versões anteriores do Ingress não tinham esse recurso (commit fatídico em 0.23). E se você tiver 2 aplicativos completamente diferentes em execução em seu cluster e quiser especificar um serviço de back-end padrão diferente e processar códigos de erro diferentes para cada um deles, para isso você terá que usar soluções alternativas, das quais temos duas.

Entrada <0.23: abordagem um

Esta opção é mais simples. Como uma aplicação que atende suas páginas, temos o HTML normal, que não sabe olhar os cabeçalhos e retornar os códigos de resposta corretos. Esse aplicativo é implementado com o Ingress a partir do URL /error-pagese no catálogo ws será o HTML retornado.

Ilustração em 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

O serviço para esta implantação deve ser do tipo ClusterIP.

Ao mesmo tempo, na aplicação onde processaremos o erro, no Ingress adicionamos um snippet de servidor ou snippet de configuração com o seguinte conteúdo:

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

Entrada <0.23: segunda abordagem

Uma opção para um aplicativo que pode processar cabeçalhos... E em geral esta é uma forma mais correta, emprestada de erros http personalizados. Usá-lo manualmente (copiar) permitirá que você não altere as configurações globais.

As etapas são as seguintes. Nós criamos mesma implantação com um aplicativo que pode ouvir as manchetes necessárias e responder corretamente. Adicione um snippet de servidor ao aplicativo Ingress com o seguinte conteúdo:

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

Como você pode ver, para cada erro que queremos processar, precisamos fazer um local próprio, onde serão inseridos todos os cabeçalhos necessários, como no “nativo”. páginas de erro personalizadas. Desta forma, podemos criar diferentes páginas de erro personalizadas, mesmo para locais e servidores individuais.

PS

Outros da série de dicas e truques do K8s:

Leia também em nosso blog:

Fonte: habr.com

Adicionar um comentário