Mark Ku's Blog

前言

先前有透過 Cloud Run 運行容器應用,也有試著在地端架了Kubernetes,這篇來談 GKS (google kubernetes engine),目前市面上的雲服務,都是基於 Kubernetes 的雲端架構服務,如:AWS、AKS、GKE,因此 Kubernetes的基礎知識就顯得很重要,但Kubernetes 的官方文件也真的很多東西,只好邊實作邊學習。

順便比較一下 Cloud Run vs Google Kubernetes Engine

  • Google Cloud Run:適合單一容器應用,簡單快速部署,適合小型應用、API、微服務等。
  • Google Kubernetes Engine:提供叢集和高可用性支持,適合需要多容器協作、具備自動擴展和高容錯的應用場景。

預先準備

  1. 確保本地已安裝 Docker 和 Google Cloud CLI。
  2. 啟用 GCP 的 Kubernetes API。 enable kubernetes api
  3. 在 GCP 中建立 Google Artifact Registry。
  4. Google Cloud CLI 登入及設定好專案。
gcloud projects list
gcloud config set project [PROJECT_ID]
  1. gcloud 安裝 kubectl 元件
gcloud components install kubectl  gke-gcloud-auth-plugin
gcloud components update

首先,初始化 Next.js 專案

npx create-next-app@latest nextjs-blog --use-npm --example "https://github.com/vercel/next-learn/tree/main/basics/learn-starter"
cd nextjs-blog

接著,複製官方範例的 Dockerfile 和 next.config.js 到專案根目錄

建置與推送 Docker 映像檔到 Google Artifact Registry

docker build -t asia-east1-docker.pkg.dev/gcr-my-project01/my-registry/blog:v2 .
docker run -d -p 8888:80 asia-east1-docker.pkg.dev/gcr-my-project01/my-registry/blog:v2
docker push asia-east1-docker.pkg.dev/gcr-my-project01/my-registry/blog:v2

建立 Kubernetes Clusters

Google 的 Clusters 有兩種模式

  • Standard Cluster:

    • 需手動設定節點資源和管理叢集,提供更高的靈活性。
    • 使用者可進行更深入的自訂控制,但管理負擔較高。
    • 適合需要細節控制和自訂設定的使用者。
  • Autopilot Cluster:

    • 自動管理基礎設施,使用者只需專注於應用部署和工作負載。
    • 系統會根據需求自動調整資源,並按使用量計費。
    • 適合希望簡化管理的工作,無需手動設定節點。

可以使用網頁或腳本指令建立 Kubernetes clusters。

Kubernetes Engine > Cluster > Create

create cluster
create cluster

使用腳本指令建立Cluster

** 標準叢集 (Standard Cluster)**

gcloud container clusters create blog-cluster --num-nodes 2 --machine-type n1-standard-1 --zone asia-east1-a

** 自動叢集(Autopilot Cluster)**

gcloud container clusters create-auto blog-autopilot-cluster --region asia-east1

部署應用

使用網頁部署容器

  1. 回到 GCP 後台,選擇 Kubernetes Engine > Workloads > Deploy。
  2. 設定伺服器節點與部署名稱。 deployment by web ui
  3. 選擇先前上傳的 Google Artifact Registry 映像檔。 select docker image
  4. 設定內外部連接埠。 change mapping port
  5. 可以查看 YAML 設定,Close 後,點擊 Deploy。 check yaml file

使用腳本指令部署

連線至叢集:從 Cloud Shell 使用 kubectl 操作。

use kubectl in cloud shell 可從 CloudShell 執行kubectl腳本指令,或複製連線指令到地端執行這個連線 use kubectl in cloud shell

kubectl get nodes
kubectl get nodes in cloud shell
kubectl get nodes in cloud shell

建立 Deployment

vim nextjs-blog-deployment.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
  name: nextjs-blog
  labels:
    app: nextjs-blog
spec:
  selector:
    matchLabels:
      app: nextjs-blog
      tier: web
  template:
    metadata:
      labels:
        app: nextjs-blog
        tier: web
    spec:
      containers:
      - name: nextjs-blog-app
        image: asia-east1-docker.pkg.dev/gcr-my-project01/my-registry/blog:v2
        ports:
        - containerPort: 3000

運行應用:

kubectl apply -f nextjs-blog-deployment.yaml
kubectl get deploy nextjs-blog

網路設定 - Load Balancer

  • 自動建立外部服務、 Load Balancer 設定、挷定外部 IP
kubectl expose deployment nextjs-blog-deployment --type="LoadBalancer"
  • 或也可以指定連接埠的方式建立*
