在前一篇(Day11),我們學習了 Kubernetes Service 的三種基礎型態:ClusterIP、NodePort、LoadBalancer,並了解它們如何將服務暴露給集群內外的使用者。
但是,即使有了 Service,我們仍然需要解決一個問題:Pod 與 Pod 之間如何知道要存取哪個服務?
因為 Pod 的 IP 是動態的(重啟或水平擴展時可能會變動),直接依賴 Pod IP 顯然不可行。
這時候,就需要 Service Discovery(服務發現) 與 DNS 來幫助我們找到服務。
今天,我們將深入理解 Kubernetes 內建的 DNS 與 Service Discovery 機制,並透過實作來驗證它們的運作方式。
為什麼需要 Service Discovery?
在微服務架構中,服務之間經常需要互相存取。問題在於:
Kubernetes 的解法:
這樣一來,無論 Pod IP 如何變動,服務之間都能透過名稱找到彼此。
CoreDNS
在 Kubernetes 裡,每個 Service 都會自動被分配一個 DNS 名稱,格式如下:
<service-name>.<namespace>.svc.cluster.local
舉例來說:
完整的 DNS 會是:
nginx-service.default.svc.cluster.local
在相同 namespace 下,可以直接簡寫為: nginx-service
當 Pod A 要呼叫 Pod B 的 Service 時,流程如下:
my-service
解析為 my-service.default.svc.cluster.local
。💡 這整個過程讓開發者與應用程式不用關心 Pod IP,只需要記住 Service 名稱即可。
Headless Service
範例 DNS 名稱:
zk-0.zookeeper.default.svc.cluster.local
SRV 記錄
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。
kubectl get pods -n kube-system -l k8s-app=kube-dns
<service>.<namespace>.svc.cluster.local
)。在理解 Service Discovery 之後,下一篇(Day13)我們將走出集群,學習 Ingress 與 Ingress Controller,了解如何將 HTTP/HTTPS 流量導入 Kubernetes 集群中的服務。