使用 Service 公開應用程式


本頁說明如何在 Google Kubernetes Engine (GKE) 中建立 Kubernetes 服務,公開應用程式,讓應用程式可從內部網路或網際網路存取。涵蓋五種服務類型:ClusterIP、NodePort、LoadBalancer、ExternalName 和 Headless。

本教學課程提供每種服務類型的範例,說明如何建立部署、使用服務公開部署,以及存取部署。

本頁適用於佈建及設定雲端資源,並部署應用程式和服務的營運人員和開發人員。如要進一步瞭解內容中提及的常見角色和範例工作,請參閱「常見的 GKE Enterprise 使用者角色和工作」。 Google Cloud

閱讀本頁面之前,請先熟悉如何使用 kubectl

簡介

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

服務有五種類型:

  • ClusterIP (預設)
  • NodePort
  • LoadBalancer
  • ExternalName
  • 無頭

Autopilot 叢集預設為公開。如果您選擇私人 Autopilot 叢集,則必須設定 Cloud NAT,才能建立傳出網際網路連線,例如從 DockerHub 提取映像檔。

本主題附有幾項練習。在每項練習中,您會透過建立服務來建立部署,並公開該部署的 Pod,然後傳送 HTTP 要求至服務。

事前準備

開始之前,請確認你已完成下列工作:

  • 啟用 Google Kubernetes Engine API。
  • 啟用 Google Kubernetes Engine API
  • 如要使用 Google Cloud CLI 執行這項工作,請安裝初始化 gcloud CLI。如果您先前已安裝 gcloud CLI,請執行 gcloud components update,取得最新版本。
* 建立 GKE 叢集

建立 ClusterIP 類型的服務

在本節中,您將建立 ClusterIP 類型的 Service。

kubectl apply

以下是部署的資訊清單:

apiVersion: apps/v1
kind: Deployment
metadata:
  name: my-deployment
spec:
  selector:
    matchLabels:
      app: metrics
      department: sales
  replicas: 3
  template:
    metadata:
      labels:
        app: metrics
        department: sales
    spec:
      containers:
      - name: hello
        image: "us-docker.pkg.dev/google-samples/containers/gke/hello-app:2.0"

將資訊清單複製到名為「my-deployment.yaml」的檔案,然後建立 Deployment:

kubectl apply -f my-deployment.yaml

確認有三個 Pod 正在執行:

kubectl get pods

輸出會顯示三個執行中的 Pod:

NAME                            READY   STATUS    RESTARTS   AGE
my-deployment-dbd86c8c4-h5wsf   1/1     Running   0          7s
my-deployment-dbd86c8c4-qfw22   1/1     Running   0          7s
my-deployment-dbd86c8c4-wt4s6   1/1     Running   0          7s

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

apiVersion: v1
kind: Service
metadata:
  name: my-cip-service
spec:
  type: ClusterIP
  # Uncomment the below line to create a Headless Service
  # clusterIP: None
  selector:
    app: metrics
    department: sales
  ports:
  - protocol: TCP
    port: 80
    targetPort: 8080

該服務具有指定兩個標籤的選取器:

  • app: metrics
  • department: sales

在先前建立的部署中,每個 Pod 都會有這兩個標籤。因此部署中的 Pod 會成為這項服務的成員。

將資訊清單儲存到名為「my-cip-service.yaml」的檔案,然後建立 Service:

kubectl apply -f my-cip-service.yaml

請稍候幾分鐘,讓 Kubernetes 將穩定的內部位址指派給服務,並接著查看該服務:

kubectl get service my-cip-service --output yaml

輸出會顯示 clusterIP 的值:

spec:
  clusterIP: 10.59.241.241

請記下 clusterIP 的值,稍後將會用到。

控制台

