使用服務來公開您的應用程式

瞭解 Kubernetes 中的服務。瞭解標籤和選擇器如何與服務相關。將應用程式公開在 Kubernetes 叢集外部。

目標

  • 瞭解 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"

我們從伺服器收到回應。服務已公開。

步驟 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。

準備就緒後,請繼續前往執行應用程式的多個執行個體