ติดตั้งและใช้งาน Multiple NGINX Ingress Controller, New release 1.11.1, for Kubernetes
Tags: nginx, kubernetes, ingress
Published: 2021-04-09 16:19:23

เมื่อเราพูดถึง NGINX Ingress Controller จะมี 3 แบบครับ ต่างกันที่ Based และ Maintainer
- Maintained by the Kubernetes community and based on NGINX Open Source
- Maintained by NGINX and based on NGINX Open Source
- Maintained by NGINX and based on NGINX Plus

ถ้าทำ Performance test ระหว่าง 3 แบบ แน่นอนว่า NGINX Plus ได้ผลดีที่สุด
Ref: https://www.nginx.com/blog/performance-testing-nginx-ingress-controllers-dynamic-kubernetes-cloud-environment/
        
        
<h1> Environment </h1>
Kubernetes version 1.20.5
NGINX Ingress Controller New release 1.11.1, Maintained by NGINX and based on NGINX Open Source
        
สำหรับ NGINX Ingress Controller แบบ based on NGINX Plus จะคล้ายกันในแง่การติดตั้ง ยกเว้น Subscription และ Advance Features ครับ


<h1> Ingress คืออะไร </h1>
เนื่องจาก Applications บน Kubernetes Cluster วิ่งอยู่ใน Overlay network ของตนเอง คนภายนอกจึงมองไม่เห็น เข้าไปใช้งานไม่ได้

วิธีหนึ่งเพื่อให้เข้าถึง Applications ภายใน Kubernetes Cluster คือเรียกใช้งานผ่าน NGINX Ingress Controller

Ingress จึงเปรียบเสมือนประตูเข้าบ้าน เพื่อเช้าไปใช้งาน Application ในบ้าน
โดย Applications ก็จะเปรียบได้กับห้องทำงาน หรือห้องนั่งเล่นครับ

![Alt Text](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/r877tk9rb4j025dom7be.jpg)


<h1> การทำงานภายใน NGINX Ingress Controller </h1> 
NGINX Ingress Controller มีความสามารถจำเป็นพื้นฐาน 2 ข้อ
1. ความสามารถในการเป็นคนกลาง เชื่อมระหว่าง Client ภายนอก กับ Application ภายใน สามารถทำได้หลายวิธี เช่นทำ NodePort ที่ Kubernetes services
![Alt Text](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/8h3t2v9os845fg7yfgax.jpg)ตัวอย่าง NodePort 32230 จะเชื่อมกับ NGINX Port 80, และ NodePort 31825 จะเชื่อมกับ Port 443 ฉะนั้นเมื่อเราต้องการเรียกใช้บริการแบบ HTTPS สามารถเรียกใช้ผ่าน IP ของ node ที่ port: 31825


2. ความสามารถในการ Load Balance 
เนื่องจากภายใน Kubernetes Cluster ประกอบไปด้วย Application หลาย ๆ ตัวอยู่รวมกัน ฉะนั้น Ingress Controller ต้องสามารถส่งต่อ Request ไปยัง Service ปลายทางที่ถูกต้องได้
![Alt Text](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/gaepfh38b3l81q52l5to.jpg)ตัวอย่าง NGINX Load Balance Pool ที่ประกอบไปด้วย IP:Port ของ pod ปลายทาง ถ้า pod ใดตาย เกิด pod ใหม่มาแทนที่, NGINX Load Balance Pool จะทำการอัพเดท IP:Port ของ pod ใหม่เข้ามา
          
          
          
ฉะนั้น ถ้าเราสร้าง Service เพิ่มขึ้นมาอีก 1 ตัว โดยให้มีความสามารถ 2 ข้อนี้ ก็จะได้ Ingress เพิ่มขึ้นมาครับ
![Alt Text](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/w8p5calzgl9fclp04n7w.jpg)
          
          

<h1> Multiple Ingress Controller </h1>
เรามาดูเบื้องหลังการทำงานของ NGINX Ingress Controller ให้ลึกลงไปอีกนิดครับ ตอนสร้าง Ingress หรือที่เรามักเรียกว่าสร้าง yaml ที่เป็น kind: Ingress จะมีการระบุค่าที่จำเป็น ได้แก่ ชื่อ Ingress, host, paths, serviceName, servicePort

![Alt Text](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/rjv1qdn77an9zee85vh7.jpg)ไฟล์ cafe-ingress.yaml ที่เราทำการ kubectl create -f ไปนั้น จะถูก Controller อ่าน และแปลงไปเป็น NGINX Configuration ใน NGINX Ingress Controller เพื่อที่จะสามารถ Load Balance requests ไปยังกลุ่มของ pods ที่อยู่หลัง Service ได้ตรงกับที่ระบุไว้ใน cafe-ingress.yaml
![Alt Text](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/hojr9lrxota5a073gadx.jpg)รูปนี้เป็นการใช้ VirtualServer ซึ่งเป็น CRD ที่สร้างขึ้นให้มีความสามารถมากกว่า Ingress ธรรมดาครับ



