---
title: "用 Helm 佈署應用：為什麼選 Helm 佈署Kubernetes 容器應用、怎麼裝、和純 YAML 的差異"
description: "以實務角度整理 Helm 的價值、安裝方式、與 Deployment YAML 的差異，並提供官方/社群 Chart 來源與下載範例。"
canonical_url: "https://blog.markkulab.net/post/helm-chart-deploy"
author: "Mark Ku"
author_url: "https://blog.markkulab.net/author/mark-ku"
site: "Mark Ku's Blog"
date_published: "2025-09-24 09:00:00 +0800"
category: "DevOps"
tags: ["kubernetes", "helm", "devops", "chart", "artifact hub", "bitnami", "ci/cd"]
language: "zh-TW"
license: "CC BY 4.0"
license_url: "https://creativecommons.org/licenses/by/4.0/"
attribution: "轉載或引用請註明作者並附上原文連結"
---

# 用 Helm 佈署應用：為什麼選 Helm 佈署Kubernetes 容器應用、怎麼裝、和純 YAML 的差異

## 前言

在容器化技術的演進過程中，我們經歷了從 Docker 到 Kubernetes 的轉變：

**Docker 時代**：
- 學習曲線相對平緩，一個 `docker run` 就能啟動應用
- 單一容器，配置簡單，容易理解
- 適合小型專案和個人開發

**Kubernetes 時代**：
- 功能強大，但學習曲線陡峭
- 需要管理多種資源（Pod、Service、Deployment、Ingress 等）
- 檔案數量爆炸式增長，維護成本高
- 但提供了企業級的擴展性、高可用性和自動化能力

**Helm 的出現**：
- 讓 Kubernetes 的複雜性變得可管理
- 就像 Docker 讓容器變得簡單一樣，Helm 讓 K8s 部署變得簡單
- 一個 Chart 就能管理整個應用的生命週期
- 抽換方便，版本管理清晰，回滾容易

**但 Helm 也帶來了新的挑戰**：
- 配置數量變得更多：除了原本的 YAML，還要學習 Chart 結構、values.yaml、模板語法
- 學習曲線又更高了：需要理解 Go template、Helm 指令、Chart 生態圈
- 初學者可能覺得 Helm 比純 YAML 更複雜
- 但一旦掌握，維護及遷移成本會是比較低的。

## 什麼是 Helm？為什麼需要它？

想像你要在 Kubernetes 上部署一個完整的 Web 應用，你需要：
- Deployment（Pod 管理）
- Service（網路服務）
- Ingress（外部存取）
- ConfigMap（設定檔）
- Secret（密碼）

如果每個環境（開發、測試、正式）都要手動寫這些 YAML，你會發現：

❌ **問題一：檔案爆炸**
- 開發環境：5 個 YAML 檔案
- 測試環境：5 個 YAML 檔案  
- 正式環境：5 個 YAML 檔案
- 總共 15 個檔案要維護！

❌ **問題二：參數混亂**
- 開發用 `nginx:1.20`，正式用 `nginx:1.21`
- 開發 1 個副本，正式 3 個副本
- 每次改版都要手動修改一堆檔案

❌ **問題三：版本管理困難**
- 出問題時不知道要回滾到哪個版本
- 沒有清楚的部署歷史記錄

## Helm 如何解決這些問題？

Helm 就像 Kubernetes 的「套件管理器」，把多個 YAML 檔案打包成一個「Chart」：

✅ **一個 Chart 搞定所有環境**
- 用 `values.yaml` 控制不同環境的參數
- 開發環境：`helm install my-app ./my-chart -f dev-values.yaml`
- 正式環境：`helm install my-app ./my-chart -f prod-values.yaml`

✅ **版本管理與回滾**
- 每次部署都有版本號（REVISION 1, 2, 3...）
- 出問題時：`helm rollback my-app 2` 立即回滾

✅ **豐富的生態圈**
- 不用自己寫 Chart，直接使用現成的（MySQL、Redis、Nginx 等）
- 就像手機的 App Store，有數千個現成的應用

> **簡單說：** Helm 讓你在 K8s 上部署應用就像安裝手機 App 一樣簡單！

