Basic Kubernetes Part 6 - Ingress
ในการติดต่อกันระหว่าง Client Server ในชั้น Application Layer นั้นเราจะใช้ IP กับ Port ซึ่ง Protocol HTTP ใช้ port 80 , HTTPS ใช้ port 443 ทุกอย่างเหมือนไม่มีปัญหาอะไร แต่ปัญหาเกิดขึ้นเมื่อเครื่องเรา deploy application หลายๆ appliaction ซึ่งหลายๆ application นั้นใช้ protocol http , https ซึ่งเราไม่สามารถให้ 2 pod ใช้ Port เดียวกันได้ จะให้ใช้ Port แบบ 32010 , 32020 ก็ไม่สะดวกเพราะ คนใช้งานต้องกำหนด Port มาใน URL ซึ่งน่าจะสร้างความลำบากให้ผู้ใช้น่าดู
ถ้าเป็นการ Deploy แบบไม่ใช่ k8s นั้นเรามีวิธีทำคือ เราก็สร้าง Reverse proxy (nginx , apache) ขึ้นมาแล้ว Run บน Port 80 , 443 จากนั้นก็ให้มันรับ Request แล้ว routing ตามกฏไปหา Application ที่ต้องการ
คราวนี้ถ้าเราอยากทำแบบนี้บน k8s ล่ะจะทำยังไง จากความรู้ที่เรามีเราไม่สามารถทำได้ เพราะตอนเราสร้าง service แบบ NodePort ไม่สามารถตั้งค่า Port เป็น 80 , 443 ได้ ดังนั้นเราไม่สามารถเอา nginx หรือ apache ไปวางได้ แล้วเราจะทำยังไงล่ะ
จากความต้องการแบบนี้ตัว k8s ได้กำหนดสิ่งที่เรียกว่า Ingress ขึ้นมามาให้เราเพื่อทำตามความต้องการที่อยากได้ โดย Ingress นี้เป็นแค่ Spec ของ Configfile เท่านั้นไม่มีตัวที่ทำงานจริง ตัวที่ทำงานจริงคือ Ingress controller ซึ่ง Ingress controller มีให้เราใช้มากมายตัวอย่างเช่น
โดยใครอยากใช้ Ingress controller ตัวไหนก็ลองเข้าไปดูวิธี Install ที่ Document ของแต่ละเจ้าได้เลย ส่วนใครที่ใช้ VM ของผมนั้น ตัว k3s เขาลงตัว Traefik Ingress controller มาให้แล้ว ดังนั้นไม่ต้องลงเพิ่มนะครับ
ลองสร้าง Ingress กัน
ตัวอย่างไฟล์ Config สามารถได้ดูได้ที่ Link
เตรียม Application (Pod)
อันดับเแรกมาทำการสร้าง Application (Pod) บน k8s กันก่อน โดยสร้างไฟล์ : nginx-whoami-app.yml
1 | apiVersion: apps/v1 |
จากนั้นทดสอบเปิด Browser แล้วเข้าไปที่ URL
- http://<ip ที่ run k8s>:32010 (ของผมคือ http://192.168.156.101:32010)
- http://<ip ที่ run k8s>:32020 (ของผมคือ http://192.168.156.101:32020)
จากภาพจะเห็นว่าเราสามารถเข้าถึง nginx ผ่าน port 32010 และ whoami ผ่าน port 32020
Set file host
เนื่องจากเราไม่ได้จด Domain name : nginx-application.com และ whoami-application.com ไว้ (ต่อให้จดได้ก็จะไม่ได้ ip ตรงกันเพราะแต่ละเครื่องที่ run k8s มี ip ไม่เหมือนกัน) ดังนั้นจะไม่สามารถ resolve domain name ได้ แต่เราสามารถแก้ปัญหานี้ได้โดยการกำหนดค่าในไฟล์ : hosts ซึ่งไฟล์ host นี้แต่ละ os อยู่ไม่เหมือนกัน โดยแต่ละ os ไฟล์จะอยู่ที่
- windows : c:\Windows\System32\Drivers\etc\hosts
- linux : /etc/hosts
- macOs : /private/etc/hosts
เมื่อเปิดไฟล์ให้และเพิ่มข้อมูลลงไปคือ
1 | <ip เครื่องที่ run k8s> nginx-application.com |
ซึ่งของผมจะได้เป็น
1 | 192.168.156.101 nginx-application.com |
ทำการทดสอบลองใช้คำสั่ง ping ไปที่ nginx-application.com , whoami-application.com ว่าทำการ resolve ip เป็น ip ที่ตั้งไว้หรือไม่
1 | ping nginx-application.com |
สร้าง Ingress
สร้างไฟล์ basic-ingress.yml จากนั้นสั่ง apply file
1 | apiVersion: networking.k8s.io/v1 |
จากนั้นลอง get และ describe ingress ดูครับ
จากภาพจะเห็นว่ามี Ingress ชื่อ basic-ingress ขึ้นมาและมีการบอก host และ path ซึ่งตรงกับที่เรากำหนดในไฟล์ อีกทั้งมีชื่อ service คือ nginx-service , whoami-service
จากนั้นลองเข้า browser แล้วเปิด URL
- nginx-application.com
- whoami-application.com
จากภาพจะเห็นว่าสามารถเปิดหน้าได้ตรงตามความต้องการของเราคือ เข้า nginx-application.com ก็ไปหา nginx เข้า whoami-application.com ก็ไปหา whoami ซึ่งนั่นแปลว่า Ingress ของเราทำงานได้ตรงตามความต้องการของเราแล้ว
อธิบายไฟล์ basic-ingress.yml
ในส่วนของ apiVersion , kind , metadata ไม่ขอลงรายละเอียดเพราะเหมือนกับตัวอื่นๆที่ผ่านมา
rules
ตรงนี้จะเป็นการประกาศเกี่ยวกับ rule (มีได้หลาย rule) ที่ใช้ในการ route ของ Ingress (Reverse Proxy) ถ้าเทียบง่ายๆก็เหมือน file nginx.conf ของ nginx ที่เรากำหนดว่ามาด้วย host นี้จะให้ส่งไปที่ไหนต่อ โดย rule จะเป็นไปตามรายละเอียดต่อไปนี้
1 | - host: "nginx-application.com" |
host
ตรงส่วนนี้จะเป็นการบอกกฏว่า request ที่มาต้องมีค่า host ตรงกับ nginx-application.com
http
ตรงนี้เป็นการบอกว่าถ้าเป็น protocol http
paths
ตรงนี้จะเป็นการบอกต่อว่าเมื่อเข้ามาด้วย http แล้วจะใช้ path อะไรในการ map (มีได้หลาย path)
path
1 | - path: / |
ตรงนี้จะเป็นการบอกรายละเอียดแล้วว่าต้องตรงด้วย path อะไร ลักษณะของการ map เป็นแบบไหน ถ้า map ตรงแล้วจะให้ยิงไปที่ service ไหน port อะไร
จากตัวอย่างจะเป็นการว่า ถ้า map ที่ path : / การ map เป็นแบบ Prefix คือถ้าขึ้นต้นด้วย / จะถือว่าตรงตามเงื่อนไขหมด ซึ่งถ้าตรงตามเงื่อนไขทั้งหมดเนี่ยให้ route request นี้ไปหา service : nginx-service ที่ port 80
สรุปการ config rule
1 | - host: "nginx-application.com" |
rule นี้มีความหมายคือ request ที่ยิงเข้ามามีค่า host == nginx-application.com แล้วมี path ที่ขึ้นต้นด้วย / จะถูก route request ไปที่ nginx-service port 80
สิ่งที่ต้องอ่านเพิ่มเติม
การตั้งค่าเพิ่มเติม Ingress Controller
ที่อยู่ในตัวอย่างทั้งหมดของเรานั้นเป็น Ingress กลางๆที่ k8s กำหนดขึ้นให้ใช้ได้กับทุก IngressController ซึ่ง Rule ที่ตั้งได้นั้นมีจำกัดมากๆแค่ host กับ path จะ route ด้วยเงื่อนไขอื่นๆ เช่น header ที่เรากำหนดเป็นต้น หรือ เวลา Route แล้วให้เราทำการแก้ไข path เพิ่ม header ที่ต้องการ อันนี้ไม่สามารถทำได้ผ่านการประกาศแบบนี้
แต่ถามว่าทำได้ไหม ก็ต้องบอกว่าสามารถทำได้ครับ แต่ต้องเพิ่มการประกาศตาม Ingress controller ที่คุณเลือกใช้ เช่น
- Nginx : เราสามารถใช้ Feature ต่างๆแบบที่ nginx reverse proxy ทำได้แต่ต้องประกาศในส่วนของ Annotation โดยสามารถดูรายละเอียดการ config ได้ที่ Link
- Traefik : ถ้าอยากใช้ Feature ที่มากกว่าที่ k8s กำหนดต้องประกาศตัว IngressRoute ของ Traefik เพิ่ม โดยสามารถดูรายละเอียดการ config ได้ที่ Link และดู Annotation ได้ที่ Link
- Contour : ตัวนี้จะคล้ายๆกับตัว Traefik ที่ต้องทำการประกาศ Ingress ของตัว Contour เองเพื่อใช้ Feature ของ Contour โดยสามารถดูรายละเอียดการ Config ได้ที่ Link
การ Set ssl ให้กับ Ingress
ในตัวอย่างที่เราได้ทดลองนั้น เราทดลองสร้าง Ingress ที่เป็นแบบ http แต่ในการทำงานจริงๆนั้นคนที่ใช้งานจริงๆนั้นใช้งานแบบ https นั้นจะต้อง set อย่างไร โดยสามารถดูรายละเอียดการ setting ได้ที่ : Link
สรุป
สำหรับตอนนี้เราได้ทำความรู้จักกับ Ingress ว่าคืออะไร เอาไปใช้อะไรกับกรณีไหน rule ที่เราพอตั้งให้ได้คืออะไร ซึ่งถ้าใครอ่านมาตั้งแต่ตอนแรกจนถึงตอนนี้ก็น่าจะสามารถ Deploy application ขึ้น k8s ไปใช้งานได้แล้ว (แต่ไม่ได้ดีมาก และไม่ถูกต้องตาม best practice ) แต่อ่านอย่างเดียวอาจจะไม่เข้าใจ ตอนหน้าเรามาลองทำการ Deploy application สักตัวกันว่าถ้าต้องทำโจทย์แบบนี้แล้วเราต้องทำอะไรบ้าง