可建立部署作業

  1. 前往 Google Cloud 控制台的「Workloads」(工作負載) 頁面。

    前往「Workloads」(工作負載)

  2. 按一下「部署」

  3. 在「Specify container」(指定容器) 下方,選取「Existing container image」(現有容器映像檔)

  4. 在「Image path」(圖片路徑) 中輸入 us-docker.pkg.dev/google-samples/containers/gke/hello-app:2.0

  5. 依序點選「完成」和「繼續」。

  6. 在「設定」下方的「應用程式名稱」中輸入 my-deployment

  7. 在「標籤」底下建立下列標籤:

    • 鍵: app 和「值」:metrics
    • 鍵: department 和「值」:sales
  8. 在「叢集」下方,選擇要建立 Deployment 的叢集。

  9. 按一下 [Deploy] (部署)

  10. 部署作業就緒後,「Deployment details」(部署作業詳細資料) 頁面隨即開啟。在「Managed pods」(代管的 pod) 下方,您可以看到部署作業有一或多個執行中的 Pod。

建立服務來公開您的部署

  1. 在「部署詳細資料」頁面中,依序點選 「動作」>「公開」。
  2. 在「Expose」(公開) 對話方塊的「Port mapping」(通訊埠對應) 下方,設定下列值:

    • 通訊埠: 80
    • 目標通訊埠: 8080
    • 通訊協定: TCP
  3. 在「服務類型」下拉式清單中,選取「叢集 IP」

  4. 按一下 [公開]。

  5. 當您的服務就緒時,「服務詳細資料」頁面就會開啟,您可以看到服務的相關詳細資料。在「叢集 IP」下方,記下 Kubernetes 指派給服務的 IP 位址。這是內部用戶端可以用來呼叫服務的 IP 位址。

存取您的服務

列出執行中的 Pod:

kubectl get pods

在輸出中,複製任何一個名稱開頭是 my-deployment 的 Pod。

NAME                            READY   STATUS    RESTARTS   AGE
my-deployment-dbd86c8c4-h5wsf   1/1     Running   0          2m51s

將殼層放入其中一個執行中的容器:

kubectl exec -it POD_NAME -- sh

POD_NAME 替換為 my-deployment 中的其中一個 Pod 名稱。

在您的殼層中安裝 curl

apk add --no-cache curl

在容器中,使用叢集 IP 位址和通訊埠 80 向您的服務發出要求。請注意,80 是您服務的 port 欄位值,您會使用這個通訊埠做為服務的用戶端。

curl CLUSTER_IP:80

CLUSTER_IP 替換為您 Service 中的 clusterIP 值。

您的要求會轉送至 TCP 通訊埠 8080 上其中一個成員 Pod,也就是 targetPort 欄位的值。請注意,服務的每個成員 Pod 都必須有監聽通訊埠 8080 的容器。

回應會顯示 hello-app 的輸出:

Hello, world!
Version: 2.0.0
Hostname: my-deployment-dbd86c8c4-h5wsf

如要結束殼層以返回容器,請輸入 exit

建立 NodePort 類型的服務

在本節中,您將建立 NodePort 類型的 Service。

kubectl apply

以下是部署的資訊清單:

apiVersion: apps/v1
kind: Deployment
metadata:
  name: my-deployment-50000
spec:
  selector:
    matchLabels:
      app: metrics
      department: engineering
  replicas: 3
  template:
    metadata:
      labels:
        app: metrics
        department: engineering
    spec:
      containers:
      - name: hello
        image: "us-docker.pkg.dev/google-samples/containers/gke/hello-app:2.0"
        env:
        - name: "PORT"
          value: "50000"

請注意資訊清單中的 env 物件。env 物件會將執行中容器的 PORT 環境變數值指定為 50000hello-app 應用程式會監聽 PORT 環境變數指定的通訊埠,因此在本練習中,您會告知容器監聽通訊埠 50000。

將資訊清單複製到名為「my-deployment-50000.yaml」的檔案,然後建立 Deployment:

kubectl apply -f my-deployment-50000.yaml

確認有三個 Pod 正在執行:

kubectl get pods

以下的資訊清單是針對 NodePort 類型的服務:

apiVersion: v1
kind: Service
metadata:
  name: my-np-service
spec:
  type: NodePort
  selector:
    app: metrics
    department: engineering
  ports:
  - protocol: TCP
    port: 80
    targetPort: 50000