## Helm 是怎麼運作的？

### 1. Chart 就像一個「應用包」

```
my-web-app/
├── Chart.yaml          # 應用資訊（名稱、版本）
├── values.yaml         # 預設設定
├── templates/          # YAML 模板
│   ├── deployment.yaml
│   ├── service.yaml
│   └── ingress.yaml
└── charts/             # 其他依賴的應用
```

### 2. 模板 + 設定 = 最終的 YAML

**模板檔案（templates/deployment.yaml）：**
```yaml
apiVersion: apps/v1
kind: Deployment
metadata:
  name: {{ .Values.app.name }}    # 這裡會被替換
spec:
  replicas: {{ .Values.replicas }} # 這裡會被替換
  template:
    spec:
      containers:
      - name: {{ .Values.app.name }}
        image: {{ .Values.image }}:{{ .Values.tag }}
```

**設定檔案（values.yaml）：**
```yaml
app:
  name: "my-web-app"
replicas: 3
image: "nginx"
tag: "1.21"
```

**最終產生的 YAML：**
```yaml
apiVersion: apps/v1
kind: Deployment
metadata:
  name: my-web-app
spec:
  replicas: 3
  template:
    spec:
      containers:
      - name: my-web-app
        image: nginx:1.21
```

### 3. 不同環境用不同設定檔

**開發環境（dev-values.yaml）：**
```yaml
replicas: 1
image: "nginx"
tag: "1.20"
```

**正式環境（prod-values.yaml）：**
```yaml
replicas: 3
image: "nginx"
tag: "1.21"
```

## 實際操作：5 分鐘部署 Elasticsearch

### 步驟 1：安裝 Helm
```bash
# macOS
brew install helm

# Linux
curl https://raw.githubusercontent.com/helm/helm/main/scripts/get-helm-3 | bash

# Windows
choco install kubernetes-helm
```

### 步驟 2：加入 Elastic 的應用商店
```bash
helm repo add elastic https://helm.elastic.co
helm repo update
```

### 步驟 3：一鍵安裝 Elasticsearch
```bash
helm install elasticsearch elastic/elasticsearch
```

就這樣！Elasticsearch 開始部署了。

### 步驟 4：查看部署狀態
```bash
# 查看所有已安裝的應用
helm list

# 查看 Elasticsearch 的詳細狀態
helm status elasticsearch

# 查看部署歷史
helm history elasticsearch
```

### 步驟 5：升級或回滾
```bash
# 升級到新版本
helm upgrade elasticsearch elastic/elasticsearch --set imageTag=8.5.0

# 如果出問題，回滾到上一個版本
helm rollback elasticsearch
```

## Helm vs 純 YAML：實際比較

### 用純 YAML 部署 Nginx

**deployment.yaml：**
```yaml
apiVersion: apps/v1
kind: Deployment
metadata:
  name: nginx-dev
spec:
  replicas: 1
  template:
    spec:
      containers:
      - name: nginx
        image: nginx:1.20
```

**service.yaml：**
```yaml
apiVersion: v1
kind: Service
metadata:
  name: nginx-dev-service
spec:
  selector:
    app: nginx-dev
  ports:
  - port: 80
```

**正式環境還要再寫一套類似的檔案...**

### 用 Helm 部署 Nginx

**一個命令搞定：**
```bash
# 開發環境
helm install nginx bitnami/nginx --set replicaCount=1,imageTag=1.20

# 正式環境  
helm install nginx bitnami/nginx --set replicaCount=3,imageTag=1.21
```

**差異對比：**

| 項目 | 純 YAML | Helm |
|------|---------|------|
| 檔案數量 | 環境數 × 資源數 | 1 個 Chart |
| 參數管理 | 手動修改每個檔案 | 統一 values.yaml |
| 版本控制 | 手動記錄 | 自動版本管理 |
| 回滾 | 手動重建 | `helm rollback` |
| 生態圈 | 自己寫 | 數千個現成 Chart |

## 常用的 Helm 指令

