Service

本頁說明何謂 Kubernetes Service,以及它們在 Google Kubernetes Engine 中的用途。如要瞭解如何建立服務,請參閱使用服務公開應用程式

什麼是 Service?

Service 的概念,就是將一組 Pod 端點聚集成單一資源,而您可以設定利用多種方式來存取這組 Pod 端點。根據預設,您會有個穩定的叢集 IP 位址,能讓叢集中的用戶端拿來聯絡 Service 中的 Pod。用戶端會將要求傳送至穩定的 IP 位址,然後系統會把該要求轉送至 Service 中的某個 Pod。

Service 會利用選取器辨識自己的成員 Pod。如要讓 Pod 成為 Service 的成員,該 Pod 必須要有在選取器中指定的所有標籤。標籤就是附加在物件上的任意鍵/值組合。

以下的 Service 資訊清單擁有會指定兩個標籤的選取器。selector 欄位表示,只要是同時擁有 app: metrics 標籤和 department:engineering 標籤的 Pod,就是這個 Service 的成員。

apiVersion: v1
kind: Service
metadata:
  name: my-service
spec:
  selector:
    app: metrics
    department: engineering
  ports:
  ...

為什麼要使用 Service?

在 Kubernetes 叢集中,每個 Pod 都有內部 IP 位址。但部署中的 Pod 會變動,其 IP 位址也會變更。因此,直接使用 Pod IP 位址並不合理。透過服務,您可獲得一個在服務生命週期內持續存在的穩定 IP 位址,甚至在成員 Pod 的 IP 位址變更時仍不會改變。

服務也能提供負載平衡。用戶端呼叫單一穩定的 IP 位址,而用戶端的要求會平均分配到屬於服務成員的 Pod 之間。

服務類型

Service 有五種類型:

  • ClusterIP (預設):內部用戶端會將要求傳送至穩定的內部 IP 位址。

  • NodePort:用戶端會根據 Service 所指定的一或多個 nodePort 值,將要求傳送至某個節點的 IP 位址。

  • LoadBalancer:用戶端會將要求傳送至某個網路負載平衡器的 IP 位址。

  • ExternalName:內部用戶端會把 Service 的 DNS 名稱當做外部 DNS 名稱的別名。

  • 無介面:如果您想要使用一組 Pod,但不需要穩定的 IP 位址,即可使用無介面 Service

NodePort 類型是 ClusterIP 類型的延伸,因此 NodePort 類型的 Service 擁有 1 個叢集 IP 位址。

LoadBalancer 類型是 NodePort 類型的延伸,因此 LoadBalancer 類型的 Service 擁有 1 個叢集 IP 位址,以及一或多個nodePort 值。

ClusterIP 類型的 Service

當您建立 ClusterIP 類型的 Service 時,Kubernetes 會建立可從叢集中的節點存取的穩定 IP 位址。

以下是 ClusterIP 類型 Service 的資訊清單:

apiVersion: v1
kind: Service
metadata:
  name: my-cip-service
spec:
  selector:
    app: metrics
    department: sales
  type: ClusterIP
  ports:
  - protocol: TCP
    port: 80
    targetPort: 8080

您可以使用 kubectl apply -f [MANIFEST_FILE]建立 Service。當您建立 Service 之後,即可使用 kubectl get service 查看穩定的 IP 位址:

NAME             TYPE        CLUSTER-IP      EXTERNAL-IP   PORT(S)
my-cip-service   ClusterIP   10.11.247.213   none          80/TCP

叢集中的用戶端會利用叢集 IP 位址,以及在 Service 資訊清單的 port 欄位中指定的 TCP 通訊埠來呼叫 Service。系統會把要求轉送至在 targetPort 欄位中指定的 TCP 通訊埠上的某個成員 Pod。因此,在上述範例中,用戶端會呼叫位於 10.11.247.213 的 TCP 通訊埠 80 上的 Service。要求會轉送至 TCP 通訊埠 8080 上的其中一個成員 Pod。請注意,成員 Pod 必須有監聽 TCP 通訊埠 8080 的容器。如果沒有任何監聽通訊埠 8080 的容器,用戶端會看到類似「無法連接」或「無法連上這個網站」的訊息。

NodePort 類型的 Service