將資訊清單儲存到名為「my-np-service.yaml」的檔案,然後建立 Service:

kubectl apply -f my-np-service.yaml

查看 Service:

kubectl get service my-np-service --output yaml

輸出會顯示 nodePort 值:

...
  spec:
    ...
    ports:
    - nodePort: 30876
      port: 80
      protocol: TCP
      targetPort: 50000
    selector:
      app: metrics
      department: engineering
    sessionAffinity: None
    type: NodePort
...

建立防火牆規則來允許節點通訊埠上的 TCP 流量:

gcloud compute firewall-rules create test-node-port \
    --allow tcp:NODE_PORT

NODE_PORT 替換為服務的 nodePort 欄位值。

控制台

可建立部署作業

  1. 前往 Google Cloud 控制台的「Workloads」(工作負載) 頁面。

    前往「Workloads」(工作負載)

  2. 按一下「部署」

  3. 在「Specify container」(指定容器) 下方,選取「Existing container image」(現有容器映像檔)

  4. 在「Image path」(圖片路徑) 中輸入 us-docker.pkg.dev/google-samples/containers/gke/hello-app:2.0

  5. 按一下「新增環境變數」

  6. 在「Key」(索引鍵) 中輸入 PORT,以及在「Value」(值) 中輸入 50000

  7. 依序點選「完成」和「繼續」。

  8. 在「設定」下方的「應用程式名稱」中輸入 my-deployment-50000

  9. 在「標籤」底下建立下列標籤:

    • 鍵: app值: metrics
    • 鍵: department 和「值」:engineering
  10. 在「叢集」下方,選擇要建立 Deployment 的叢集。

  11. 按一下 [Deploy] (部署)

  12. 部署作業就緒後,「Deployment details」(部署作業詳細資料) 頁面隨即開啟。在「Managed pods」(代管的 pod) 下方,您可以看到部署作業有一或多個執行中的 Pod。

建立服務來公開您的部署

  1. 在「部署詳細資料」頁面中,依序點選 「動作」>「公開」。
  2. 在「Expose」(公開) 對話方塊的「Port mapping」(通訊埠對應) 下方,設定下列值:

    • 通訊埠: 80
    • 目標通訊埠: 50000
    • 通訊協定: TCP
  3. 在「服務類型」下拉式選單中,選取「節點通訊埠」

  4. 按一下 [公開]。

  5. 當您的服務就緒時,「服務詳細資料」頁面就會開啟,您可以看到服務的相關詳細資料。在「通訊埠」下方,記下 Kubernetes 指派給服務的「節點通訊埠」

建立節點通訊埠的防火牆規則

  1. 前往 Google Cloud 控制台的「Firewall policies」(防火牆政策) 頁面。

    前往「Firewall policies」(防火牆政策) 頁面

  2. 按一下 「建立防火牆規則」

  3. 在「Name」(名稱) 中輸入 test-node-port

  4. 從「Targets」(目標) 下拉式清單中,選取「All instances in the network」(網路中的所有執行個體)

  5. 在「Source IPv4 ranges」(來源 IPv4 範圍) 中輸入 0.0.0.0/0

  6. 在「Protocols and ports」(通訊協定與通訊埠) 下方,選取 [Specified protocols and ports] (指定的通訊協定與通訊埠)

  7. 勾選「tcp」tcp核取方塊,然後輸入您記下的節點通訊埠值。

  8. 點選「建立」

取得節點 IP 位址

找出其中一個節點的外部 IP 位址:

kubectl get nodes --output wide

輸出結果會與下列內容相似:

NAME          STATUS    ROLES     AGE    VERSION        EXTERNAL-IP
gke-svc-...   Ready     none      1h     v1.9.7-gke.6   203.0.113.1

並非所有叢集的節點都有外部 IP 位址,舉例來說,如果您啟用私人節點,節點就不會有外部 IP 位址。

存取您的服務

在瀏覽器的網址列中輸入下列內容:

NODE_IP_ADDRESS:NODE_PORT

