Kubernetes 入門:Pod、Service、Deployment

當你的應用只是一個簡單的 Docker 容器時,用 Docker Compose 來管理就已經足夠了。但當你的系統擴展到以下規模時,Docker Compose 就會開始顯得力不從心:

  • 你的應用需要自動伸縮(流量高時自動增加副本,流量低時減少)
  • 某個容器 crash 了,需要自動重新啟動
  • 你需要在不中斷服務的情況下更新版本(滾動更新)
  • 你需要將多個容器平均分配到不同的伺服器上(負載平衡)
  • 你的服務散落在多台雲端主機上,需要統一管理

這時候,我們就需要 Kubernetes (K8s) 登場了。

什麼是 Kubernetes?

Kubernetes 是一個容器編排平台 (Container Orchestration Platform),由 Google 基於其內部使用多年的 Borg 系統開源而來,現在由 Cloud Native Computing Foundation (CNCF) 維護。

簡單來說,Kubernetes 就是你整個應用的「作業系統」:

  • Docker 容器就像是「應用程式
  • Kubernetes 就像是「作業系統」,負責管理這些應用程式的啟動、監控、資源分配與溝通

Kubernetes 的優勢

| 功能 | 說明 | |------|------| | 自動修復 | 當某個容器 crash,K8s 自動重新啟動 | | 自動伸縮 | 根據 CPU 或記憶體使用量,自動增減容器數量 | | 滾動更新 | 更新版本時逐步替換,不中斷服務 | | 服務發現 | 自動為每個服務分配 DNS 名稱,容器間可直接透過名稱溝通 | | 負載平衡 | 自動將流量分配到多個容器副本 | | 儲存編排 | 自動掛載雲端硬碟、本地儲存等 | | 自我修復 | 如果某個節點 (Node) 掛了,自動在其他節點重新排程 |

Kubernetes 的三大核心物件

在 Kubernetes 中,一切都是「物件 (Object)」。你透過撰寫 YAML 或 JSON 來宣告你想要的狀態,然後 K8s 會努力讓現實狀態符合你的宣告。

1. Pod(最小的部署單元)

Pod 是 Kubernetes 中最小的可部署單元。一個 Pod 裡面可以包含一個或多個容器(通常是一個)。

你可以把 Pod 想像成「一艘太空船」:

  • 太空船裡面可以有一個或多個太空人(容器)
  • 每個太空人各自執行不同的任務
  • 他們共享太空船的生命週期與資源
  • 太空船被摧毀時,所有太空人同時消失

Pod 的 YAML 範例:

apiVersion: v1
kind: Pod
metadata:
  name: my-app-pod
  labels:
    app: my-app
    version: v1
spec:
  containers:
    - name: my-app
      image: my-app:latest
      ports:
        - containerPort: 3000
      resources:
        requests:
          cpu: "250m"        # 最少保證 0.25 核心
          memory: "256Mi"     # 最少保證 256 MB
        limits:
          cpu: "500m"        # 最多使用 0.5 核心
          memory: "512Mi"     # 最多使用 512 MB

但 Pod 有一個重要的特性:Pod 是臨時性的 (Ephemeral)。如果你刪除了一個 Pod,它不會自動重現。這就是為什麼我們通常不會直接建立 Pod,而是透過更高層的抽象來管理它們。

2. Deployment(宣告期望狀態)

Deployment 是 Kubernetes 中最常用的控制器。它定義了你期望的「副本數量」與「更新策略」,K8s 會自動確保實際運行的 Pod 數量符合你的期望。

Deployment 的 YAML 範例:

apiVersion: apps/v1
kind: Deployment
metadata:
  name: my-app-deployment
spec:
  replicas: 3              # 期望 3 個副本
  selector:
    matchLabels:
      app: my-app
  template:                # Pod 模板
    metadata:
      labels:
        app: my-app
    spec:
      containers:
        - name: my-app
          image: my-app:v2
          ports:
            - containerPort: 3000
          livenessProbe:    # 存活檢查:如果失敗則重新啟動
            httpGet:
              path: /api/health
              port: 3000
            initialDelaySeconds: 10
            periodSeconds: 15
          readinessProbe:   # 就緒檢查:如果失敗則不導入流量
            httpGet:
              path: /api/ready
              port: 3000
            initialDelaySeconds: 5
            periodSeconds: 10

Deployment 的關鍵能力:

