เคล็ดลับและลูกเล่น 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

ในการดำเนินการนี้ คุณต้องสร้างพ็อด (ปรับใช้) และบริการของคุณเองด้วยแอปพลิเคชันของคุณ (ตัวอย่างการใช้งานใน 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ตกเป็นค่าเริ่มต้นแบ็กเอนด์ ในรายการด้านบน โดเมนนี้กลายเป็น sadsdasdas.

2. การจัดการข้อผิดพลาด HTTP ในแอปพลิเคชันโดยใช้แบ็กเอนด์เริ่มต้น

อีกสถานการณ์หนึ่งคือการร้องขอที่ลงท้ายด้วยข้อผิดพลาด HTTP (404, 500, 502...) ไปยังแอปพลิเคชันที่ไม่ได้ประมวลผลสถานการณ์ดังกล่าว (ไม่มีการสร้างเพจที่สวยงามที่เกี่ยวข้อง) นี่อาจเป็นเพราะความต้องการของนักพัฒนาที่จะให้บริการหน้าข้อผิดพลาดเดียวกันในหลายแอปพลิเคชัน

หากต้องการใช้กรณีนี้บนฝั่งเซิร์ฟเวอร์ เราต้องการ:

  1. ปฏิบัติตามคำแนะนำข้างต้นจากย่อหน้าเกี่ยวกับแบ็กเอนด์เริ่มต้น
  2. เพิ่มคีย์ให้กับการกำหนดค่า nginx-ingress ConfigMap custom-http-errorsเช่น ด้วยค่า 404,503 (เห็นได้ชัดว่าสอดคล้องกับรหัสข้อผิดพลาดที่กฎใหม่ครอบคลุม)

บรรลุผลลัพธ์ที่คาดหวัง: เมื่อแอปพลิเคชันไคลเอนต์กำลังทำงานและได้รับข้อผิดพลาดด้วยรหัสตอบกลับ 404 หรือ 503 คำขอจะถูกเปลี่ยนเส้นทางไปยังแบ็กเอนด์เริ่มต้นใหม่โดยอัตโนมัติ...

อย่างไรก็ตาม เมื่อพัฒนาแอปพลิเคชันสำหรับแบ็กเอนด์เริ่มต้นและข้อผิดพลาด http-error ที่กำหนดเอง คุณจะต้องคำนึงถึงคุณลักษณะที่สำคัญด้วย:

!!! 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 ตัวที่ทำงานอยู่ในคลัสเตอร์ของคุณ และคุณต้องการระบุบริการแบ็กเอนด์เริ่มต้นที่แตกต่างกันและการประมวลผลรหัสข้อผิดพลาดที่แตกต่างกันสำหรับแต่ละแอปพลิเคชัน คุณจะต้องใช้วิธีการแก้ไขปัญหาชั่วคราว ซึ่งเรามีสองรายการ

ทางเข้า < 0.23: เข้าใกล้หนึ่ง

ตัวเลือกนี้ง่ายกว่า ในฐานะแอปพลิเคชันที่ให้บริการหน้าเว็บ เรามี HTML ปกติซึ่งไม่ทราบวิธีการดูส่วนหัวและส่งกลับรหัสตอบกลับที่ถูกต้อง แอปพลิเคชันดังกล่าวเปิดตัวด้วย Ingress จาก url /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 เราได้เพิ่ม server-snippet หรือ configuration-snippet ด้วยเนื้อหาต่อไปนี้:

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

ทางเข้า < 0.23: แนวทางที่สอง

ตัวเลือกสำหรับแอปพลิเคชันที่สามารถประมวลผลส่วนหัวได้... และโดยทั่วไปแล้ว นี่เป็นวิธีที่ถูกต้องกว่า โดยยืมมาจากข้อผิดพลาด http แบบกำหนดเอง การใช้ด้วยตนเอง (การคัดลอก) จะทำให้คุณไม่ต้องเปลี่ยนการตั้งค่าส่วนกลาง

ขั้นตอนมีดังนี้ เราสร้าง การใช้งานเดียวกัน ด้วยแอพพลิเคชั่นที่สามารถฟังหัวข้อข่าวที่จำเป็นและตอบสนองได้อย่างถูกต้อง เพิ่มข้อมูลโค้ดเซิร์ฟเวอร์ลงในแอปพลิเคชัน 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:

อ่านเพิ่มเติมในบล็อกของเรา:

ที่มา: will.com

เพิ่มความคิดเห็น