返回文章列表

Kubernetes Service Pod 內部溝通機制

本文探討 Kubernetes 中 Service 的型別與應用,特別是 ClusterIP Service 如何 facilitating Pod 內部溝通,並涵蓋 Headless Service 和 LoadBalancer Service 的組態與使用。文章也解析了 Service 的 YAML

容器技術 網路管理

Kubernetes 提供了 Service 資源,作為 Pod 的抽象層,簡化了應用程式之間的網路連線。ClusterIP Service 賦予 Pod 一個穩定的內部 IP,讓其他 Pod 可以透過這個 IP 進行存取,不受 Pod 重啟或擴縮減影響。選擇 ClusterIP Service 還是 NodePort Service 取決於應用程式是否需要外部連線,ClusterIP Service 更適用於叢集內部通訊。它透過 kube-proxy 在每個節點上建立虛擬 IP,實作 Pod 間的負載平衡。透過 kubectl expose 指令,可以輕鬆建立 ClusterIP Service,並指定目標 Deployment 和埠。除了指令式建立方式,也可以使用 YAML 檔案定義 Service,提供更彈性的組態選項。Headless Service 則是一種特殊的 ClusterIP Service,它不提供負載平衡和 ClusterIP,而是直接傳回匹配 Pod 的 DNS 名稱。LoadBalancer Service 則整合雲端供應商的負載平衡器,提供外部連線能力。Kubernetes 也提供了探針機制,例如 ReadinessProbe,用於檢查 Pod 的健康狀態,確保 Service 只將流量導向可用的 Pod。ExternalName Service 則可以將 Service 對映到外部 DNS 名稱,方便叢集內應用程式存取外部資源。

使用 ClusterIP Service 進行 Pod 內部溝通

在 Kubernetes 中,ClusterIP Service 是一種用於在叢集內部暴露 Pod 的服務型別。它提供了一個靜態的 IP 地址和 DNS 名稱,讓其他 Pod 可以透過它來存取特定的 Pod。

為什麼需要 ClusterIP Service?

ClusterIP Service 與 NodePort Service 類別似,但它們有一個重要的區別:NodePort Service 是用於將 Pod 暴露給外部世界,而 ClusterIP Service 則是用於將 Pod 暴露給叢集內部的其他 Pod。

ClusterIP Service 提供了一個靜態的介面,讓不同的 Pod 可以透過它來相互通訊。這個介面不會隨著 Pod 的重新啟動或刪除而改變,從而確保了叢集內部通訊的穩定性。

如何選擇 NodePort 或 ClusterIP Service?

選擇使用 NodePort 或 ClusterIP Service 取決於您的應用程式需求。如果您的應用程式需要被外部存取,那麼您需要使用 NodePort Service(或其他型別的 Service)。如果您的應用程式只需要被叢集內部的其他 Pod 存取,那麼您需要使用 ClusterIP Service。

ClusterIP Service 適合用於無狀態的應用程式,可以根據需要進行擴充套件、銷毀和重新建立。因為 ClusterIP Service 提供了一個靜態的入口點,可以存取一組 Pod,而不受 worker node 上的埠限制。

ClusterIP Service 的工作原理

ClusterIP Service 使用由 kube-proxy 在每個 Node 上管理的內部虛擬 IP 地址來暴露 Pod。這意味著 Service 只可以在叢集內部存取。

以下是 ClusterIP Service 的工作原理圖:

@startuml
skinparam backgroundColor #FEFEFE
skinparam defaultTextAlignment center
skinparam rectangleBackgroundColor #F5F5F5
skinparam rectangleBorderColor #333333
skinparam arrowColor #333333

title ClusterIP Service 的工作原理

rectangle "存取 ClusterIP" as node1
rectangle "負載平衡" as node2

node1 --> node2

@enduml

圖示解說:

