在前面幾天,我們知道 Deployment 可以隨時建立、刪除、擴縮容或滾動更新 Pod。但這衍生出一個嚴重的網路通訊問題:
10.244.0.15),但只要 Pod 重啟或更新,IP 就會立刻改變。如果讓應用程式直接寫死 Pod IP,整個系統會變得極度脆弱。
這正是 Service 出現的原因:Service 為一群功能相同的 Pod 提供了一個「單一、固定、永久不變的入口(IP 與 DNS 名稱)」,並自動在後端的 Pod 之間進行負載平衡。
答案依然是我們在 Day 08 學到的 Label Selector(標籤選擇器):
spec.selector 去尋找帶有特定標籤的 Pod。Kubernetes 的 Service 有多種型態(Type),最基本也是預設的型態就是 ClusterIP:
nginx-service.yaml我們為前兩天建立的 nginx-deployment(標籤為 app: nginx-app)配置一個 ClusterIP Service:
apiVersion: v1
kind: Service
metadata:
name: nginx-service
spec:
type: ClusterIP
selector:
app: nginx-app
ports:
- protocol: TCP
port: 80 # Service 對外暴露的 Port
targetPort: 80 # 轉發到後端 Pod 容器的 Port
kubectl apply -f nginx-service.yaml
查看已建立的 Service:
kubectl get svc nginx-service
輸出預期:
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
nginx-service ClusterIP 10.105.120.45 <none> 80/TCP 10s
你會拿到一個固定的 CLUSTER-IP,只要 Service 不刪除,這個 IP 永遠不會改變。
檢查背後的 Endpoints(確認是否有成功抓到 3 個 Nginx Pod 的 IP):
kubectl get endpoints nginx-service
Kubernetes 內建 CoreDNS 服務,在集群內部的任何 Pod 都可以直接用 Service 名稱 作為網域名稱進行訪問!
我們臨時起一個帶有 curl 工具的測試 Pod 來驗證:
kubectl run test-client --image=curlimages/curl --rm -it -- restart=Never -- sh
進入測試容器後,直接用 Service 名稱發送請求:
# 1. 透過 Service 名稱連線 (K8s 內部自動解析)
curl http://nginx-service
# 2. 透過完整 FQDN (Fully Qualified Domain Name) 連線
curl [http://nginx-service.default.svc.cluster.local](http://nginx-service.default.svc.cluster.local)
若成功輸出 Nginx 的 HTML 歡迎頁面,代表內部 Service 發現與負載平衡機制完全運作正常!
(測試完成後輸入 exit 退出並自動銷毀測試 Pod)
今天我們搞懂了 Service 的核心價值:
但 ClusterIP 只能在集群內部存取,如果我們要讓外面的使用者或本機瀏覽器真正連進我們的網站,該怎麼辦?
明天 Day 11,我們將把服務對外開放:「對外開門營運:Service NodePort 與 LoadBalancer 存取測試」!