```bash
# 基本操作
helm list                    # 查看已安裝的應用
helm status <app-name>       # 查看應用狀態
helm history <app-name>      # 查看部署歷史

# 安裝與升級
helm install <name> <chart>   # 安裝應用
helm upgrade <name> <chart>  # 升級應用
helm uninstall <name>        # 刪除應用

# 回滾
helm rollback <name> <revision>  # 回滾到指定版本
helm rollback <name>             # 回滾到上一個版本

# 查看與下載
helm search repo <keyword>   # 搜尋可用的 Chart
helm pull <chart>            # 下載 Chart 到本地
helm template <chart>        # 預覽會產生的 YAML
```

## Helm Rollback 是怎麼實作的？

很多人好奇 `helm rollback` 是如何快速回滾的，其實背後的原理並不複雜：

### Release 與 Revision 機制

每次執行 `helm install` 或 `helm upgrade`，Helm 都會建立一個 **Release**，並記錄版本號（Revision）：

```bash
# 查看部署歷史
helm history my-app

# 輸出範例：
REVISION    STATUS      CHART           DESCRIPTION
1           superseded  my-app-1.0.0    Install complete
2           superseded  my-app-1.0.1    Upgrade complete
3           deployed    my-app-1.0.2    Upgrade complete
```

### 歷史資料儲存在哪裡？

Helm 會把每個 Revision 的完整資訊儲存在 Kubernetes 的 **Secret** 中：

```bash
# 查看 Helm 建立的 Secret
kubectl get secrets -l owner=helm

# 輸出範例：
NAME                          TYPE                 DATA
sh.helm.release.v1.my-app.v1  helm.sh/release.v1   1
sh.helm.release.v1.my-app.v2  helm.sh/release.v1   1
sh.helm.release.v1.my-app.v3  helm.sh/release.v1   1
```

每個 Secret 包含：
- **Chart 模板**：當時使用的所有 YAML 模板
- **Values**：當時使用的設定值
- **Manifest**：最終產生的 Kubernetes 資源 YAML
- **Metadata**：版本號、狀態、時間戳記等

### Rollback 的運作流程

當你執行 `helm rollback my-app 2` 時，Helm 會：

```
┌─────────────────────────────────────────────────────────┐
│  1. 讀取目標版本                                          │
│     從 Secret sh.helm.release.v1.my-app.v2 取出資料      │
└─────────────────────────────────────────────────────────┘
                          ↓
┌─────────────────────────────────────────────────────────┐
│  2. 解壓縮並解碼                                          │
│     Secret 內容是 base64 + gzip 壓縮的                   │
└─────────────────────────────────────────────────────────┘
                          ↓
┌─────────────────────────────────────────────────────────┐
│  3. 取得舊版 Manifest                                     │
│     獲得當時產生的完整 Kubernetes YAML                    │
└─────────────────────────────────────────────────────────┘
                          ↓
┌─────────────────────────────────────────────────────────┐
│  4. 執行三方合併（Three-way Merge）                       │
│     比對：舊版 Manifest vs 現有狀態 vs 目標版本           │
└─────────────────────────────────────────────────────────┘
                          ↓
┌─────────────────────────────────────────────────────────┐
│  5. 套用變更                                              │
│     透過 kubectl apply 將資源更新到目標狀態               │
└─────────────────────────────────────────────────────────┘
                          ↓
┌─────────────────────────────────────────────────────────┐
│  6. 建立新的 Revision                                     │
│     Rollback 本身也會建立一個新版本（如 v4）              │
└─────────────────────────────────────────────────────────┘
```

### 實際範例：查看 Secret 內容

```bash
# 取得特定版本的 Release 資料
kubectl get secret sh.helm.release.v1.my-app.v2 -o jsonpath='{.data.release}' | base64 -d | gunzip

# 會輸出 JSON 格式的完整 Release 資訊，包含：
# - chart: Chart 的完整內容
# - config: 當時的 values
# - manifest: 產生的 YAML
# - version: 版本號
```

### 為什麼 Rollback 這麼快？

1. **不需要重新下載 Chart**：所有資料都存在 Secret 裡
2. **不需要重新渲染模板**：Manifest 已經預先產生好
3. **只更新有差異的資源**：透過三方合併，只處理真正需要改變的部分

