Google Kubernetes Engine 是什麼?GKE 簡介與手把手操作教學

Google Kubernetes Eengine 是 Kubernetes 在 GCP 的雲端加值版本,可以讓你的 Kubernetes 在管理 Docker 容器應用程式的時候,更方便好用。

假如你本來就已經會使用容器技術,例如 Docker,可以使用虛擬機器或是 Cloud Run 來運作容器應用程式,但當我們的系統變得更加複雜時,我們可能需要更強大的工具來管理整個應用程式生態系統。

這時候就需要「容器編排」技術了。編排(Orchestration)這個詞來自音樂領域,就像指揮家需要協調管弦樂團中的各種樂器,讓他們在正確的時間演奏正確的音符,最終產生和諧的音樂一樣,容器編排就是自動化協調和管理複雜系統中多個容器元件的過程。它負責決定哪些容器應該在哪裡運行、如何分配資源、確保容器間的通訊,以及根據需求自動擴展或縮減容器數量。

Kubernetes 簡介

為什麼需要 Kubernetes

想像一下,你正在經營一家大型的線上商店。最初,你可能只有一個簡單的網站容器在運行,這時 Cloud Run 就足夠了。但隨著業務成長,你的系統開始變得複雜:

  • 前端網站需要與後端 API 服務通訊
  • 需要負載平衡來分配流量
  • 某些服務需要定期備份和更新
  • 不同的服務有不同的資源需求
  • 需要監控各個環節的健康狀態

這時候,單純使用多個獨立的容器服務就變得難以管理。你需要手動協調各個服務之間的通訊、處理故障恢復、管理各種設定檔和機密資訊等等。這就是 Kubernetes 要解決的問題。

單個容器獨立管理因數量變多導致工作繁重

Kubernetes(常簡稱為 K8s)是一個開源的容器編排平台,它就像是一個聰明的指揮家,能夠協調和管理大量的容器化應用程式。

Kubernetes 的核心價值

它的核心價值在於:

自動化部署和擴充:
根據負載自動增加或減少容器執行個體的數量。

服務發現 (Service Discovery) 和負載平衡:
服務發現機制讓服務能夠輕鬆找到彼此,並自動分配流量到健康的容器。

自我修復能力:
當某個容器發生故障,會自動重啟新的容器,確保系統的高可用性。

設定和機密資訊管理:
提供了統一的方式來管理應用程式的設定資訊和敏感資料。

滾動更新 (Rolling Update):
能夠逐步替換舊版本的容器,確保服務不中斷。

從單一容器到容器叢集

如果說 Cloud Run 讓我們能夠輕鬆運行單一的容器化應用程式,那麼 Kubernetes 就是讓我們能夠管理整個容器化應用程式生態系統的平台。它將多個容器組織成一個協調運作的叢集 (Cluster) ,每個容器都有自己的角色和責任,但它們共同協作來提供完整的服務。

就像管理一個小型團隊發展到管理一個大型組織。在小團隊中,每個人可能身兼多職,溝通簡單直接。但在大型組織中,你需要明確的分工、標準化的流程、有效的溝通機制,以及能夠快速適應變化的管理體系。

Google Kubernetes Engine (GKE) 簡介

雖然 Kubernetes 非常強大,但設置和維護一個 Kubernetes 叢集本身就是一項複雜的任務。你需要處理主節點的高可用性、網路配置、安全性設定、監控和日誌收集等等。

你可以在地端,或使用 Compute Engine 的虛擬機器來架設 Kubernetes,但是整個過程非常繁瑣,架設完成還要處理各個節點之前的通訊,極為複雜且耗時,當你花了好幾搭建好環境,你都還沒處理到應用程式的部分。

這就是為什麼 Google 推出了 Google Kubernetes Engine

在自建 Kubernetes 和直接使用 GKE 的建置過程差異

GKE 是 Google Cloud 提供的代管式 Kubernetes 服務。它讓你能夠善用 Kubernetes 的所有強大功能,同時 Google 會負責處理底層的基礎建設管理工作。代表你可以專注於開發和部署應用程式,而不需要擔心 Kubernetes Cluster 本身的維護。

Kubernetes 的幾個核心物件