此圖示展示了 Client Pod 如何透過 ClusterIP Service 存取後端的多個 Pod。ClusterIP Service 提供了負載平衡的功能,將請求分配到不同的 Pod 上。

建立 ClusterIP Service

要建立 ClusterIP Service,您可以使用以下命令:

$ kubectl expose deployment whoami --type=ClusterIP --port=80

這個命令會建立一個名為 whoami 的 ClusterIP Service,將 whoami Deployment 中的 Pod 暴露在埠 80 上。

程式碼解析:

$ kubectl expose deployment whoami --type=ClusterIP --port=80
  • kubectl expose 命令用於建立一個新的 Service。
  • deployment whoami 指定了要暴露的 Deployment 名稱。
  • --type=ClusterIP 指定了 Service 的型別為 ClusterIP。
  • --port=80 指定了 Service 的埠號為 80。

使用 ClusterIP Service 暴露 Pod

在 Kubernetes 中,ClusterIP Service 是一種用於在叢集內部暴露 Pod 的服務型別。它允許 Pod 之間的通訊,並提供負載平衡功能。本章節將探討 ClusterIP Service 的組態、使用方法以及其工作原理。

ClusterIP Service 的工作原理

ClusterIP Service 會為一組 Pod 分配一個虛擬 IP 地址,並將請求從該 IP 地址轉發到相應的 Pod。如下圖所示,ClusterIP Service 組態為將請求從其 IP 地址的 TCP 連線埠 8080 對應到容器的 TCP 連線埠 80。

與 NodePort Service 不同,ClusterIP Service 不會佔用工作節點的連線埠,因此無法從叢集外部直接存取它。然而,這並不妨礙同時使用兩種型別的 Service 來暴露相同的 Pod 組。例如,如果應用程式需要對外公開存取,同時也需要對叢集內的其他 Pod 私下暴露,可以建立兩個 Service:一個 NodePort Service 和一個 ClusterIP Service。

使用指令列出 ClusterIP Service

列出 ClusterIP Service 的指令與列出 NodePort Service 的指令相同:

$ kubectl get svc

該指令會列出所有 Service,包括其型別。

建立 ClusterIP Service

建立 ClusterIP Service 有多種方法,包括使用 --expose 引數(指令式方式)和使用 YAML 清單檔案(宣告式方式)。

使用指令式方式建立 ClusterIP Service

使用 --expose 引數可以快速建立一個 ClusterIP Service。以下範例建立了一個名為 nginx-clusterip 的 Pod 和一個 ClusterIP Service:

$ kubectl run nginx-clusterip --image nginx --expose=true --port=80
service/nginx-clusterip created
pod/nginx-clusterip created

描述 ClusterIP Service

可以使用 kubectl describe 指令來描述 ClusterIP Service:

$ kubectl describe svc/nginx-clusterip
Name: nginx-clusterip
Namespace: default
Labels: <none>
Annotations: <none>
Selector: run=nginx-clusterip
Type: ClusterIP
IP Family Policy: SingleStack
IP Families: IPv4
IP: 10.101.229.225
IPs: 10.101.229.225
Port: <unset> 80/TCP
TargetPort: 80/TCP
Endpoints: 10.244.0.10:80
Session Affinity: None
Events: <none>

輸出結果顯示了 Service 的選擇器(Selector),它與 Pod 的標籤(Label)相符,從而建立了 Service 與 Pod 之間的通訊。

驗證 ClusterIP Service

可以使用 kubectl exec 指令在另一個 Pod 中存取 ClusterIP Service:

$ kubectl exec k8sutils -- curl nginx-clusterip.default.svc.cluster.local

該指令會向 ClusterIP Service 傳送請求,並將請求轉發到後端的 Pod。

使用宣告式方式建立 ClusterIP Service

除了使用指令式方式外,還可以使用 YAML 清單檔案來建立 ClusterIP Service。這種方式提供了更大的彈性,可以根據需要自定義 Service 的組態。

建立 YAML 清單檔案