### 注意事項

⚠️ **Secret 有大小限制**：Kubernetes Secret 預設最大 1MB，如果 Chart 很大可能會有問題

⚠️ **歷史版本會累積**：預設保留 10 個版本，可透過 `--history-max` 調整：
```bash
helm upgrade my-app ./my-chart --history-max 5
```

⚠️ **Rollback 不會還原資料**：只會還原 Kubernetes 資源設定，資料庫等持久化資料不會回滾

### 與 Kubernetes 原生 Rollback 的差異

| 項目 | Helm Rollback | kubectl rollout undo |
|------|---------------|----------------------|
| 範圍 | 整個 Release（多個資源） | 單一 Deployment |
| 歷史儲存 | Kubernetes Secret | ReplicaSet |
| 設定還原 | 完整還原（含 values） | 只還原 Pod 模板 |
| ConfigMap/Secret | ✅ 會還原 | ❌ 不會還原 |

### Helm 版本號與 Git 的關係

很多人會問：「Helm 的 Revision 和 Git commit 有什麼關係？」

**答案是：兩者是完全獨立的系統，沒有直接關聯。**

```
┌─────────────────────────────────────────────────────────────────┐
│                        兩套獨立的版本系統                         │
├─────────────────────────────────────────────────────────────────┤
│                                                                 │
│   Git（原始碼版本控制）          Helm（部署版本控制）              │
│   ├── commit abc123             ├── Revision 1                 │
│   ├── commit def456             ├── Revision 2                 │
│   ├── commit ghi789             ├── Revision 3                 │
│   └── 儲存在 Git Repository      └── 儲存在 K8s Secret          │
│                                                                 │
└─────────────────────────────────────────────────────────────────┘
```

**它們追蹤的東西不同：**

| 項目 | Git | Helm Revision |
|------|-----|---------------|
| 追蹤對象 | 原始碼變更 | 部署狀態變更 |
| 儲存位置 | Git Repository | Kubernetes Secret |
| 版本格式 | SHA hash（如 `abc123`） | 遞增數字（1, 2, 3...） |
| 回滾影響 | 程式碼回到過去 | K8s 資源回到過去 |

**為什麼會獨立？**

1. **部署不一定對應程式碼變更**
   - 你可能只改了 `replicas: 3` → `replicas: 5`（沒有程式碼變更）
   - 這時 Helm 會有新 Revision，但 Git 沒有新 commit

2. **一次 commit 可能多次部署**
   - 同一個版本的程式碼，可能部署到 dev、staging、prod
   - 每次部署都是新的 Helm Revision

3. **部署可能失敗重試**
   - 同一個 commit 可能因為設定調整而部署多次

**實務上如何關聯？**

雖然兩者獨立，但在 CI/CD 流程中，我們通常會透過 **標籤（Label）或註解（Annotation）** 來關聯：

```yaml
# 在 values.yaml 或部署時加入 Git 資訊
metadata:
  annotations:
    git.commit: "abc123def"
    git.branch: "main"
    git.repo: "github.com/myorg/myapp"
```

**部署時帶入 Git 資訊：**
```bash
# 在 CI/CD 中自動帶入 Git commit
helm upgrade my-app ./chart \
  --set gitCommit=$(git rev-parse --short HEAD) \
  --set gitBranch=$(git branch --show-current)
```

**這樣做的好處：**
- 出問題時可以快速對應到是哪個 commit 造成的
- 方便追蹤「這個部署對應哪個版本的程式碼」
- 但 Rollback 還是只能用 Helm Revision，不能用 Git commit

> **總結：** Helm 透過把每個版本的完整資訊存在 Secret 中，實現了快速且完整的回滾機制。這也是為什麼 Helm 比手動管理 YAML 更可靠的原因之一。

## 哪裡可以找到現成的 Chart？

### 1. Artifact Hub（最推薦）
- 網址：https://artifacthub.io/
- 就像 Helm 的「App Store」
- 有數千個現成的應用可以直接使用

