ข้ามไปยังเนื้อหา

DNS และ Service Discovery

CoreDNS ให้ทุก Service มี DNS name ที่คาดเดาได้ ทำให้ Pod หากันด้วยชื่อแทนที่จะเป็น IP และ headless Service เปลี่ยนจาก IP เดียวที่ load balance ให้กลายเป็น IP ของแต่ละ Pod ที่อยู่เบื้องหลังโดยตรง

CoreDNS รันเป็น Deployment อยู่ใน cluster (ปกติอยู่ใน kube-system) และทำหน้าที่เป็น DNS server ภายในของ cluster ทุก Pod ถูกตั้งค่าผ่าน /etc/resolv.conf ให้ส่ง DNS query ไปที่ CoreDNS พอ Service ถูกสร้างขึ้น CoreDNS จะเริ่มตอบชื่อของ Service นั้นทันทีด้วยชื่อเต็มในรูปแบบ

<service-name>.<namespace>.svc.cluster.local
Terminal window
# From inside any Pod in the cluster
nslookup payments.default.svc.cluster.local

ถ้าอยู่ใน namespace เดียวกัน ชื่อแบบสั้นก็ใช้ได้เหมือนกัน เพราะ DNS search path ของ Pod จะมี suffix svc.cluster.local ของ namespace ตัวเองต่อท้ายให้อัตโนมัติ

Terminal window
# From a Pod that lives in the same namespace as the "payments" Service
nslookup payments
curl http://payments/health

สำหรับ Service ปกติ (ไม่ใช่ headless) ชื่อนั้นจะ resolve ไปที่ A/AAAA record เดียว คือ ClusterIP ของ Service ทุก request ที่ยิงไปชื่อนั้นก็ยังถูก load balance ไปยัง Pod เบื้องหลังผ่าน kube-proxy อยู่ดี DNS แค่พา client ไปหา virtual IP เท่านั้น

บางครั้ง client ต้องการเข้าถึง Pod ตัวใดตัวหนึ่งเจาะจง ไม่ใช่แค่ “Pod ตัวไหนก็ได้ที่ healthy อยู่หลัง Service” การตั้ง clusterIP: None จะสร้าง headless Service

apiVersion: v1
kind: Service
metadata:
name: cache
spec:
clusterIP: None
selector:
app: cache
ports:
- port: 6379

headless Service จะไม่มี virtual IP เลย แทนที่ด้วยการที่ CoreDNS ตอบกลับ IP ของทุก Pod ที่ match และพร้อมใช้งานโดยตรง query ยังคง resolve ชื่อเดิม cache.default.svc.cluster.local แต่คำตอบตอนนี้กลายเป็นลิสต์ของ Pod IP แทนที่จะเป็น ClusterIP เดียว

StatefulSet ให้แต่ละ Pod มี identity ที่เสถียร เช่น web-0, web-1, web-2 และจับคู่กับ headless Service (ผ่าน spec.serviceName) เพื่อให้แต่ละ Pod มี DNS record ของตัวเองที่เสถียรด้วย

<pod-name>.<service-name>.<namespace>.svc.cluster.local
Terminal window
# Reach one specific ordinal Pod directly, not a load-balanced peer
nslookup web-0.cache.default.svc.cluster.local

นี่คือสิ่งที่ระบบ stateful แบบ distributed ต้องการเป๊ะ ๆ database replica ต้องต่อกลับไปที่ peer ตัวเดิม ที่เคยต่อไว้ ไม่ใช่ตัวสุ่มที่ load balancer เลือกให้ ถ้าไม่มี headless Service DNS record รายตัวแบบนี้จะไม่มีทางเกิดขึ้นเลย

flowchart TB
  pod["Client Pod"] -->|"DNS query"| coredns["CoreDNS"]
  coredns -->|"normal Service"| vip["Service ClusterIP\n(load-balanced)"]
  coredns -->|"headless Service"| p0["web-0 IP"]
  coredns -->|"headless Service"| p1["web-1 IP"]
  coredns -->|"headless Service"| p2["web-2 IP"]
DNS query ของ Pod ที่ CoreDNS resolve ให้ ไปเป็น Service ClusterIP หรือ IP ของแต่ละ Pod สำหรับ headless Service
รูปแบบ DNS name เต็มที่ Kubernetes ตั้งให้ Service อัตโนมัติคืออะไร
ทำไม StatefulSet ถึงต้องใช้ headless Service เพื่อ DNS
CoreDNS มีบทบาทอะไรใน cluster
headless Service (clusterIP: None) คืนอะไรตอนถูก query ด้วย DNS