以下是一個範例 YAML 清單檔案,用於建立 ClusterIP Service:

apiVersion: v1
kind: Service
metadata:
  name: nginx-clusterip
spec:
  selector:
    run: nginx-clusterip
  ports:
  - name: http
    port: 80
    targetPort: 80
  type: ClusterIP

套用 YAML 清單檔案

可以使用 kubectl apply 指令來套用 YAML 清單檔案:

$ kubectl apply -f service.yaml

該指令會根據 YAML 清單檔案的定義建立 ClusterIP Service。

此圖示顯示了 ClusterIP Service 的基本架構和工作原理。
@startuml
skinparam backgroundColor #FEFEFE
skinparam defaultTextAlignment center
skinparam rectangleBackgroundColor #F5F5F5
skinparam rectangleBorderColor #333333
skinparam arrowColor #333333

title 套用 YAML 清單檔案

rectangle "請求" as node1
rectangle "負載平衡" as node2

node1 --> node2

@enduml

該圖示闡述了 Client 如何透過 ClusterIP Service 存取後端的多個 Pod,以及 ClusterIP Service 如何進行負載平衡。

程式碼範例解說:

$ kubectl run nginx-clusterip --image nginx --expose=true --port=80

內容解密:

  1. kubectl run:用於建立一個新的 Pod。
  2. nginx-clusterip:指定 Pod 的名稱。
  3. --image nginx:指定使用的 Docker 映象。
  4. --expose=true:表示要為該 Pod 建立一個 Service。
  5. --port=80:指定 Service 的連線埠。

此指令綜合了建立 Pod 和建立 Service 的操作,簡化了佈署流程。

$ kubectl describe svc/nginx-clusterip

內容解密:

  1. kubectl describe:用於取得某個 Kubernetes 資源的詳細資訊。
  2. svc/nginx-clusterip:指定要查詢的 Service 名稱。

輸出結果包含了 Service 的基本資訊、選擇器、連線埠組態等,有助於瞭解 Service 的執行狀態和組態細節。

使用Service暴露Pod

在前面的章節中,我們已經瞭解瞭如何使用ClusterIP型別的Service來暴露Pod。這裡,我們將進一步探討不同型別的Service,包括headless Service和LoadBalancer Service。

ClusterIP Service的YAML組態

以下是一個用於建立ClusterIP Service的YAML檔案範例:

# clusterip-service.yaml
apiVersion: v1
kind: Service
metadata:
  name: nginx-clusterip
spec:
  type: ClusterIP
  ports:
  - port: 80
    protocol: TCP
    targetPort: 80
  selector:
    run: nginx-clusterip

內容解密:

  • apiVersionkind 指定了Kubernetes資源的版本和型別。
  • metadata.name 定義了Service的名稱。
  • spec.type 設定為ClusterIP,表示這是一個ClusterIP Service。
  • ports.port 是Service暴露的埠。
  • ports.targetPort 是Pod中容器所監聽的埠,Service會將流量轉發到這個埠。
  • selector 用於匹配具有特定標籤的Pod。

理解Headless Service

Headless Service是根據ClusterIP Service的一種特殊組態,它透過將.spec.clusterIP設定為None來實作。下面是一個範例:

# clusterip-headless.yaml
apiVersion: v1
kind: Service
metadata:
  name: nginx-clusterip-headless
spec:
  clusterIP: None
  type: ClusterIP
  ports:
  - port: 80
    protocol: TCP
    targetPort: 80
  selector:
    run: nginx-clusterip

內容解密:

  • clusterIP設定為None,表示這是一個headless Service。
  • Headless Service不具備負載平衡功能,也沒有預先分配的ClusterIP。
  • 當查詢headless Service的DNS名稱時,會傳回匹配標籤的Pod的DNS名稱。

LoadBalancer Service簡介