### 2. Bitnami Charts（品質很高）
- 網址：https://charts.bitnami.com/bitnami
- VMware 維護，品質穩定
- 包含 MySQL、Redis、Kafka 等常用服務

### 3. 官方 Charts
- Elastic：https://helm.elastic.co
- Grafana：https://grafana.github.io/helm-charts
- Prometheus：https://prometheus-community.github.io/helm-charts

### 如何選擇好的 Chart？

1. **看維護狀況**：最近 6 個月有更新
2. **看下載量**：下載量高的通常比較穩定
3. **看文件**：有完整的使用說明
4. **看社群**：GitHub 上有活躍的討論

## 實務建議

### 1. 從簡單開始
- 先試用現成的 Chart（如 Nginx、Redis）
- 熟悉後再考慮自建 Chart

### 2. 環境分離
- 開發、測試、正式環境用不同的 values.yaml
- 不要直接修改 Chart 的原始檔案

### 3. 版本控制
- 把 values.yaml 放到 Git 管理
- 每次部署都記錄版本號

### 4. 備份重要資料
- 資料庫等重要服務要定期備份
- Helm 只管理應用部署，不負責資料備份

## 常見問題

**Q: Helm 會影響現有的 Kubernetes 資源嗎？**
A: 不會。Helm 只是管理工具，不會影響已經存在的資源。

**Q: 可以同時使用 Helm 和 kubectl 嗎？**
A: 可以。Helm 最終還是透過 kubectl 與 Kubernetes 互動。

**Q: 如果 Chart 出問題怎麼辦？**
A: 用 `helm rollback` 回滾，或 `helm uninstall` 刪除後重新安裝。

**Q: 自建 Chart 很複雜嗎？**
A: 一開始可能有點複雜，但熟悉後會比手寫 YAML 簡單很多。

## 總結

Helm 讓 Kubernetes 應用部署變得：
- **更簡單**：一個命令部署複雜應用
- **更安全**：版本管理與快速回滾
- **更高效**：重用現成的 Chart，不用重複造輪子

如果你還在手寫一堆 YAML 檔案，建議試試 Helm，會發現新世界！

## 參考資源