更改下列內容:

  • NODE_IP_ADDRESS:其中一個節點的外部 IP 位址,在先前工作建立服務時找到。
  • NODE_PORT:節點通訊埠值。

輸出結果會與下列內容相似:

Hello, world!
Version: 2.0.0
Hostname: my-deployment-50000-6fb75d85c9-g8c4f

建立 LoadBalancer 類型的服務

在本節中,您將建立 LoadBalancer 類型的 Service。

kubectl apply

以下是部署的資訊清單:

apiVersion: apps/v1
kind: Deployment
metadata:
  name: my-deployment-50001
spec:
  selector:
    matchLabels:
      app: products
      department: sales
  replicas: 3
  template:
    metadata:
      labels:
        app: products
        department: sales
    spec:
      containers:
      - name: hello
        image: "us-docker.pkg.dev/google-samples/containers/gke/hello-app:2.0"
        env:
        - name: "PORT"
          value: "50001"

請注意,這個部署中的容器將會監聽通訊埠 50001。

將資訊清單複製到名為「my-deployment-50001.yaml」的檔案,然後建立 Deployment:

kubectl apply -f my-deployment-50001.yaml

確認有三個 Pod 正在執行:

kubectl get pods

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

apiVersion: v1
kind: Service
metadata:
  name: my-lb-service
spec:
  type: LoadBalancer
  selector:
    app: products
    department: sales
  ports:
  - protocol: TCP
    port: 60000
    targetPort: 50001

將資訊清單複製到名為「my-lb-service.yaml,」的檔案,然後建立 Service:

kubectl apply -f my-lb-service.yaml

建立 LoadBalancer 類型的 Service 時, Google Cloud控制器會喚醒並設定外部直通式網路負載平衡器。請稍候幾分鐘,讓控制器設定外部直通式網路負載平衡器,並產生穩定的 IP 位址。

查看 Service:

kubectl get service my-lb-service --output yaml

輸出會在 loadBalancer:ingress 底下顯示穩定的外部 IP 位址:

...
spec:
  ...
  ports:
  - ...
    port: 60000
    protocol: TCP
    targetPort: 50001
  selector:
    app: products
    department: sales
  sessionAffinity: None
  type: LoadBalancer
status:
  loadBalancer:
    ingress:
    - ip: 203.0.113.10

控制台

可建立部署作業

  1. 前往 Google Cloud 控制台的「Workloads」(工作負載) 頁面。

    前往「Workloads」(工作負載)

  2. 按一下「部署」

  3. 在「Specify container」(指定容器) 下方,選取「Existing container image」(現有容器映像檔)

  4. 在「Image path」(圖片路徑) 中輸入 us-docker.pkg.dev/google-samples/containers/gke/hello-app:2.0

  5. 按一下「新增環境變數」

  6. 在「Key」(索引鍵) 中輸入 PORT,以及在「Value」(值) 中輸入 50001

  7. 依序點選「完成」和「繼續」。

  8. 在「設定」下方的「應用程式名稱」中輸入 my-deployment-50001

  9. 在「標籤」底下建立下列標籤:

    • 鍵: app 和「值」:products
    • 鍵: department 和「值」:sales
  10. 在「叢集」下方,選擇要建立 Deployment 的叢集。

  11. 按一下 [Deploy] (部署)

  12. 部署作業就緒後,「Deployment details」(部署作業詳細資料) 頁面隨即開啟。在「Managed pods」(代管的 pod) 下方,您可以看到部署作業有一或多個執行中的 Pod。

建立服務來公開您的部署

  1. 在「部署詳細資料」頁面中,依序點選 「動作」>「公開」。
  2. 在「Expose」(公開) 對話方塊的「Port mapping」(通訊埠對應) 下方,設定下列值:

    • 通訊埠: 60000
    • 目標通訊埠: 50001
    • 通訊協定: TCP
  3. 在「服務類型」下拉式選單中,選取「負載平衡器」

  4. 按一下 [公開]。

  5. 當您的服務就緒時,「服務詳細資料」頁面就會開啟,您可以看到服務的相關詳細資料。在「Load Balancer」(負載平衡器) 下方,記下負載平衡器的外部 IP 位址。