滾動更新 (Rolling Update) 當你將 Image 版本從 v1 更新到 v2 時,K8s 會逐步替換 Pod:

  1. 建立一個 v2 的 Pod
  2. 等待 v2 的 Pod 通過 Readiness Probe(就緒檢查)
  3. 刪除一個 v1 的 Pod
  4. 重複直到所有 Pod 都被替換

這確保了更新過程中服務完全不會中斷

自動復原 (Rollback) 如果 v2 版本出了問題(例如 Liveness Probe 失敗),K8s 會自動停止滾動,保留 v1 版本:

# 查看 Deployment 的更新歷史
kubectl rollout history deployment/my-app-deployment

# 回滾到上一個版本
kubectl rollout undo deployment/my-app-deployment

3. Service(穩定的存取入口)

Pod 是動態的,它可能因為節點故障而被重新排程到不同的伺服器,IP 位址也會隨之改變。如果我們直接使用 Pod 的 IP 來連線,只要 Pod 重啟或漂移,連線就會中斷。

Service 提供了一個穩定的虛擬 IP (ClusterIP) 與 DNS 名稱,作為後端 Pod 的存取入口。

Service 的 YAML 範例:

apiVersion: v1
kind: Service
metadata:
  name: my-app-service
spec:
  selector:
    app: my-app              # 選擇所有 label 為 app: my-app 的 Pod
  ports:
    - protocol: TCP
      port: 80               # Service 對外開放的埠
      targetPort: 3000       # 轉發到 Pod 的 3000 埠
  type: ClusterIP            # 只在叢集內部可存取

Service 的四種類型:

| 類型 | 說明 | 使用場景 | |------|------|---------| | ClusterIP | 只在叢集內部可存取,分配一個虛擬 IP | 內部服務(資料庫、API) | | NodePort | 在所有節點上開啟一個隨機埠,外部可透過節點 IP 存取 | 開發測試 | | LoadBalancer | 自動建立雲端負載平衡器,分配外部 IP | 正式環境(搭配雲端服務商) | | Ingress | 七層 HTTP 路由,根據域名或路徑轉發到不同 Service | 生產環境的對外入口 |

在本機建立 Kubernetes 測試叢集

在正式購買雲端 K8s 叢集之前,我們可以用 kind (Kubernetes in Docker) 來在本機建立一個測試用的 K8s 環境。

安裝 kind

# macOS (Homebrew)
brew install kind

# 驗證安裝
kind version

建立一個叢集

kind create cluster --name my-test-cluster

輸出範例:

Creating cluster "my-test-cluster" ...
 ✓ Ensuring node image (kindest/node:v1.28.0) 🖼
 ✓ Preparing nodes 📦
 ✓ Writing configuration 📜
 ✓ Starting control-plane 🕹️
 ✓ Installing CNI 🔌
 ✓ Installing StorageClass 💾
Set kubectl context to "kind-my-test-cluster"
You can now use your cluster with:

kubectl cluster-info --context kind-my-test-cluster

驗證叢集狀態

# 檢視節點
kubectl get nodes

# 檢視系統 Pod
kubectl get pods -n kube-system

# 取得叢集資訊
kubectl cluster-info

部署你的第一個應用

現在,讓我們用剛才學到的 Deployment 與 Service,將我們之前 Docker 化的應用部署到 K8s 上:

# 部署應用(建立 Deployment)
kubectl apply -f deployment.yaml

# 暴露服務(建立 Service)
kubectl apply -f service.yaml

# 查看 Pod 狀態
kubectl get pods -w

# 查看 Service
kubectl get svc

[!TIP] 在 kind 中,由於不是雲端環境,LoadBalancer 類型的 Service 不會自動分配外部 IP。你可以使用 kubectl port-forward 來將叢集內的服務轉發到本機: kubectl port-forward service/my-app-service 3000:80

本日總結

在本章中,你學到了:

  1. Kubernetes 是什麼:一個容器編排平台,管理容器叢集的生命週期
  2. Pod:最小的部署單元,運行一個或多個容器
  3. Deployment:宣告期望狀態,管理 Pod 的滾動更新與伸縮
  4. Service:提供穩定的存取入口,支援 ClusterIP/NodePort/LoadBalancer/Ingress
  5. kind 本地叢集:在本機用 Docker 建立 K8s 測試環境
  6. kubectl 基本操作:get、apply、port-forward、rollout

下一章,我們將真正把一個完整的應用部署到雲端 Kubernetes 叢集上!

解鎖完整教學內容

本章為付費內容。加入專案即可解鎖超過 5000 字的深度解析,包含 10 個以上神級 Prompt 與真實 Source Code 範例!