當您建立 NodePort 類型的 Service 時,Kubernetes 會提供您 nodePort 值。然後,您就可以利用任何節點的 IP 位址與該 nodePort 值來存取 Service。

以下是 NodePort 類型 Service 的資訊清單:

apiVersion: v1
kind: Service
metadata:
  name: my-np-service
spec:
  selector:
    app: products
    department: sales
  type: NodePort
  ports:
  - protocol: TCP
    port: 80
    targetPort: 8080

當您建立 Service 之後,即可使用 kubectl get service -o yaml 檢視該 Service 的規格,以及查看 nodePort 值。

spec:
  clusterIP: 10.11.254.114
  externalTrafficPolicy: Cluster
  ports:
  - nodePort: 32675
    port: 80
    protocol: TCP
    targetPort: 8080

外部用戶端會利用某個節點的外部 IP 位址,以及 nodePort 所指定的 TCP 通訊埠來呼叫 Service。系統會把要求轉送至在 targetPort 欄位中指定的 TCP 通訊埠上的某個成員 Pod。

舉例來說,假設某個叢集節點的外部 IP 位址為 203.0.113.2,則在上述範例中,外部用戶端會呼叫位於 203.0.113.2 的 TCP 通訊埠 32675 上的 Service。系統會把要求轉送到 TCP 通訊埠 8080 上的某個成員 Pod,而該成員 Pod 必須擁有會監聽 TCP 通訊埠 8080 的容器。

NodePort Service 類型是 ClusterIP Service 類型的延伸,因此內部用戶端呼叫 Service 的方式有兩種:

  • 使用 clusterIPport
  • 使用節點的內部 IP 位址和 nodePort

對於某些叢集設定,Google Cloud HTTP (S) 負載平衡器會使用 NodePort 類型的 Service。詳情請參閱使用 Ingress 設定 HTTP 負載平衡

請注意,HTTP(S) 負載平衡器是 Proxy 伺服器,它與本文的 LoadBalance 類型的 Service 小節中所述的網路負載平衡器完全不同

LoadBalancer 類型的 Service

當您建立 LoadBalancer 類型的 Service 時,Google Cloud 控制器將會甦醒,並在您的專案中設定網路負載平衡器。該負載平衡器擁有可從專案外部存取的穩定 IP 位址。

請注意,網路負載平衡器並非 Proxy 伺服器。它會轉送封包,但不會變更來源和目的地 IP 位址。

以下是 LoadBalancer 類型 Service 的資訊清單:

apiVersion: v1
kind: Service
metadata:
  name: my-nlb-service
spec:
  selector:
    app: metrics
    department: engineering
  type: LoadBalancer
  ports:
  - port: 80
    targetPort: 8080

當您建立 Service 之後,即可使用 kubectl get service -o yaml 檢視該 Service 的規格,以及查看穩定的外部 IP 位址。

spec:
  clusterIP: 10.11.242.115
  externalTrafficPolicy: Cluster
  ports:
  - nodePort: 32676
    port: 80
    protocol: TCP
    targetPort: 8080
  selector:
    app: metrics
    department: engineering
  sessionAffinity: None
  type: LoadBalancer
  status:
    loadBalancer:
      ingress:
      - ip: 203.0.113.100

在輸出內容中,網路負載平衡器的 IP 位址會顯示在 loadBalancer:ingress: 下方。外部用戶端會利用該負載平衡器的 IP 位址,以及 port 所指定的 TCP 通訊埠來呼叫 Service。系統會把要求轉送至在 targetPort 中指定的 TCP 通訊埠上的某個成員 Pod。因此在上述範例中,用戶端會呼叫位於 203.0.113.100 的 TCP 通訊埠 80 上的 Service。系統會把要求轉送到 TCP 通訊埠 8080 上的某個成員 Pod,而該成員 Pod 必須擁有會監聽 TCP 通訊埠 8080 的容器。

LoadBalancer Service 類型是 NodePort 類型的延伸,而 NodePort 類型是 ClusterIP 類型的延伸。

ExternalName 類型的 Service

ExternalName 類型的 Service 會提供外部 DNS 名稱的內部別名。內部用戶端會使用內部 DNS 名稱來發出要求,而系統會把該要求重新導向至外部名稱。