การสร้าง Multiple Ingress Controller เพื่อให้ Controller นำ Configuration จาก Ingress มา Apply ให้กับ Ingress Controller ที่กำหนด มีหลักดังนี้

1. ถ้า NGINX Ingress Controller ไม่มีการกำหนดค่า หรือใช้ค่า Default, เมื่อมีการสร้าง Ingress(e.g. cafe-ingress.yaml) โดย Ingress นี้ก็ไม่มีการกำหนดค่าเช่นกัน controller จะอ่าน Configuration จาก Ingress ที่สร้าง แล้วเขียนลง NGINX Ingress Controller

2. ถ้า NGINX Ingress Controller มีการกำหนดค่า watchNamespace, controller จะนำค่าจาก Ingress เฉพาะที่อยู่ใน Namespace ที่กำหนดเท่านั้น มาเขียนลง NGINX Ingress Controller โดยตัว NGINX Ingress Controller อาจจะอยู่ที่ Namespace อื่นก็ได้

3. ถ้า Ingress มีการกำหนดค่า ingressClass, controller จะตรวจสอบว่าตรงกับ ingressClass ใน NGINX Ingress Controller หรือไม่ ถ้าตรงกันจึงจะเขียนลง NGINX Ingress Controller
(หาก Ingress ไม่ได้ระบุ ingressClass แต่แรก จะเข้าเงื่อนไขข้อ 1.)

ทำการสร้าง NGINX Ingress Controller 3 ตัว เพื่อทดสอบกฎข้างต้น โดยตัวแรกไม่กำหนดค่าใดๆ(default), ตัวที่สองกำหนด watchNamespace: home, ตัวที่สามกำหนด ingressClass: capital

![Alt Text](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/ofe8xbuvljbp1x4ljsc7.jpg)จะได้ Ingress Controller 3 ตัว ต่างก็ Expose service แบบ NodePort คนละชุด

จากนั้นทำการสร้าง cafe-ingress.yaml แล้วทดสอบว่าถูกเขียน Configuration ไปยัง NGINX Ingress Controller ตัวไหนบ้าง
![Alt Text](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/v6gjwajn2cr08bcvd09f.jpg)
default-ingress controller, เข้าเงื่อนไข เพราะไม่ได้กำหนด watchNamespace จึงรับทุก namespace, และ ingress ไม่ได้ระบุ ingressClass จึงไม่ติดเรื่อง ingressClass

home-ingress controller เข้าเงื่อนไข เพราะสร้าง ingress บน namespace: home ตรงกับที่ home-ingress controller ทำการ watch อยู่

capital-ingress controller เข้าเงื่อนไข เพราะถึงแม้ capital-ingress จะมีการระบุ ingressClass, แต่ cafe-ingress.yaml ไม่ได้มีการระบุ ingressClass ด้วย จึงถือไม่ได้ว่า ingress Class ไม่ตรงกัน(ปฏิเสธ ซ้อน ปฏิเสธ จึงเข้าเงื่อนไข)

สรุป เราสามารถที่จะเรียกใช้งาน cafe-ingress ได้จากทั้ง NGINX Ingress Controller default, home และ capital

<h1> Use case 1: </h1>กำหนดให้ทีมงาน home Department มีสิทธิ์สร้างและใช้งาน Kubernetes resource บน namespace: home ฉะนั้นเมื่อสร้าง NGINX Ingress home ให้ watchNamespace: home จะได้ Ingress สำหรับทีม home ไว้ใช้งาน โดย Ingress Controller นี้จะรับ Configuration จาก Ingress ที่สร้างภายใต้ namespace: home เท่านั้น
![Alt Text](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/r0qlnfha1lva2zu0d60c.jpg)

<h1> Use case 2: </h1> หากต้องการกำหนดความละเอียดที่ลึกกว่าระดับ namespace, สามารถเจาะจงเป็นราย Ingress ได้ครับ เริ่มจากเตรียม NGINX Ingress Controller-capital ให้กำหนด ingressClass=capital จากนั้น เมื่อต้องการใช้งาน NGINX Ingress Controller-capital จะต้องระบุ ingressClass=capital ให้ตรงกันเท่านั้น ถึงจะใช้งานได้
![Alt Text](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/x342g1v5eiq9t1cb714n.jpg)

watchNamespace และ ingressClass สามารถใช้งานพร้อมกันได้ครับ โดยจะต้องตรงเงื่อนไขครบทั้งสองกรณี Ingress นั้นจึงจะถูกนำมาเขียนลงบน NGINX Ingress Controller



การใช้ Multiple Ingress Controller ช่วยให้แต่ละทีม Manage resource สะดวกขึ้น, สามารถเลือกรัน NGINX Ingress Controller บน Kubernetes Worker Node เฉพาะที่เรามีสิทธิ์ใช้งานได้, ช่วย Isolate หาก Ingress Controller ตัวใดใช้งานไม่ได้ ก็จะไม่กระทบทั้ง Cluster