kubectl expose deployment nextjs-blog-deployment --name=nextjs-blog-service --port=80 --target-port=3000 --type=LoadBalancer

指定連接埠相關文件

部署完成後訪問服務

點選服務進行訪問。 deployment finish 訪問 Next.js 網站: check accessible

若需要額外的連接埠映射,也可使用下方Expose 按鈕:

manual expose
manual expose

補充 - 在 Kubernetes 中,要更新的映像檔,通常可以使用以下幾種方法

1. 使用 kubectl set image 更新映像檔

這種方式適合快速更新映像檔版本:

kubectl set image deployment/<deployment-name> <container-name>=<new-image>:<new-tag>

例如:

kubectl set image deployment/my-app my-container=my-app-image:v2

2. 更新 Deployment YAML 文件並重新應用

如果管理配置是基於 YAML 文件,您可以更新文件中的映像檔標籤,然後重新應用該文件:

# my-app-deployment.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
  name: my-app
spec:
  replicas: 3
  template:
    spec:
      containers:
      - name: my-container
        image: my-app-image:v2  # 更新映像檔標籤

重新應用更新過的 YAML 文件:

kubectl apply -f my-app-deployment.yaml

3. 使用 kubectl rollout restart 重新啟動 Deployment

如果映像檔標籤已經更新(例如,如果您用相同標籤推送了一個新版本),可以使用重新啟動來強制刷新:

kubectl rollout restart deployment/<deployment-name>

4. 使用 kubectl patch 更新映像檔

這種方式可以直接通過命令行進行部分更新:

kubectl patch deployment <deployment-name> -p '{"spec":{"template":{"spec":{"containers":[{"name":"<container-name>","image":"<new-image>:<new-tag>"}]}}}}'

例如:

kubectl patch deployment my-app -p '{"spec":{"template":{"spec":{"containers":[{"name":"my-container","image":"my-app-image:v2"}]}}}}'

驗證更新

無論採用哪種方法,可以使用以下命令來檢查更新是否成功:

kubectl rollout status deployment/<deployment-name>

這些方法都會觸發滾動更新,以保持服務不中斷的情況下逐步替換舊版本的容器。

補充 - Next js 如果要支援多台伺服器時,要額外設定generateBuildId,確保每個應用都拿到一致性的檔案。

/_next/static/<build-ID>/<static-file>

參考資料

How to deploy NextJS app to Kubernetes Cluster in GCP with Custom Domain?

作者

Mark Ku

擁有 10+ 年經驗的資深軟體工程師,現為 AI 應用 Builder,專注於大型平台架構與簡化複雜系統設計,從電商系統到訂閱與收費平台,結合 AI Agent、AI 整合與自動化開發,打造高效率且可持續演進的產品技術基礎。閱讀更多

覺得這篇有幫助?

作者做的免費工具、每日 Podcast 與電子報,都在這裡。

Mark Ku · 本文採用 CC BY 4.0 授權,轉載請註明作者並附上原文連結。

留言

訂閱電子報

訂閱後即時收到新文章通知,不錯過任何技術分享。

提交即表示同意接收電子報,隨時可

熱門文章

View all
Mark Ku
··597

Oracle Cloud 永久免費方案 Linux 主機及固定 IP :0 元打造雲端解決方案

Oracle Cloud 永久免費方案 Linux 主機及固定 IP :0 元打造雲端解決方案
Mark Ku
··469

告別 Postman 收費陷阱!開源 Git 原生 API 測試神器 Bruno 實戰指南

告別 Postman 收費陷阱!開源 Git 原生 API 測試神器 Bruno 實戰指南
Mark Ku
··327

一款免費開源類似於 Notion 類知識庫系統 — Outline Wiki 佈署與備份全攻略

一款免費開源類似於 Notion 類知識庫系統 — Outline Wiki 佈署與備份全攻略
Mark Ku
··239

打造高效 API 管理平台:從 0 開始部署 Kong Gateway - Part 1

打造高效 API 管理平台:從 0 開始部署 Kong Gateway - Part 1
Mark Ku
··233

訓練自己的 AI 語音:硬體門檻、開源模型比較與 LoRA 微調

訓練自己的 AI 語音:硬體門檻、開源模型比較與 LoRA 微調
Mark Ku
··220

在 Ubuntu 上設置 Samba 來共享資料夾,讓 Windows 11 用戶可以存取

在 Ubuntu 上設置 Samba 來共享資料夾,讓 Windows 11 用戶可以存取