為什麼不用其他方案?
| 方案 | 優點 | 缺點 | 適用場景 |
|---|---|---|---|
| Helm Charts(本文) | 標準化、版本控制、可重用 | 學習曲線 | 多服務微服務架構 |
| 純 YAML | 簡單直接 | 重複多、難維護 | 單一服務 |
| Kustomize | 原生支援 | 複雜覆寫較難 | 簡單環境差異 |
| Docker Compose | 開發方便 | 不適合生產環境 | 本地開發 |
前言:微服務部署的挑戰
多通路 OMS 系統包含:
| 服務類型 | 數量 | 說明 |
|---|---|---|
| Consumer Job | 17+ 個 | 每個通路一個 |
| API 服務 | 10+ 個 | 訂單、商品、物流等 |
| Web 前端 | 3 個 | 商戶、管理、OpenAPI |
解決方案:Helm Charts
Chart 目錄結構
└── oms-consumer-shopee/
├── Chart.yaml # Chart 基本資訊
├── values.yaml # 預設變數
├── values-dev.yaml # 開發環境
├── values-prod.yaml # 正式環境
├── config/ # 應用程式配置
│ ├── application.yml
│ └── logback.xml
└── templates/ # K8s 資源模板
├── deployment.yaml
├── service.yaml
└── configmap.yaml
Deployment 設定
apiVersion: apps/v1
kind: Deployment
metadata:
name: {{ .Chart.Name }}
namespace: oms
labels:
app: {{ .Chart.Name }}
spec:
replicas: {{ .Values.replicas }}
selector:
matchLabels:
app: {{ .Chart.Name }}
template:
metadata:
annotations:
# ConfigMap 變更時自動觸發滾動更新
checksum/config: {{ include (print $.Template.BasePath “/configmap.yaml”) . | sha256sum }}
# Prometheus 監控
prometheus.io/scrape: “true”
prometheus.io/path: /metrics
prometheus.io/port: “8080”
labels:
app: {{ .Chart.Name }}
version: {{ .Values.image.version }}
spec:
containers:
– name: {{ .Chart.Name }}
image: “{{ .Values.image.repository }}:{{ .Values.image.version }}”
imagePullPolicy: {{ .Values.image.pullPolicy }}
# 資源限制
resources:
requests:
cpu: {{ .Values.resources.requests.cpu }}
memory: {{ .Values.resources.requests.memory }}
limits:
cpu: {{ .Values.resources.limits.cpu }}
memory: {{ .Values.resources.limits.memory }}
# 健康檢查
livenessProbe:
httpGet:
path: /health/liveness
port: 8080
initialDelaySeconds: 30
periodSeconds: 10
readinessProbe:
httpGet:
path: /health/readiness
port: 8080
initialDelaySeconds: 20
periodSeconds: 5
# 優雅關閉
lifecycle:
preStop:
exec:
command: [“curl”, “-XPOST”, “http://localhost:8080/shutdown”]
values.yaml:環境變數化
replicas: 2
image:
repository: registry.example.com/oms/consumer-shopee
version: latest
pullPolicy: Always
resources:
requests:
cpu: 100m
memory: 256Mi
limits:
cpu: 1000m
memory: 1Gi
replicas: 5
image:
version: v1.2.3
pullPolicy: IfNotPresent
resources:
requests:
cpu: 500m
memory: 512Mi
limits:
cpu: 2000m
memory: 2Gi
部署指令
helm upgrade –install consumer-shopee ./helm/oms-consumer-shopee \
-f values-dev.yaml
# 正式環境
helm upgrade –install consumer-shopee ./helm/oms-consumer-shopee \
-f values-prod.yaml \
–set image.version=v1.2.3
Secret 管理
env:
– name: DB_USERNAME
valueFrom:
secretKeyRef:
name: db-credentials
key: username
– name: DB_PASSWORD
valueFrom:
secretKeyRef:
name: db-credentials
key: password
kubectl create secret generic db-credentials \
–namespace oms \
–from-literal=username=admin \
–from-literal=password=secret123
ConfigMap 管理
apiVersion: v1
kind: ConfigMap
metadata:
name: {{ .Chart.Name }}-config
data:
{{ (.Files.Glob “config/*”).AsConfig | indent 2 }}
config/ 目錄下的檔案會自動打包成 ConfigMap
健康檢查整合
| Probe 類型 | 端點 | 失敗行為 |
|---|---|---|
| liveness | /health/liveness | 重啟 Pod |
| readiness | /health/readiness | 從 Service 移除 |
livenessProbe:
httpGet:
path: /health/liveness
port: 8080
initialDelaySeconds: 30 # 啟動後等待時間
periodSeconds: 10 # 檢查間隔
timeoutSeconds: 5 # 超時時間
failureThreshold: 3 # 失敗幾次後重啟
readinessProbe:
httpGet:
path: /health/readiness
port: 8080
initialDelaySeconds: 20
periodSeconds: 5
failureThreshold: 3
多通路部署策略
17 個通路,每個都有獨立的 Helm Chart:
├── oms-consumer-shopee/
├── oms-consumer-momo/
├── oms-consumer-yahoo/
├── oms-consumer-pchome/
├── oms-consumer-rakuten/
├── oms-consumer-shopify/
├── oms-consumer-shopline/
└── … (共 17 個)
批次部署腳本
CHANNELS=(
“shopee”
“momo”
“yahoo”
“pchome”
“rakuten”
“shopify”
“shopline”
)
VERSION=$1
for channel in “${CHANNELS[@]}”; do
echo “Deploying $channel…”
helm upgrade –install “consumer-${channel}” \
“./helm/oms-consumer-${channel}” \
–set image.version=$VERSION \
–namespace oms
done
echo “All channels deployed!”
Service 與 Ingress
apiVersion: v1
kind: Service
metadata:
name: {{ .Chart.Name }}
namespace: oms
spec:
type: ClusterIP
ports:
– port: 80
targetPort: 8080
name: http
selector:
app: {{ .Chart.Name }}
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: oms-api-gateway
annotations:
nginx.ingress.kubernetes.io/rewrite-target: /
spec:
rules:
– host: api.example.com
http:
paths:
– path: /orders
pathType: Prefix
backend:
service:
name: order-service
port:
number: 80
CI/CD 整合
stages:
– build
– deploy
build:
stage: build
script:
– docker build -t registry.example.com/oms/consumer-shopee:$CI_COMMIT_SHA .
– docker push registry.example.com/oms/consumer-shopee:$CI_COMMIT_SHA
deploy-dev:
stage: deploy
script:
– helm upgrade –install consumer-shopee ./helm/oms-consumer-shopee
–set image.version=$CI_COMMIT_SHA
-f values-dev.yaml
only:
– develop
deploy-prod:
stage: deploy
script:
– helm upgrade –install consumer-shopee ./helm/oms-consumer-shopee
–set image.version=$CI_COMMIT_TAG
-f values-prod.yaml
only:
– tags
when: manual
實戰踩坑
情境:改了 application.yml 但服務行為沒變
原因:K8s 不會自動重啟 Pod,舊的 ConfigMap 還在記憶體中
解法:在 Deployment 加 checksum annotation,ConfigMap 變化時觸發滾動更新
情境:服務突然重啟,查了半天才發現是記憶體不足
原因:JVM heap 設定超過 container limits,被 K8s 強制 kill
解法:JVM heap 設為 limits 的 70%,並設定 Prometheus 告警監控 OOM 事件
情境:部署新版本時用戶收到 502 錯誤
原因:新 Pod 還沒 ready 就把舊 Pod 砍掉,或 preStop 沒有 graceful shutdown
解法:設好 readinessProbe + preStop hook,確保流量先切換再關閉
總結
| 設計 | 效果 |
|---|---|
| Helm Chart 標準化 | 每個服務結構一致,易於維護 |
| values 分環境 | 同一 Chart 部署不同環境 |
| ConfigMap 動態載入 | 配置與程式碼分離 |
| Secret 管理 | 敏感資訊安全儲存 |
| 健康檢查整合 | K8s 自動管理故障 |
| 多通路獨立部署 | 故障隔離,獨立升級 |
| 上一篇 | 系列目錄 | 完結 |
|---|---|---|
| OpenTracing分散式追蹤 | 系列導讀 | 本篇為系列最終篇 |
這是「多通路電商 OMS 系統實戰」系列的最終篇。感謝閱讀,希望對你的系統設計有所幫助!
發佈留言