kubernetes下定制 http 50x 以及 40x 服务器返回信息的话,如果用 Nginx 做 ingress,大家会很自然想到直接用 nginx 来定制:

        error_page   500 502 503 504  /50x.html;
        location = /50x.html {
            root   /export/html;
        }

这样做是不行的,因为 Nginx 作为 ingress 来使用,就不能落地,只能做转发;如果你落地了,访问了本地文件,就违背了初衷。而且在 ingress 的 pod 上放页面,会导致 ingress 的配置错乱。

那么正确 50x 重定位的方法如下:首先建立一个 deploy 和对应的 svc,就是建立一个 web 服务器,能提供服务返回 50x 和 40x 的定制页面;然后在 ingress

内指定 custom-http-errors 和 default-backend 指向它就可以了。

一、建立miniserve的deploy和svc

我们选用 rust 的 miniserve 作为 web 服务器,准备好定制好的 index.html,写个 Dockerfile

网址:https://github.com/svenstaro/miniserve

FROM alpine:3.12
RUN apk add --update bash && rm -rf /var/cache/apk/*

COPY . /data/

RUN    rm -rf /data/Dockerfile

WORKDIR /data
EXPOSE 8080

CMD ["/data/miniserve","--index","index.html"]
#CMD /bin/sh -c "while true; do echo hi; sleep 10; done"

作出镜像后推送到阿里镜像:registry.cn-shanghai.aliyuncs.com/rendoumi/miniserve:lastest

然后准备好 deploy和 svc,部署到 kubernetes 里

---
apiVersion: apps/v1
kind: Deployment
metadata:
  name: miniserve-deploy
  labels:
    app: miniserve
spec:
  replicas: 1
  selector:
    matchLabels:
      app: miniserve
  template:
    metadata:
      labels:
        app: miniserve
    spec:
      containers:
      - name: miniserve
        image: registry.cn-shanghai.aliyuncs.com/rendoumi/miniserve:lastest
        imagePullPolicy: Always
        ports:
        - containerPort: 8080
---
apiVersion: v1
kind: Service
metadata:
 name: miniserve-svc
 labels:
   app: miniserve
spec:
 ports:
 - name: http
   protocol: TCP
   port: 80
   targetPort: 8080
 selector:
   app: miniserve
 type: ClusterIP

二、修改ingress

修改的地方就是 annotations 的最后两行:

apiVersion: networking.k8s.io/v1beta1 
kind: Ingress 
metadata: 
  name: kala-com-ingress 
  annotations: 
    kubernetes.io/ingress.class: "nginx" 
    nginx.ingress.kubernetes.io/limit-connections: "2" 
    nginx.ingress.kubernetes.io/limit-rpm: "2" 
    nginx.ingress.kubernetes.io/limit-rps: "1" 
    nginx.ingress.kubernetes.io/app-root: "/webui/" 
    nginx.ingress.kubernetes.io/auth-type: basic 
    nginx.ingress.kubernetes.io/auth-secret: kala-auth 
    nginx.ingress.kubernetes.io/auth-realm: 'Authentication Required - Kala' 
    nginx.ingress.kubernetes.io/default-backend: "miniserve-svc" 
    nginx.ingress.kubernetes.io/custom-http-errors: "403,404,500,502,503,504" 
spec: 
  rules: 
  - host: kala.rendoumi.com 
    http: 
      paths: 
      - path: / 
        backend: 
          serviceName: kala-svc 
          servicePort: 80

测试的话用 wrk 压住,然后curl再测就503转到miniserve-svc

wrk -c 3 -t 3 -d 10 http://kala.rendoumi.com/webui/ --latency 

curl -v -H "Host: kala.rendoumi.com" http://kala.rendoumi.com/webui/