以下是 ExternalName 類型 Service 的資訊清單:

apiVersion: v1
kind: Service
metadata:
  name: my-xn-service
spec:
  type: ExternalName
  externalName: example.com

當您建立 Service 時,Kubernetes 會建立可讓內部用戶端拿來呼叫 Service 的 DNS 名稱。在上述範例中,DNS 名稱為 my-xn-service.default.svc.cluster.local。當內部用戶端向 my-xn-service.default.svc.cluster.local 發出要求時,系統會把該要求重新導向至 example.com。

ExternalName Service 類型與其他的 Service 類型完全不同。事實上,ExternalName 類型的 Service 並不符合本文一開始為 Service 所下的定義。ExternalName 類型的 Service 並沒有與一組 Pod 相關聯,且它沒有穩定的 IP 位址。相反地,ExternalName 類型的 Service 是內部 DNS 名稱與外部 DNS 名稱的對應關係。

Service 抽象層

Service 是種抽象概念,因為它並不是監聽某個網路介面的程序。而這抽象概念有部分會在叢集節點的 iptables 規則中實現。視 Service 類型而定,這抽象概念的其他部分會由網路負載平衡HTTP(S) 負載平衡來實現。

可任意選擇的 Service 通訊埠

Service 資訊清單中 port 欄位的值可讓您任意選擇,但您無法任意選擇 targetPort 的值。每個成員 Pod 成員都必須要有一個監聽 targetPort 的容器。

以下是 LoadBalancer 類型的 Service,它的 port 值為 50000:

apiVersion: v1
kind: Service
metadata:
  name: my-ap-service
spec:
  clusterIP: 10.11.241.93
  externalTrafficPolicy: Cluster
  ports:
  - nodePort: 30641
    port: 50000
    protocol: TCP
    targetPort: 8080
  selector:
    app: parts
    department: engineering
  sessionAffinity: None
  type: LoadBalancer
status:
  loadBalancer:
    ingress:
    - ip: 203.0.113.200

用戶端會呼叫位於 203.0.113.200 的 TCP 通訊埠 50000 上的 Service。要求會轉送至 TCP 通訊埠 8080 上的其中一個成員 Pod。

多個通訊埠

Service 的 ports 欄位包含一系列的 ServicePort物件,而 ServicePort 物件有以下欄位:

  • name
  • protocol
  • port
  • targetPort
  • nodePort

如果您有數個 ServicePort,每個 ServicePort 都必須要有獨特的名稱。

以下是 LoadBalancer 類型的 Service,它擁有兩個 ServicePort 物件:

apiVersion: v1
kind: Service
metadata:
  name: my-tp-service
spec:
  clusterIP: 10.11.242.196
  externalTrafficPolicy: Cluster
  ports:
  - name: my-first-service-port
    nodePort: 31233
    port: 60000
    protocol: TCP
    targetPort: 50000
  - name: my-second-service-port
    nodePort: 31081
    port: 60001
    protocol: TCP
    targetPort: 8080
  selector:
    app: tests
    department: engineering
  sessionAffinity: None
  type: LoadBalancer
status:
  loadBalancer:
    ingress:
    - ip: 203.0.113.201

在上述範例中,如果用戶端呼叫位於 203.0.113.201 的 TCP 通訊埠 60000 上的 Service,系統會把要求轉送至 TCP 通訊埠 50000 上的成員 Pod。不過,如果用戶端在 TCP 通訊埠 60001 上從 203.0.113.201 呼叫服務,要求則會轉送至 TCP 通訊埠 8080 上的成員 Pod。

每個成員 Pod 都必須有一個監聽 TCP 通訊埠 50000 的容器,以及一個監聽 TCP 通訊埠 8080 的容器。這可以是具有兩個執行緒的單一容器,或在同一個 Pod 中執行的兩個容器。

Service 端點

當您建立服務時,Kubernetes 會建立 Endpoints 物件,而該物件的名稱會與您的 Service 名稱相同。Kubernetes 會使用該 Endpoints 物件來記錄哪些 Pod 是 Service 的成員。

後續步驟

本頁內容對您是否有任何幫助?請提供意見:

傳送您對下列選項的寶貴意見...

這個網頁
Kubernetes Engine 說明文件