如何自定义通过nginx入口控制器的默认后端提供的错误页面?

时间:2020-02-14 21:48:33

标签: nginx kubernetes

我正在Kubernetes集群上运行通过Helm安装的Nginx Ingress Controller。我想针对某些特定错误(例如404)更改默认后端服务中的HTML / CSS。

This链接提供了有关默认后端的一些常规信息。但是,没有提到如何实际自定义提供的HTML / CSS文件。

5 个答案:

答案 0 :(得分:12)

好的,这些答案中的某些部分对于寻求完整的解决方案很有帮助,尤其是@@ Matt中的解决方案。但是,我花了很多时间才能完成此工作,因此我决定用其他人可能也会遇到的所有必需的详细信息写自己的答案。


第一件事是创建一个Docker图像服务器,该服务器能够响应除/healthz/metrics之外的所有带有404内容的请求。正如@ Matt所提到的,这可能是一个Nginx实例(我已经使用过)。总结一下:

  • /healthz应该返回200
  • /metrics是可选的,但是如果您将其用于k8s度量标准,它应该返回Prometheus可读的数据。 Nginx可以提供Prometheus可以读取的一些基本数据。如果您想与Nginx全面集成Prometheus,请考虑使用此link
  • /返回带有自定义HTML内容的404。

因此,Dockerfile看起来像这样:

FROM nginx:alpine

# Remove default NGINX Config
# Take care of Nginx logging
RUN rm /etc/nginx/conf.d/default.conf && \
    ln -sf /dev/stdout /var/log/nginx/access.log && \
    ln -sf /dev/stderr /var/log/nginx/error.log

# NGINX Config
COPY ./default.conf /etc/nginx/conf.d/default.conf

# Resources
COPY content/ /var/www/html/

CMD ["nginx", "-g", "daemon off;"]

在Dockerfile所在的文件夹中,创建以下default.conf Nginx配置文件:

server {
    root /var/www/html;
    index 404.html;

    location / {

    }

    location /healthz {
        access_log off;
        return 200 "healthy\n";
    }

    location /metrics {
        # This creates a readable and somewhat useful response for Prometheus
        stub_status on;
    }

    error_page 404 /404.html;
    location = /404.html {
        internal;
    }
}

最后,根据您的喜好提供一个带有HTML / CSS的content/404.html文件。

现在使用以下命令构建Docker映像:

docker build --no-cache -t custom-default-backend .

标记此图像,以便准备将其推入DockerHub(或您自己的私有Docker注册表):

docker tag custom-default-backend:latest <your_dockerhub_username>/custom-default-backend

将映像推送到DockerHub存储库:

docker push <your_dockerhub_username>/custom-default-backend

现在是将此自定义默认后端映像集成到Helm安装中的部分。为此,我们首先需要创建此k8s资源文件(custom_default_backend.yaml):

---
apiVersion: v1
kind: Service
metadata:
  name: custom-default-backend
  namespace: ingress-nginx
  labels:
    app.kubernetes.io/name: custom-default-backend
    app.kubernetes.io/part-of: ingress-nginx
spec:
  selector:
    app.kubernetes.io/name: custom-default-backend
    app.kubernetes.io/part-of: ingress-nginx
  ports:
  - port: 80
    targetPort: 80
    name: http
---
apiVersion: apps/v1
kind: Deployment
metadata:
  name: custom-default-backend
  namespace: ingress-nginx
  labels:
    app.kubernetes.io/name: custom-default-backend
    app.kubernetes.io/part-of: ingress-nginx
spec:
  replicas: 1
  selector:
    matchLabels:
      app.kubernetes.io/name: custom-default-backend
      app.kubernetes.io/part-of: ingress-nginx
  template:
    metadata:
      labels:
        app.kubernetes.io/name: custom-default-backend
        app.kubernetes.io/part-of: ingress-nginx
    spec:
      containers:
      - name: custom-default-backend
        # Don't forget to edit the line below
        image: <your_dockerhub_username>/custom-default-backend:latest
        imagePullPolicy: Always
        ports:
        - containerPort: 80

假设我们已经创建了一个k8s命名空间ingress-nginx,我们可以创建这两个资源。

kubectl apply -f custom_default_backend.yaml

现在,为了将Nginx Ingress Controller与我们的新服务绑定在一起,我们可能只需编辑Ingress Controller的部署即可。但是我决定通过Helm将其完全删除:

helm delete nginx-ingress -n ingress-nginx

并使用此命令再次安装(确保您具有包含适当参数的--set标志)

helm install nginx-ingress --namespace ingress-nginx stable/nginx-ingress --set defaultBackend.enabled=false,controller.defaultBackendService=ingress-nginx/custom-default-backend

使用这些步骤,您应该最终得到一个有效的自定义默认后端实现。 Here是一个GitHub存储库,其中包含我在此答案中使用的文件。

答案 1 :(得分:1)

该项目提供了Go custom error application,可以将其内置到容器映像中以替换default-backenderrorHandler function发挥了神奇作用。

最后,这是一台Web服务器,它响应除/healthz/metrics之外的所有带有404内容的请求。如果需要,可以使用nginx实例和html错误页面来实现。

您可能不想使用完整的custom error handling,这与入口控制器将在常规应用后端中查找某些HTTP状态代码并将其传递给默认后端进行处理的方式略有不同。除非他们从一开始就打算使用它,否则这对于大多数应用程序都会引起问题。

答案 2 :(得分:1)

您需要创建和部署自定义默认后端,这将返回自定义错误页面。遵循doc来部署自定义默认后端,并通过修改部署yaml以使用此自定义默认后端来配置nginx入口控制器。

自定义默认后端的部署yaml为here,源代码为here

答案 3 :(得分:0)

可以在以下位置找到默认 httpbackend 的 docker: https://github.com/interlegis/nginx-ingress-controller-defaultbackend

在 root/etc/nginx 文件夹下,您可以根据自己的方便修改 nginx.conf。 然后构建更新docker并部署。 (您可以查看上面的答案如何部署) 与其删除入口控制器然后安装,不如修改已部署的服务,使其指向您的 pod,您部署该服务以替换默认的 http 后端。

可能以上答案可以让您更轻松。但是如果你已经在运行生产环境,我不建议把nginx ingress controller去掉再重新安装。

答案 4 :(得分:0)

我以前遇到过这个问题,..但我有一个想法,使用路由路径“/”到服务..所以入口控制器不会再次显示 404 页面..它可以工作!!!

  1. 创建一个简单服务的部署,就我而言,我使用的是 this 80端口

  2. 然后,将部署公开为服务

    kubectl 公开部署部署名称 --port=80

  3. 最后一步,我们应该配置入口资源以将此服务路由到“/”路径


apiVersion: networking.k8s.io/v1beta1
kind: Ingress
metadata:
  name: default-ingress
  annotations:
    ingress.kubernetes.io/rewrite-target: /
spec:
  rules:
  - http:
      paths:
        - path: /
          backend:
            serviceName: service-name
            servicePort: 80