Kubernetes 提示和技巧:NGINX Ingress 中的自定义错误页面

Kubernetes 提示和技巧:NGINX Ingress 中的自定义错误页面

在本文中,我想谈谈 NGINX Ingress 与显示个性化错误页面相关的两个功能,以及它们存在的限制以及解决方法。

1. 更改默认后端

默认情况下,NGINX Ingress 使用默认后端,执行相应的功能。 这意味着当请求 Ingress 指定的主机不在 Ingress 资源中时,我们会收到以下带有 404 响应代码的页面:

Kubernetes 提示和技巧:NGINX Ingress 中的自定义错误页面

然而,我们的客户越来越多地要求显示带有公司徽标和其他设施的页面,而不是标准的 404。 为此,NGINX Ingress 有 内置功能 重新定义 default-backend-service。 我们将格式条目作为参数传递给同名选项 namespace/servicename。 该服务的端口应为 80。

为此,您需要使用应用程序创建自己的 pod(部署)和服务(YAML 中的示例实现 来自 ingress-nginx 存储库),它将代替默认后端。

这是一个小例子:

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

另一种情况是以 HTTP 错误(404、500、502...)结尾的请求,发送到不处理此类情况的应用程序(不会生成相应的漂亮页面)。 这也可能是由于开发人员希望在多个应用程序中提供相同的错误页面。

为了在服务器端实现这个案例,我们需要:

  1. 按照上面有关默认后端的段落中的说明进行操作;
  2. 在 nginx-ingress 配置 ConfigMap 中添加一个键 custom-http-errors,例如,值为 404,503 (显然对应于新规则涵盖的错误代码)。

预期结果已经达到:当客户端应用程序运行并收到响应代码 404 或 503 的错误时,请求将自动重定向到新的默认后端...

但是,在开发默认后端和自定义 http 错误的应用程序时,您需要考虑一个重要功能:

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

事实上,当请求重定向时,标头将包含有用的信息以及先前的响应代码和附加信息(它们的完整列表可用 这里).

这意味着你自己必须 注意正确的响应代码. 下面是一个例子 从文档中可以看出它是如何工作的。

不同的应用程序有不同的默认后端

为了确保该方案不是针对整个集群全局的,而是只适用于特定应用,首先需要检查Ingress版本。 如果匹配的话 0.23 或更高,使用原生 Ingress 注解:

  1. 我们可以重写 default-backend 入口的 使用注释;
  2. 我们可以重写 custom-http-errors 入口的 使用注释.

结果,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 将被重定向到带有所有必要标头的错误页面服务。

В 之前版本的Ingress没有这个功能 (0.23 的致命承诺)。 如果您的集群中运行着 2 个完全不同的应用程序,并且您想要为每个应用程序指定不同的默认后端服务并处理不同的错误代码,为此您将必须使用解决方法,我们有两个解决方法。

Ingress < 0.23:方法一

这个选项比较简单。 作为为其页面提供服务的应用程序,我们有常规的 HTML,它不知道如何查看标头并返回正确的响应代码。 这样的应用程序是通过 url 中的 Ingress 推出的 /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 中添加包含以下内容的服务器片段或配置片段:

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。 手动使用它(复制)将允许您不更改全局设置。

步骤如下。 我们创造 相同的部署 具有可以收听必要的标题并正确响应的应用程序。 将包含以下内容的服务器片段添加到 Ingress 应用程序:

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

正如您所看到的,对于我们想要处理的每个错误,我们需要创建自己的位置,其中将插入所有必要的标头,就像“本机”标头一样。 自定义错误页面。 通过这种方式,我们甚至可以为各个位置和服务器创建不同的个性化错误页面。

PS

K8s 提示和技巧系列中的其他内容:

另请阅读我们的博客:

来源: habr.com

添加评论