LoadBalancer Service是一種依賴於雲平台提供的外部負載平衡器的Service型別。以下是相關的關鍵點:

  • 當Service的型別被設定為LoadBalancer時,雲平台會為其組態一個負載平衡器。
  • 負載平衡器的建立是非同步進行的,其細節會在Service的.status.loadBalancer欄位中提供。
  • 可以透過.spec.loadBalancerIP指定負載平衡器的IP地址,如果未指定,則會使用臨時IP地址。
apiVersion: v1
kind: Service
metadata:
  name: example-loadbalancer
spec:
  type: LoadBalancer
  loadBalancerIP: "指定的IP地址"
  ports:
  - port: 80
    targetPort: 80
  selector:
    app: example-app

內容解密:

  • .spec.loadBalancerClass允許使用非雲平台預設提供的負載平衡器實作。
  • .spec.loadBalancerClass被設定時,預設的負載平衡器實作將忽略此Service。

Kubernetes 中的 Service 型別與探針機制

在 Kubernetes 中,Service 是用來暴露 Pod 並提供網路存取的抽象資源。根據不同的使用場景,Kubernetes 提供了多種 Service 型別,包括 LoadBalancer、ExternalName 等。同時,為了確保 Service 的可用性,Kubernetes 提供了探針(Probes)機制來檢查 Pod 的健康狀態和準備情況。

LoadBalancer Service 型別

LoadBalancer 是一種 Service 型別,它允許將流量分配到後端的 Pod 上。支援 LoadBalancer 的雲端供應商包括 AWS、GCP、Azure 和 OpenStack 等。然而,使用 LoadBalancer Service 時需要注意以下幾點:

  • LoadBalancer 的組態通常由雲端供應商控制,Kubernetes 對其組態的控制權有限。
  • LoadBalancer 可能會產生額外的費用,費用取決於供應商和流量大小。
  • 由於 LoadBalancer 是由雲端供應商實作的,因此需要了解其工作原理和限制。

ExternalName Service 型別

ExternalName Service 是一種特殊的 Service 型別,它允許將 Kubernetes 中的 Service 對應到外部的 DNS 名稱,而不是對應到叢集內的 Pod。這使得叢集內的應用程式可以輕鬆存取外部資源,而無需知道其 IP 位址或內部細節。

以下是一個 ExternalName Service 的 YAML 定義範例:

# externalname-service.yaml
apiVersion: v1
kind: Service
metadata:
  name: mysql-db
  namespace: prod
spec:
  type: ExternalName
  externalName: app-db.database.example.com

ExternalName Service 的優點包括:

  • 簡化組態:應用程式只需知道 Service 名稱,而無需知道外部資源的詳細資訊。
  • 彈性資源管理:如果將外部資源遷移到叢集內,可以簡單地更新 Service 而不影回應用程式。
  • 增強安全性:敏感資訊(如 IP 位址)可以隱藏在叢集內,提高安全性。

使用探針確保 Service 可用性

當建立一個 Service 時,Kubernetes 不會自動檢查應用程式的健康狀態。為了確保 Service 的可用性,Kubernetes 提供了探針機制,包括 LivenessProbe、ReadinessProbe 和 StartupProbe。

ReadinessProbe

ReadinessProbe 用於檢查 Pod 是否準備好接收流量。當 Pod 組態了 ReadinessProbe 時,它可以向控制平面傳送訊號,表示它尚未準備好接收流量。在此期間,Service 不會將流量轉發到該 Pod。

以下是如何在 Pod 的 YAML 清單中組態 ReadinessProbe:

apiVersion: v1
kind: Pod
metadata:
  name: example-pod
spec:
  containers:
  - name: example-container
    readinessProbe:
      httpGet:
        path: /healthcheck
        port: 80
      initialDelaySeconds: 5
      periodSeconds: 10

在這個範例中,ReadinessProbe 使用 HTTP GET 請求檢查容器的健康狀態。如果容器尚未準備好,Service 將不會將流量轉發到該 Pod。