在開始使用 GKE 之前,先來了解 Kubernetes 的幾個核心物件:

Node:工作節點而非虛擬機器

Node 是指叢集中的工作節點。為什麼不直接叫「虛擬機器」?因為 Node 是一個更抽象的概念:它可以是實體機器或虛擬機器。Kubernetes 把這些不同類型的運算資源統一稱為 Node,強調的是它們的「工作節點」角色,能夠運作容器,至於它們到底是怎樣的機器,其實並不重要。

Pod:容器的最小單位

Pod 是 Kubernetes 中部署和管理的最小單位。一個 Pod 通常包含一個容器,但也可以包含多個緊密相關的容器。這些容器共享網路和儲存資源,就像室友共享一個公寓一樣。Pod 的生命週期很短暫,隨時可能被創建或銷毀。

Deployment:管理應用程式的生命週期

Deployment 負責管理你的應用程式如何部署和更新。它告訴 Kubernetes:「我想要運行 3 個網站的副本」,然後 Deployment 會確保始終有 3 個健康的 Pod 在運行。如果某個 Pod 掛掉了,Deployment 會自動建立新的來替代。當你要更新應用程式時,Deployment 也會協調整個更新過程。

Service:穩定的網路端點

由於 Pod 會頻繁地建立和銷毀,它們的 IP 地址也會不斷變化。Service 就像是一個穩定的門牌號碼,為一組 Pod 提供固定的網路端點。無論後面的 Pod 如何變化,其他服務都可以通過 Service 找到它們,不需要你手動調整網路連結。

Ingress:對外開放的大門

Ingress 是叢集的對外入口,負責將外部的 HTTP/HTTPS 流量路由到叢集內的 Service。它就像是一個智慧的接待人員,根據 URL 路徑或網域將流量導向正確的服務。比如,當用戶訪問 api.example.com 時,Ingress 會將請求轉發給 API 服務;訪問 app.example.com 時,則轉發給前端應用程式。

整體的運作架構示意如下圖:

Kubernetes 核心物件架構

這些元件形成了一個完整的體系:Node 提供運算資源,Pod 在 Node 上運行你的應用程式,Deployment 管理 Pod 的生命週期,Service 為 Pod 提供穩定的網路訪問方式,而 Ingress 則負責將外部流量導入到正確的 Service。

就像一個運作良好的公司:Node 是辦公大樓,Pod 是員工工作的辦公室,Deployment 是人事部門負責人員配置,Service 是內部電話系統,而 Ingress 是前台接待處。

建立你的第一個 GKE Cluster

了解了 Kubernetes 的核心概念後,現在讓我們實際建立一個 GKE Cluster。GKE 提供了兩種主要的叢集模式,讓我們先來了解它們的差異。

Standard 模式 vs Autopilot 模式

GKE 提供兩種不同的 Cluster 運作模式,各有其適用場景:

Standard 模式(標準模式)

Standard 模式讓你擁有完整的控制權,就像擁有一輛可以自己調整引擎、變速箱的汽車。你需要自己管理節點(Node)的配置、擴展策略、安全性設定等等。這種模式適合有經驗的團隊,需要精細控制叢集行為,或是有特殊的硬體需求。

要注意的是,當你建立完 Cluster,它會幫你建立好節點,其實你還沒部署應用程式,代表這些節點資源已經開始隨著時間計費,這樣會浪費你的預算,你就可以選擇 Autopilot 模式。

Autopilot 模式(自動駕駛模式)

Autopilot 模式就像使用自動駕駛汽車,Google 會自動處理大部分的基礎設施管理工作。它會自動配置節點、處理安全性更新、優化資源使用,並且只針對你實際使用的 Pod 資源收費,所以讓你還沒部署 Pod 的時候,還沒建立任何 Node,就不會針對 Node 收取費用。

這種模式特別適合想要專注於應用程式開發,而不想花時間管理基礎設施的團隊。對於初學者和大多數應用場景,我們推薦使用 Autopilot 模式,因為它大幅簡化了叢集管理的複雜度。

使用 GCP Console 來建立 GKE Autopilot Cluster