存取您的服務

請稍候幾分鐘,讓 GKE 設定負載平衡器。

在瀏覽器的網址列中輸入下列內容:

LOAD_BALANCER_ADDRESS:60000

LOAD_BALANCER_ADDRESS 替換為負載平衡器的外部 IP 位址。

回應會顯示 hello-app 的輸出:

Hello, world!
Version: 2.0.0
Hostname: my-deployment-50001-68bb7dfb4b-prvct

請注意,服務中的 port 值為任意值,上述範例使用 60000 的 port 值來示範這點。

建立 ExternalName 類型的服務

在本節中,您將建立 ExternalName 類型的 Service。

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

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

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

在上述範例中,DNS 名稱為 my-xn-service.default.svc.cluster.local。當內部用戶端向 my-xn-service.default.svc.cluster.local 發出要求時,系統會把該要求重新導向至 example.com。

使用 kubectl expose 建立服務

除了編寫服務資訊清單以外,您也可以使用 kubectl expose 建立服務來公開部署。

如要公開本主題前面所述的 my-deployment,您可以輸入這個指令:

kubectl expose deployment my-deployment --name my-cip-service \
    --type ClusterIP --protocol TCP --port 80 --target-port 8080

如要公開本主題前面所述的 my-deployment-50000,您可以輸入這個指令:

kubectl expose deployment my-deployment-50000 --name my-np-service \
    --type NodePort --protocol TCP --port 80 --target-port 50000

如要公開本主題前面所述的 my-deployment-50001,您可以輸入這個指令:

kubectl expose deployment my-deployment-50001 --name my-lb-service \
    --type LoadBalancer --port 60000 --target-port 50001

查看服務

您可以在 Google Cloud 控制台的「Services」(服務) 頁面中查看建立的 Service。

前往「Service」分頁

或者,您也可以在應用程式中心中,查看服務支援的業務功能。App Hub 提供所有應用程式及其相關聯服務的集中總覽。

如要在 App Hub 中查看服務,請前往 Google Cloud 控制台的「App Hub」頁面。

前往 App Hub

做為代管 Kubernetes 服務,每當資源建立或毀損時,GKE 會自動將服務中繼資料 (具體來說是資源 URI) 傳送至 App Hub。這項持續運作的元資料擷取功能,可提升 App Hub 的應用程式建構和管理體驗。

如要進一步瞭解 App Hub 支援的資源,請參閱「支援的資源」。

如要瞭解如何在專案中設定 App Hub,請參閱「設定 App Hub」。

正在清除所用資源

完成本頁的練習後,請按照下列步驟移除資源,以免您的帳戶產生不必要的費用:

kubectl apply

刪除您的服務

kubectl delete services my-cip-service my-np-service my-lb-service

刪除您的部署

kubectl delete deployments my-deployment my-deployment-50000 my-deployment-50001

刪除您的防火牆規則

gcloud compute firewall-rules delete test-node-port

主控台

刪除您的服務

  1. 前往 Google Cloud 控制台的「服務」頁面。

    前往「Service」分頁

  2. 選取您在本練習中建立的服務,然後按一下「Delete」(刪除)

  3. 當系統提示時,按一下「Delete」(刪除)

刪除您的部署

  1. 前往 Google Cloud 控制台的「Workloads」(工作負載) 頁面。

    前往「Workloads」(工作負載)

  2. 選取您在本練習中建立的部署作業,然後按一下 「Delete」(刪除)

  3. 系統提示確認時,請選取「Delete Horizontal Pod Autoscalers associated with selected Deployments」(刪除與所選 Deployment 相關聯的水平 Pod 自動配置器) 核取方塊,然後按一下「Delete」(刪除)

刪除您的防火牆規則

  1. 前往 Google Cloud 控制台的「Firewall policies」(防火牆政策) 頁面。

    前往「Firewall policies」(防火牆政策) 頁面

  2. 選取「test-node-port」核取方塊,然後按一下 「刪除」

  3. 當系統提示時,按一下「Delete」(刪除)

後續步驟