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 existentes nelas e as formas 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, quando consultamos o Ingress com um host que não esteja nos recursos do Ingress, obtemos uma página com um código de resposta 404:



No entanto, cada vez mais, nossos clientes vêm com uma solicitação, em vez do padrão 404, para mostrar sua página com o logotipo da empresa e outras comodidades. Para fazer isso, o NGINX Ingress possui uma capacidade interna de substituir default-backend-service . A opção com o mesmo nome, como argumento, recebe namespace/servicename registro no formato namespace/servicename . A porta de serviço deve ser 80.

Para fazer isso, crie seu próprio pod (implantação) e serviço com seu aplicativo ( um 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 por meio do YAML com o kind: Ingress cai no back-end padrão. Na lista acima, sadsdasdas tornou esse domínio.

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


Outra situação são solicitações para um aplicativo em que situações HTTP (404, 500, 502 ...) que não conseguem processar tais situações (páginas bonitas correspondentes não são geradas) acabam com erros HTTP. Também pode ser causado pelo desejo dos desenvolvedores de fornecer as mesmas páginas de erro em muitos aplicativos.

Para implementar esse caso no lado do servidor, precisamos:

  1. Siga as instruções acima no item sobre back-end padrão;
  2. Inclua a chave custom-http-errors na configuração ConfigMap nginx-ingress, por exemplo, com um valor 404,503 (obviamente, corresponde aos códigos de erro cobertos pela nova regra).

O resultado esperado é alcançado: quando o aplicativo cliente estiver em execução e receber um erro com um 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, é necessário considerar 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, ao redirecionar uma solicitação, os cabeçalhos conterão informações úteis com o código de resposta anterior e informações adicionais (uma lista completa delas está disponível aqui ).

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

Para aplicativos diferentes - back-end padrão diferente


Para que a solução não seja global para todo o cluster, mas se aplique apenas a aplicativos específicos, primeiro você precisa verificar a versão do Ingress. Se corresponder a 0,23 ou superior , use as anotações nativas do Ingress:

  1. Podemos redefinir default-backend para cada ingresso por meio da anotação ;
  2. Podemos substituir custom-http-errors para cada Ingress usando anotações .

Como resultado, o recurso do Ingress será mais ou menos assim:

 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 

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

Nas versões anteriores do Ingress, isso não era possível (o fatídico commit em 0,23 ). E se você possui 2 aplicativos completamente diferentes em execução no cluster e deseja especificar diferentes serviços de back-end padrão e manipulação de códigos de erro diferentes para cada um deles - precisará usar soluções alternativas para isso, das quais temos duas.

Ingresso <0,23: abordagem um


Esta opção é mais simples. Como um aplicativo que fornece suas páginas, temos HTML regular, que não sabe como olhar para os cabeçalhos e fornecer os códigos de resposta corretos. Esse aplicativo é lançado com o Ingress com /error-pages URL /error-pages , e o HTML será fornecido no diretório ws .

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 essa implantação deve ser do tipo ClusterIP.

Ao mesmo tempo, no aplicativo em que trataremos o erro, no Ingress, adicionamos 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; } 

Ingresso <0,23: abordagem dois


Uma opção para um aplicativo que pode lidar com cabeçalhos ... De qualquer forma, esse é um caminho mais correto, emprestado de erros de http personalizados. A utilização manual (cópia) permitirá não alterar as configurações globais.

Os passos são os seguintes. Criamos a mesma implantação com um aplicativo que pode ouvir os cabeçalhos necessários e responder corretamente. Adicione aplicativos de snippet de servidor ao 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 desejamos tratar, é necessário definir sua localização, onde todos os cabeçalhos necessários serão substituídos, como nas páginas de erro personalizadas "nativas". Assim, podemos criar páginas personalizadas diferentes com erros, mesmo para locais e servidores individuais.

PS


Outro do ciclo de dicas e truques do K8s:


Leia também em nosso blog:

Source: https://habr.com/ru/post/pt445596/


All Articles