讓我們透過 Google Cloud Console 來建立第一個 Autopilot Cluster,點擊「叢集」,再點「建立」:

建立第一個 GKE Cluster

名稱我們保持預設,區域一樣選擇 asia-east1,然後在級別的部分選擇「標準級」,然後再點「下一個區段:機群註冊」:

Cluster 命名、設定位置和級別

GKE 有個最新功能叫做 GKE Fleet Management,可以將不同 Google Cloud 專案中的GKE Cluster 地群組在一起,而且不只 GKE Cluster,也包含地端環境、其他雲端平台的 Cluster 都可以納入管理,這樣就能一次管理所有應用程式,簡化維運工作。

在這裡我們只有一個 Cluster,所以可略過這個功能,再點「下一個區段:網路連線」:

機群註冊

在這裡保持預設即可,其中可以注意的是,最右邊有 Pod 和 Service 的 IP 範圍,代表 Kubernetes 會分配 IP 位址給它們使用,而在 GKE 環境下,就是會把 Subnet 的次要 IP 範圍自動分配給它們,我們不用額外設定。再點「下一個區段:進階設定」:

GKE Cluster 網路設定

在「目前發布版本」的下拉式選單中,我們選擇「一般(建議)」,然後再按下「建立」: 

選擇版本類型並建立 Cluster

接下來就等待  Cluster 建立完成,在這裡大概需要等待 5~10 分鐘左右:

等待 GKE Cluster 建立完成

這裡順便補充一下,大部分熟悉 Kubernertes 的工程師都偏好使用指令來建立和管理 GKE Cluster,我們也開啟 Cloud Shell 來建立第二個 Cluster 看看吧!

使用 gcloud 指令建立 Autopilot Cluster

gcloud container clusters create-auto autopilot-cluster-2  –region=asia-east1     –release-channel=regular

執行完後,你會看到它在建立過程的相關訊息,包含 Cluster 名稱、版本、Cluster IP、機器類型、節點數量等等:

使用指令建立 GKE Cluster 完成

使用 gcloud 和 kubectl 指令操作 GKE Cluster

我們回到建立好的 autopilot-cluster-1,我們可以用指令來查看它的相關資訊 (autopilot-cluster-2 如果沒用到可以先刪除):

取得 Cluster 憑證以便使用 kubectl 工具

gcloud container clusters get-credentials autopilot-cluster-1  –region=asia-east1

這個指令的作用就像是取得鑰匙,告訴 kubectl 叢集在哪裡,並且提供身分驗證資訊,來證明你有權限管理這個 Cluster 的憑證,然後把連線的設定儲存在本機電腦的 ~/.kube/config 檔案。

檢查叢集狀態

kubectl cluster-info

查看節點資訊

kubectl get nodes

檢查系統 Pod 狀態

kubectl get pods –all-namespaces

使用 kubectl 指令查看 GKE Cluster 相關資訊

到這裡你可能會覺得奇怪,為什麼指令分成 gcloud 和 kubectl?

gcloud 是 Google Cloud 的管理工具,負責管理 Google Cloud 上的資源,包含建立或刪除 GKE 叢集、管理帳單、權限、API 啟用。

而 kubectl 是 Kubernetes 用來管理 Cluster 內部的應用程式。能夠部署應用程式到 Cluster、查看 Pod、Service 的狀態、管理設定檔和執行日常維護工作。

而且每次下達 kubectl 指令,並不會用參數指定要操作的 Cluster,當你專案內有多個 Cluster 的時候,它不會知道你要對誰操作,所以才必須要 get-credentials 這個指令,才能操作到正確的 Cluster,當然你也可以再執行一次 get-credentials,切換到另外一個 Cluster,再去執行管理動作。 

部署應用程式到 GKE Cluster

使用 GKE Deployment 物件部署容器映像檔到 Pod

Cluster 建立完成,現在來部署應用程式到 Cluser,我們點擊「佈署」(雖然我覺得是「部署」):

部署應用程式到 GKE

這裡設定的部署作業就像上面提到的 deployment 物件,我們可以在這裡指定跟上個單元相同的容器映像檔,再按「下一步:公開(選用)」:

設定部署的目的 Cluster 和容器

