目標
- 瞭解 Kubernetes 中的服務
- 瞭解標籤和選擇器如何與服務相關
- 使用服務將應用程式公開在 Kubernetes 叢集外部
Kubernetes 服務總覽
Kubernetes Pod 是有壽命的。Pod 有生命週期。當工作節點故障時,在該節點上執行的 Pod 也會遺失。ReplicaSet 隨後可能會透過建立新的 Pod,動態地將叢集驅動回所需的狀態,以保持您的應用程式執行。再舉一個範例,考慮一個具有 3 個副本的映像檔處理後端。這些副本是可交換的;前端系統不應關心後端副本,甚至不應關心 Pod 是否遺失和重新建立。也就是說,Kubernetes 叢集中的每個 Pod 都有一個唯一的 IP 位址,即使是同一節點上的 Pod 也是如此,因此需要有一種自動協調 Pod 之間變更的方式,以確保您的應用程式繼續運作。
Kubernetes 中的服務是一種抽象概念,它定義了一組邏輯 Pod 和存取它們的策略。服務實現了相依 Pod 之間的鬆散耦合。服務是使用 YAML 或 JSON 定義的,就像所有 Kubernetes 物件資訊清單一樣。服務所針對的 Pod 集通常由標籤選擇器決定(請參閱下文,瞭解為何您可能需要不包含 selector
在規格中的服務)。
雖然每個 Pod 都有唯一的 IP 位址,但如果沒有服務,這些 IP 位址不會公開在叢集外部。服務允許您的應用程式接收流量。可以透過在spec服務的規格中指定 type
以不同的方式公開服務
- ClusterIP (預設) - 在叢集中的內部 IP 上公開服務。此類型使服務只能從叢集內部存取。
- NodePort - 使用 NAT 在叢集中每個選定節點的相同埠上公開服務。使服務可從叢集外部使用
<NodeIP>:<NodePort>
存取。是 ClusterIP 的超集。 - LoadBalancer - 在目前的雲端 (如果支援) 中建立外部負載平衡器,並將固定的外部 IP 指派給服務。是 NodePort 的超集。
- ExternalName - 透過傳回具有其值的
CNAME
記錄,將服務對應到externalName
欄位的內容 (例如foo.bar.example.com
)。未設定任何類型的代理。此類型需要 v1.7 或更高版本的kube-dns
,或 CoreDNS 版本 0.0.8 或更高版本。
有關不同服務類型的更多資訊,請參閱使用來源 IP教學課程。另請參閱使用服務連接應用程式。
此外,請注意,有些服務的使用案例涉及未在規格中定義 selector
。未建立 selector
的服務也不會建立對應的端點物件。這允許使用者手動將服務對應到特定端點。可能沒有選擇器的另一個原因是您嚴格使用 type: ExternalName
。
摘要
- 將 Pod 公開給外部流量
- 跨多個 Pod 的負載平衡流量
- 使用標籤
Kubernetes 服務是一個抽象層,它定義了一組邏輯 Pod,並為這些 Pod 啟用外部流量公開、負載平衡和服務探索。
服務和標籤
Service 會將流量路由到一組 Pod。服務是一種抽象化概念,可讓 Pod 在 Kubernetes 中終止和複製,而不會影響您的應用程式。相依 Pod 之間的探索和路由 (例如應用程式中的前端和後端組件) 由 Kubernetes 服務處理。
服務使用標籤和選擇器來比對一組 Pod,這是一種分組基本元素,允許對 Kubernetes 中的物件執行邏輯運算。標籤是附加到物件的鍵/值對,可用於多種方式
- 指定用於開發、測試和生產的物件
- 嵌入版本標籤
- 使用標籤對物件進行分類
標籤可以在建立物件時或稍後附加到物件。它們可以隨時修改。現在讓我們使用服務公開我們的應用程式並套用一些標籤。
步驟 1:建立新的服務
讓我們驗證我們的應用程式是否正在執行。我們將使用 kubectl get
命令並尋找現有的 Pod
kubectl get pods
如果沒有 Pod 正在執行,則表示先前教學課程中的物件已被清理。在這種情況下,請返回並從使用 kubectl 建立 Deployment 教學課程重新建立部署。請等待幾秒鐘,然後再次列出 Pod。當您看到一個 Pod 正在執行時,即可繼續。
接下來,讓我們列出叢集中目前的服務
kubectl get services
我們有一個名為kubernetes的服務,它在 minikube 啟動叢集時預設建立。若要建立新服務並將其公開到外部流量,我們將使用 `expose` 命令,並以 NodePort 作為參數。
kubectl expose deployment/kubernetes-bootcamp --type="NodePort" --port 8080
讓我們再次執行 get services
子命令
kubectl get services
我們現在有一個名為 kubernetes-bootcamp 的執行中服務。在這裡我們看到該服務收到了一個獨特的叢集 IP、一個內部埠和一個外部 IP (Node 的 IP)。
若要找出哪個埠在外部開啟 (對於type: NodePort服務),我們將執行 describe service
子命令
kubectl describe services/kubernetes-bootcamp
建立一個名為NODE_PORT的環境變數,其值為指派的 Node 埠
export NODE_PORT="$(kubectl get services/kubernetes-bootcamp -o go-template='{{(index .spec.ports 0).nodePort}}')"
echo "NODE_PORT=$NODE_PORT"
現在我們可以測試應用程式是否已公開在叢集外部,方法是使用 curl
、Node 的 IP 位址和外部公開的埠
curl http://"$(minikube ip):$NODE_PORT"
注意
如果您使用 Docker Desktop 作為容器驅動程式執行 minikube,則需要 minikube tunnel。這是因為 Docker Desktop 內的容器與您的主機電腦隔離。
在單獨的終端機視窗中,執行minikube service kubernetes-bootcamp --url
輸出看起來像這樣
http://127.0.0.1:51082
! Because you are using a Docker driver on darwin, the terminal needs to be open to run it.
然後使用給定的 URL 來存取應用程式curl 127.0.0.1:51082
我們從伺服器收到回應。服務已公開。
步驟 2:使用標籤
Deployment 自動為我們的 Pod 建立了一個標籤。使用 describe deployment
子命令,您可以查看該標籤的名稱 (鍵)
kubectl describe deployment
讓我們使用此標籤來查詢我們的 Pod 列表。我們將使用 kubectl get pods
命令,並帶有-l作為參數,後跟標籤值
kubectl get pods -l app=kubernetes-bootcamp
您可以執行相同的操作來列出現有的服務
kubectl get services -l app=kubernetes-bootcamp
取得 Pod 的名稱並將其儲存在POD_NAME環境變數中
export POD_NAME="$(kubectl get pods -o go-template --template '{{range .items}}{{.metadata.name}}{{"\n"}}{{end}}')"
echo "Name of the Pod: $POD_NAME"
若要套用新標籤,我們使用 label
子命令,後跟物件類型、物件名稱和新標籤
kubectl label pods "$POD_NAME" version=v1
這會將新標籤套用到我們的 Pod (我們將應用程式版本固定到 Pod),並且我們可以使用 describe pod 命令來檢查它
kubectl describe pods "$POD_NAME"
我們在這裡看到標籤現在已附加到我們的 Pod。而且我們現在可以使用新標籤查詢 Pod 列表
kubectl get pods -l version=v1
我們看到了 Pod。
步驟 3:刪除服務
若要刪除服務,您可以使用 delete service
子命令。標籤也可以在這裡使用
kubectl delete service -l app=kubernetes-bootcamp
確認服務已消失
kubectl get services
這確認我們的服務已移除。若要確認路由不再公開,您可以curl先前公開的 IP 和埠
curl http://"$(minikube ip):$NODE_PORT"
這證明應用程式已無法從叢集外部訪問。您可以透過以下命令確認應用程式仍在執行curl從 Pod 內部
kubectl exec -ti $POD_NAME -- curl https://127.0.0.1:8080
我們在這裡看到應用程式已啟動。這是因為 Deployment 正在管理應用程式。若要關閉應用程式,您也需要刪除 Deployment。
準備就緒後,請繼續前往執行應用程式的多個執行個體。