[Kubernetes] Nginx Ingress Controller กับ Service ต่าง Namespace

Pao Payungsak Klinchampa
Next-Hop Co., Ltd.
Published in
3 min readFeb 2, 2020
Ref : https://www.nginx.com/blog/announcing-nginx-ingress-controller-for-kubernetes-release-1-5-0/

ปกติเเล้วถ้าเราไม่ได้กำหนดลงไปว่าจะ Deploy App นี้จะให้มันไปอยู่ namespace อะไร มันก็จะไปอยู่ตรง default namespace ใช่มั๊ยครับ

และถ้าเกิดว่าใน Cluster เต็มไปด้วย Service หลายๆตัว มี Deployment เต็มไปหมดหลายๆ App หรือมีหลาย Project รันอยู่ มันก็จะดูรกหูรกตานี่ซิ !!

เราก็เลยต้องสร้าง namespace เพื่อมาช่วยเเบ่งว่า ให้ App A อยู่ตรงนี้ ให้ App B อยู่ตรงนั้น มันก็จะดูดีขึ้น

หมายเหตุ : สำหรับบทความนี้เหมาะสำหรับคนเคยจับ k8s มาบ้างนะครับ ถ้ามาอ่านเลยอาจงงๆได้ เเนะนำให้ไปลองอ่านเนื้อหาพื้นฐานก่อนนะครับ

ย้อนมาที่ Nginx Ingress กันบ้าง ปกติถ้าเรา Deploy ตามต้นฉบับ .YAML ที่เค้าเขียนไว้ให้ (จากเว็บนี้) มันก็จะไปสร้าง Deployment , Service บน namespace ชื่อ ingress-nginx และเวลาเราเขียน ingress เราก็เขียนกันที่ default namespace

แต่ๆๆ ปัญหาก็จะเกิดขึ้นทันที หากเราไปเรียกใช้ Service ที่อยู่ namespace อื่นครับ เพราะเจ้า Nginx Ingress Controller มันหา Service นั้นๆไม่เจอนี่ซิ 555+

แต่ก็ใช่ว่าจะไม่มีทางเเก้นะครับ บน Kubernetes ยังมีสิ่งที่เราเรียกกันว่า external name :D

ซึ่งโดยทั่วไปเเล้ว เราจะเอา external name มาใช้เพื่อเรียกใช้ Resource ต่างๆที่อยู่นอก Cluster อย่างเช่น ถ้าใช้ EKS ของ Amazon เเล้วใช้ RDS เวลาเราจะเรียกใช้ RDS เราต้องเอา Domain name อันเเสนจะยาวที่ระบบมัน Gen ให้มาใช้

โดยที่เราสามารถใช้ external name ในการตั้ง “ชื่อเเทน” โดยตั้งให้มันสั้นลงได้ครับ

ตัวอย่างเช่น

ตั้งชื่อว่า paocloud-rds ให้ไปเรียกใช้ paocloud-rds.abcxyz.ap-southeast-1.rds.amazonaws.com อะไรเเบบนี้

เเละก็เอามาเขียน .YAML โดยมีหน้าตาเเบบนี้

kind: Service
apiVersion: v1
metadata:
name: paocloud-rds
namespace: default
labels:
environment: production
spec:
type: ExternalName
externalName: paocloud-rds.abcxyz.ap-southeast-1.rds.amazonaws.com

คราวนี้ เวลาเราจะเรียกใช้ DB เราก็ใส่ชื่อ Service เพียงเเค่ paocloud-rds สั้นๆ ไม่ต้องเอามาทั้งยาวๆได้เเล้ว

ซึ่งจะสังเกตได้ว่า การทำงานของมัน คล้ายๆกับ CNAME เลยนี่หว่า เราก็เลยจับเอามาประยุกต์ใช้กับ Nginx Ingress Controller ของเรากันครับ

เล่ารายละเอียดเยอะเเล้ว มาลองดูกันเลยดีกว่า ว่าต้องเซทอะไรบ้าง ???

ในตัวอย่าง ผมจะ Deploy game ชื่อ 2048-game ซึ่งเป็นตัวอย่างที่ AWS เอามาเขียน Doc เรื่องการใช้ ELB บน EKS นะครับ

โดยผมจะ Deploy 2048-game app ลงบน namespace ชื่อ 2048-game และผมก็สร้าง Service เพื่อให้เข้าถึง App ที่เรา Deploy เป็นเเบบ ClusterIP ซึ่งหน้าตาจะออกมาประมาณนี้

kind: Service
apiVersion: v1
metadata:
name: service-2048
namespace: 2048-game
spec:
ports:
— protocol: TCP
port: 80
targetPort: 80
selector:
app: '2048-app'
type: ClusterIP

หลังจากนั้น เราก็ไปสร้าง External Name ที่ default namespace เพื่อให้มันเข้ามาเรียกใช้ Service ของเรากันครับ โดยหน้าตาจะออกมาเเบบนี้

kind: Service
apiVersion: v1
metadata:
name: game-2048-default
namespace: default
labels:
environment: production
spec:
type: ExternalName
externalName: service-2048.2048-game.svc.cluster.local

ซึ่งผมสร้าง External Name ขึ้นมา โดยตั้งชื่อเป็น game-2048-default เเละกำหนดค่า external name ให้ชี้ไปที่ Domain name นี้

service-2048.2048-game.svc.cluster.local

โดยที่ service-2048 คือ ชื่อ Service ของ 2048-game app

2048-game ต่อมา ก็คือชื่อ namespace

เเละตามด้วย svc.cluster.local อันนี้เข้าใจว่าเป็น dns zone บน kube dns

เเละขั้นตอนสุดท้าย ก็คือ สร้าง Ingress ให้ชี้ไปหา Servie ที่ชื่อ game-2048-default ครับ ซึ่งจะได้น่าตาออกมา เเบบนี้

kind: Ingress
apiVersion: extensions/v1beta1
metadata:
name: game
namespace: default
labels:
environment: production
annotations:
kubernetes.io/ingress.class: nginx
nginx.ingress.kubernetes.io/rewrite-target: /$2
nginx.ingress.kubernetes.io/use-regex: ‘true’
spec:
rules:
— host: game.mydomain-name.com
http:
paths:
— path: /game-2048(/|$)(.*)
backend:
serviceName: game-2048-default
servicePort: 80

ในตัวอย่างผมใช้ Nginx Ingress Controller และใช้วิธี Path based routing ซึ่งเวลาจะเปิด app ก็ต้องเข้าถึงทาง http://game.mydomain-name.com/game-2048/

หน้าตาเกม 2048 นะครับ ถ้าเซทถูกต้องเข้าได้

หน้าตาเกม 2048

สรุปเเล้ว จะได้เเผนผังเเสดงการเชื่อมต่อ / ความสัมพันธ์ดังนี้ครับ

เเผนผังเเสดงการเชื่อมต่อ / ความสัมพันธ์

นอกจากนี้ เรายังสามารถเอา External Name ไปเรียกใช้ App ที่รันอยู่นอก Cluster ก็ได้นะครับ ตัวอย่างที่ผมเคยทำคือไปเรียกใช้ App ที่เป็น Web App ใช้ Nginx เป็น Web Server รันเเบบธรรมดาเลยบน AWS EC2 เพียงเเค่ใส่ IP Address ของ EC2 เครื่องนั้นๆหรือจะใส่เป็น Domain Name ก็ได้ครับ

ขอจบบทความเพียงเเค่นี้นะครับ เเล้วเจอกันในบทความถัดไป สวัสดีครับ

--

--