部署 GKE Service 物件 (Network Load Balancer)

做到這裡可以讓 Pod 部署完成,但是要注意這個設定還不會讓 Pod 直接對外,你必須在勾選「以新 Service 的形式公開 Deployment」 。

在這裡要注意,我們當初在建立容器映像檔的時候,我們讓容器本身對外開放 Port 8080,上面的 80 是指負載平衡器對外的 Port,但是當流量進來之後,要指定 8080 才能存取到容器上的網頁喔。 

在服務類型保持預設的「負載平衡器」,它就會直接在 Google Cloud 上建立負載平衡器。 然後我們再按下建立。

設定 Service

接下來再等待幾分鐘會看到這個 Deployment 已經部署完成了,視窗可以再往下滑:

看到 Deployment 部署完成

我們往下看到各種物件產生,包含一個 Deployment 物件,和三個 Pod 物件,都是在正常運作的狀態:

往下看到各種物件產生

你可以再打開 Cloud Shell,下達各種相關的查詢指令 (記得要先 get-credentials) 喔! 

查看目前部署的 Deployment

kubectl get deployments

查看目前部署的 Pod

kubectl get pods

查看目前部署的 Service 

kubectl get services

你會看到它有產生一個外部 IP,是對外開放存取的。

輸入 kubectl 各項查詢指令

你可以打開瀏覽器輸入 https://[IP位址],或是直接在 Web Console 上面點擊會看到網頁秀出來,不過在這裡要稍微等待一下,因為我們現在使用的是 Autopilot 模式,是連 Node 都還沒建立的情況,所以現在要先等它建立 Node,再部署 Deployment、Pod 和 Service。

過幾分鐘之後,我們看到它部署完成,也看到網頁出現了!

點擊服務連結看到網頁出現

另外我們也可以在負載平衡器頁面看到一個負載平衡器:

也可以在負載平衡器頁面看到一個 TCP 負載平衡器

要注意它是 TCP 負載平衡器,它工作在網路的第 4 層(傳輸層),只能根據 IP 位址和 Port 來分配流量。無法根據 URL 路徑進行導向 (例如 /api 或 /admin),也無法根據網域名稱進行路由。

如果我們想要更聰明的流量路由功能,就需要使用 Application Load Balancer (ALB)。ALB 工作在第 7 層(應用層),能夠處理 HTTP/HTTPS 通訊協定的內容,提供更豐富的路由功能。

但目前在 Google Cloud 的 Console 上沒有辦法直接建立 ALB,必須要使用指令和設定檔的方式,來建立 Ingress 物件。

部署 GKE Ingress 物件 (Application Load Balancer)

不過!現在要先刪除原有的 deployment-1-service (Load Balancer),以免後續物件在建立時,會有衝突喔!

刪除  deployment-1-service (Load Balancer)

刪除之後,我們再建立 2 個物件:

第一個物件:ClusterIP 類型的 Service

ClusterIP Service 是 Kubernetes 中最基本的 Service 類型,它只在 Cluster 內部提供一個穩定的 IP 位址和 DNS 名稱。雖然 ClusterIP Service 無法從 Cluster 外部直接訪問,但它為 Cluster 內部的通訊提供了完美的抽象層。

你可以把 ClusterIP Service 想像成公司內部的分機號碼系統。員工可以通過分機號碼找到彼此,但外部的人無法直接撥打分機號碼。

我們現在 Cloud Shell 的環境準備好一個設定檔 cluster-ip-service.yaml,內容如下:

apiVersion: v1
kind: Service
metadata:
  name: deployment-1-service
  labels:
    app: deployment-1
spec:
  type: ClusterIP 
  selector:
    app: deployment-1
    app.kubernetes.io/managed-by: cloud-console
  ports:
  - port: 80
    targetPort: 8080
    protocol: TCP

接著來執行這個指令:

kubectl apply -f cluster-ip-service.yaml

執行部署 ClusterIP Service 物件

這裡說明一下指令和參數:

kubectl apply 

這是 Kubernetes 的宣告式管理指令。它的意思是:「讓 Cluster 的實際狀態符合這個檔案中描述的期望狀態」。如果資源不存在,它會建立;如果已存在但設定有任何不同,它會更新。

