iT邦幫忙

2025 iThome 鐵人賽

DAY 9
0
DevOps

新創視角下的 DevOps × AI 探索系列 第 12

Day12: DNS 與 Service Discovery:如何在 K8s 內部找到服務

  • 分享至 

  • xImage
  •  

前言

在前一篇(Day11),我們學習了 Kubernetes Service 的三種基礎型態:ClusterIP、NodePort、LoadBalancer,並了解它們如何將服務暴露給集群內外的使用者。
但是,即使有了 Service,我們仍然需要解決一個問題:Pod 與 Pod 之間如何知道要存取哪個服務?

因為 Pod 的 IP 是動態的(重啟或水平擴展時可能會變動),直接依賴 Pod IP 顯然不可行。
這時候,就需要 Service Discovery(服務發現) 與 DNS 來幫助我們找到服務。

今天,我們將深入理解 Kubernetes 內建的 DNS 與 Service Discovery 機制,並透過實作來驗證它們的運作方式。

為什麼需要 Service Discovery?

在微服務架構中,服務之間經常需要互相存取。問題在於:

  • Pod IP 並不是固定的,Pod scale in/out 或重啟時,IP 會改變。
  • 服務之間的存取需要穩定的入口,而不是直接記住 Pod IP。

Kubernetes 的解法:

  1. 用 Service 建立穩定的虛擬 IP(ClusterIP)。
  2. 用 CoreDNS 提供名稱解析(例如 my-service.default.svc.cluster.local)。

這樣一來,無論 Pod IP 如何變動,服務之間都能透過名稱找到彼此。

Kubernetes 內建的 DNS 機制

CoreDNS

  • Kubernetes 預設會部署一個 CoreDNS Deployment。
  • 當 Pod 透過名稱呼叫服務時,CoreDNS 會把這個名稱轉換成對應的 Service ClusterIP,再由 kube-proxy 將流量導向後端的 Pod。

DNS 命名規則

在 Kubernetes 裡,每個 Service 都會自動被分配一個 DNS 名稱,格式如下:

<service-name>.<namespace>.svc.cluster.local

舉例來說:

  • Service 名稱:nginx-service
  • Namespace:default

完整的 DNS 會是:

nginx-service.default.svc.cluster.local

在相同 namespace 下,可以直接簡寫為: nginx-service

Kubernetes 的 Service Discovery 流程

當 Pod A 要呼叫 Pod B 的 Service 時,流程如下:

  1. Pod A 發送請求到 http://my-service:8080
  2. CoreDNS 將 my-service 解析為 my-service.default.svc.cluster.local
  3. CoreDNS 回傳 ClusterIP。
  4. kube-proxy 接收流量,並轉發到 Service 背後的 Pod(Endpoint)。

💡 這整個過程讓開發者與應用程式不用關心 Pod IP,只需要記住 Service 名稱即可。

進階議題:Headless Service 與 SRV 記錄

Headless Service

  • 如果將 Service 的 clusterIP 設為 None,就會成為 Headless Service。
  • DNS 會直接回傳所有 Pod 的 IP,而不是 Service 的 ClusterIP。
  • 常見於 StatefulSet、資料庫(例如 ZooKeeper、Cassandra),因為需要 Pod-to-Pod 的直接連線。

範例 DNS 名稱:

zk-0.zookeeper.default.svc.cluster.local

SRV 記錄

  • 除了 A 記錄(IP 位址),Kubernetes 也會提供 SRV 記錄。
  • 可以查詢服務的 port 與 protocol,適用於 gRPC、資料庫等需要精準端口的應用。

實作範例:驗證 Kubernetes DNS 與 Service Discovery

1. 建立 Deployment 與 Service
建立一個簡單的 Nginx Deployment 與 Service:

apiVersion: apps/v1
kind: Deployment
metadata:
  name: nginx-deployment
spec:
  replicas: 2
  selector:
    matchLabels:
      app: nginx
  template:
    metadata:
      labels:
        app: nginx
    spec:
      containers:
      - name: nginx
        image: nginx:alpine
        ports:
        - containerPort: 80
---
apiVersion: v1
kind: Service
metadata:
  name: nginx-service
spec:
  selector:
    app: nginx
  ports:
  - port: 80
    targetPort: 80

套用配置:

kubectl apply -f nginx.yaml

2. 建立測試 Pod
我們用 busybox 來測試 DNS 與連線:

kubectl run busybox --rm -it --image=busybox:1.28 sh

3. 測試 DNS 解析
在 busybox 內執行:

nslookup nginx-service
nslookup nginx-service.default.svc.cluster.local

輸出結果應該會回傳 ClusterIP,例如:

Name:   nginx-service.default.svc.cluster.local
Address: 10.96.123.45

4. 測試存取 Service

wget -qO- http://nginx-service

若成功,會看到 Nginx 預設的首頁 HTML。

5. 測試 Headless Service

將 Service 修改如下:

spec:
  clusterIP: None

再次執行 nslookup nginx-service,這次會看到 多個 Pod IP,而不是單一 ClusterIP。

常見問題與排查

  1. DNS 無法解析 → 檢查 CoreDNS Pod 是否正常:
kubectl get pods -n kube-system -l k8s-app=kube-dns
  1. Service 名稱打錯或 namespace 錯誤 → 確認使用完整名稱(<service>.<namespace>.svc.cluster.local)。
  2. Headless Service 查不到 Pod IP → 確認有沒有符合 selector 的 Pod 存在。

結論

  • Kubernetes 的 DNS + Service Discovery 機制,解決了 Pod IP 動態變動的問題,確保服務之間能穩定地互相存取。
  • Service 提供穩定入口,CoreDNS 負責名稱解析,讓微服務能彼此溝通。
  • Headless Service 與 SRV 記錄,則提供更進階的需求支援(如資料庫、StatefulSet)。

在理解 Service Discovery 之後,下一篇(Day13)我們將走出集群,學習 Ingress 與 Ingress Controller,了解如何將 HTTP/HTTPS 流量導入 Kubernetes 集群中的服務。


上一篇
Day11: 網路與服務 - Service 基礎:ClusterIP、NodePort、LoadBalancer
下一篇
Day13: Ingress 與 Ingress Controller:管理 HTTP/HTTPS 流量
系列文
新創視角下的 DevOps × AI 探索15
圖片
  熱門推薦
圖片
{{ item.channelVendor }} | {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言