- [Artifact Hub](https://artifacthub.io/) - Helm Chart 搜尋平台
- [Bitnami Charts](https://charts.bitnami.com/bitnami) - 高品質 Chart 集合
- [Elastic Helm Charts](https://helm.elastic.co) - Elastic 官方 Charts

---

## 關於本文與作者

本文出自 [Mark Ku's Blog](https://blog.markkulab.net/post/helm-chart-deploy)

授權條款： [CC BY 4.0](https://creativecommons.org/licenses/by/4.0/) — 轉載或引用請註明作者並附上原文連結

### 關於作者

**[Mark Ku](https://blog.markkulab.net/author/mark-ku)** — Software Solution Provider

- 10+ 年資深軟體工程師，現為 AI 應用 Builder
- 專注大型平台架構設計，從北美電商到AI SaaS訂閱收費系統
- 結合 AI Agent 與自動化，打造高效可演進的產品技術基礎

### 作者開發的免費工具

以下工具皆可免費使用：

- [免費 PDF 簽名工具](https://blog.markkulab.net/tools/pdf-sign): 線上 PDF 簽名工具，瀏覽器內完成手繪、打字、上傳簽名，可拖曳放置、縮放、下載。所有處理都在你的裝置完成，檔案不會上傳。
- [VS Code Refactory](https://blog.markkulab.net/tools/refactory): Refactory 是一款 VS Code 重構擴充套件：34 個重構動作、37 條 code smell 檢查、Code Health 儀表板、18 種語言、534 支測試。懂你的專案慣例：介面放哪、DI 註冊寫在哪、'use client' 該不該加；還會用 git 修改頻率 × 複雜度排出「該先修哪個檔案」，並一鍵把壞味道交給你自己電腦上的 Claude Code 修。免費使用，原始碼不離開你的機器。
- [DB-Kit 資料庫管理工具](https://blog.markkulab.net/tools/db-kit): DB-Kit 是一個用 Tauri + Rust + React 打造的輕量跨平台資料庫管理工具，用單一一致的介面同時管理 MySQL、MariaDB、PostgreSQL、SQL Server、Oracle、SQLite、MongoDB、Redis、Kafka、Elasticsearch 與 RabbitMQ 十一種資料來源：連線密碼以 OS keychain 加密、SSH Tunnel、完整 CRUD、視覺化查詢建構器、多結果集同時顯示、跨連線資料傳輸與比對同步、Excel / CSV 匯入匯出、執行計畫視覺化、ER 圖、排程備份、SQL 壓力測試（p50～p99 延遲百分位）、15 條規則的 SQL 審查、Kafka 訊息瀏覽與監控告警；繁中 / 英文雙語介面，內建 AI 助手（自然語言生成 SQL、AI 審查與調校建議）與命令列工具 dbk。免費開源（MIT），提供 Windows / macOS / Linux 安裝檔。
- [VS Code Super Mermaid](https://blog.markkulab.net/tools/super-mermaid): Super Mermaid 是一款 VS Code 擴充套件：開箱即用的漂亮 Mermaid 圖表，自動上色、即時預覽、滑鼠平移縮放、PNG / SVG 高解析匯出，內建 21 種範本與多種主題。免費開源（MIT）。
- [React Super Mermaid](https://blog.markkulab.net/tools/react-super-mermaid): react-super-mermaid 是一個開源 React 元件庫：一行 <MermaidViewer> 即可渲染漂亮的 Mermaid 圖表，內建 colorful / sketch 主題、平移縮放、圖內搜尋、SVG / PNG 高解析匯出。輕量、SSR 安全、完整 TypeScript 型別。免費開源（MIT）。
- [Jira / Confluence Super Mermaid](https://blog.markkulab.net/tools/jira-super-mermaid): Atlassian Forge app：在 Jira issue 與 Confluence 內文直接寫 Mermaid 語法，畫流程圖、時序圖、狀態機與甘特圖。11 種圖表、SVG / PNG 匯出、明暗主題、完整中日韓文字支援。取得 Runs on Atlassian 資格：圖表存在你自己的站台，app 不呼叫任何第三方服務。免費，即將上架 Atlassian Marketplace。
- [Mermaid 線上預覽](https://blog.markkulab.net/tools/mermaid-preview): 在瀏覽器裡寫 Mermaid、即時看圖，整張圖表壓進網址就能分享。免註冊、不上傳伺服器，相容 mermaid.live 的分享連結。
- [React Intl Phone Number](https://blog.markkulab.net/tools/react-intl-phone-number): react-intl-phone-number 是一個開源 React 元件：framework-agnostic、不依賴 antd，提供 E.164 進出、可搜尋國旗 / 國碼下拉、可配置驗證等級（strict / mobile-strict / loose）、可主題化 CSS 與 i18n，電話邏輯由 google-libphonenumber 驅動。輕量、完整 TypeScript 型別。免費開源（MIT）。
- [Uptime Kuma Cluster](https://blog.markkulab.net/tools/uptime-kuma-cluster): 把單機版 Uptime Kuma 改造成高可用叢集：OpenResty + Lua 智慧負載平衡、MariaDB 共享狀態、健康檢查與自動 Failover，附叢集管理 REST API，一行 Docker Compose 啟動。免費開源（MIT）。
- [特教專案](https://blog.markkulab.net/education): 為特殊教育學生製作的學習教材

### 每日 Podcast

- [科技新鮮事](https://blog.markkulab.net/category/tech-news): 每日精選 AI 與科技趨勢，透過語音摘要快速掌握最新技術動態，涵蓋 AI 應用、軟體架構、DevOps 與工程實戰。 — RSS: https://blog.markkulab.net/feed.xml
- [AI股市蝦聊](https://blog.markkulab.net/category/ai-stock-chat): 每個交易日用 AI 分析台股盤勢，以雙人對話聊當天的盤中觀察與隔日預測。 — RSS: https://blog.markkulab.net/ai-stock-chat/feed.xml

### 電子報

[訂閱電子報](https://blog.markkulab.net/subscribe) — 第一時間收到新文章通知，無垃圾信、隨時可取消訂閱。