-f 參數

代表 “file”,告訴 kubectl 從檔案中讀取設定。你也可以使用 -f 指定多個檔案,或是指定包含多個 YAML 檔的目錄。

YAML(YAML Ain’t Markup Language)

這是是一種人類易讀的資料序列化格式。在 Kubernetes 中,我們使用 YAML 檔來描述我們想要的資源狀態。

在 Kubernetes 的術語中,這些 YAML 檔被稱為 Manifest(資訊清單)。Manifest 是一份宣告式的文件,描述了 Kubernetes 資源的期望狀態。它不是告訴 Kubernetes「如何做」,而是告訴它「我想要什麼結果」,有點像在許願的感覺,而且它會使命必達的實現你的願望。

PS. 我以前不懂 Manifest 到底是什麼,但自從看了國外的吸引力法則或顯化法則,才知道 Manifest 就是顯化的意思,把你想要的現實呈現出來。

第二個物件:Ingress

Ingress 是真正負責處理外部流量並提供 ALB 功能的物件,它就像是建築物的智慧接待處,能夠根據 URL 路徑決定要導向哪個服務,也能根據網域名進行路由,把流量帶向目的服務。(感覺跟 Load Balancer 一模一樣)

設定檔 ingress-1.yaml 的內容如下:

apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: ingress-1
  namespace: default
  annotations:
    kubernetes.io/ingress.class: "gce"
spec:
  rules:
  - http:
      paths:
      - path: /
        pathType: Prefix
        backend:
          service:
            name: deployment-1-service
            port:
              number: 80

接著來執行這個指令:

kubectl apply -f ingress-1.yaml

你會看到它有一個警告訊息「 Warning: annotation “kubernetes.io/ingress.class” is deprecated, please use ‘spec.ingressClassName’ instead」,是因為 Kubernetes 本身推薦使用新的 spec.ingressClassName,但 GKE 的官方文件卻說要用舊的註解方式。

在這裡以 GKE 的官方文件為主,不用理會該訊息。

執行部署 GKE Ingress 物件

接下來需要等待至少 5~10 分鐘的時間,如果設定正確,就能夠在 Ingress 的地方看到一個前端的 IP,點擊之後就能看到網頁。

Ingress 建立完成並看到網頁正常顯示

也能在負載平衡頁面看到 ALB,代表它能夠處理 HTTP/HTTPS 通訊協定的內容,提供更豐富的路由功能。

也能在負載平衡頁面看到 ALB

恭喜你也把 GKE 的基本服務建立完成了,接下來還是要記得刪除相關服務喔!

逐步刪除 GKE 物件

下 kubectl 指令刪除 GKE 物件

你可以按照以下的順序刪除:

查詢 Ingress 名稱

kubectl get ingress

刪除 Ingress (執行後要等 3~5 分鐘刪除完畢)

kubectl delete ingress-1 

查詢 Service 名稱

kubectl get service

刪除 Service  (名稱為 kubernetes 的 Service 不用刪除)

kubectl delete service deployment-1-service

查詢 Deployment 名稱

kubectl get deployment

刪除 Deployment

kubectl delete deployment deployment-1

刪除 GKE Cluster 上各個物件

直接刪除整個 GKE Cluster

再用這個指令刪除整個 Cluster,其實你也可以跳過前面刪除物件的步驟,直接刪除 Cluster:

gcloud container clusters delete autopilot-cluster-1 –region asia-east1

使用 gcloud 指令刪除 GKE Cluster

或是更簡單的方法,直接在 Web Console 上刪除整個 Cluster, Cluster 裡所有物件也都會跟著被刪除掉。

在 Web Console 上刪除 GKE Cluster

最後要跟各位提醒,Kubernetes 本身是一個博大精深的領域,本文礙於篇幅只能介紹到這裡,如果需要深入鑽研,建議各位再去尋找專門的書籍或文件來看。而且 Kubernetes 本身不斷在更新,GKE 也持續更新,所以現在看到可以運作的樣子,也許過不久後又會改變,所以還請大家持續追蹤 GCP 官方文件喔!

影片版教學如下:

Table of Contents
返回頂端