🚀 微服務部署:Kubernetes 與 CI/CD
📌 Kubernetes 基礎概念
Kubernetes (K8s) 核心元件:
├── Pod:最小部署單位,包含一個或多個容器
├── Service:穩定的網路端點,負載平衡到 Pod
├── Deployment:管理 Pod 的副本數量和更新策略
├── ConfigMap / Secret:外部化設定
├── Ingress:外部流量的入口(類似 API Gateway)
└── Namespace:邏輯隔離(dev、staging、production)
K8s 架構圖:
┌─────────────────────────────────────────┐
│ Kubernetes Cluster │
│ │
│ ┌─────────────┐ ┌─────────────┐ │
│ │ Ingress │ │ Ingress │ │
│ │ (外部入口) │ │ Controller │ │
│ └──────┬──────┘ └─────────────┘ │
│ │ │
│ ┌──────┴──────┐ │
│ │ Service │ ← 負載平衡 │
│ └──────┬──────┘ │
│ │ │
│ ┌──────┴───────┬──────────┐ │
│ │ Pod 1 │ Pod 2 │ Pod 3 │
│ │ OrderSvc │ OrderSvc │ OrderSvc │
│ └─────────────┴──────────┴────────┘ │
└─────────────────────────────────────────┘
📌 將 .NET 微服務部署到 K8s
Deployment 設定
# k8s/product-service/deployment.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: product-service
namespace: eshop
labels:
app: product-service
spec:
replicas: 3
selector:
matchLabels:
app: product-service
template:
metadata:
labels:
app: product-service
spec:
containers:
- name: product-service
image: myregistry.azurecr.io/product-service:v1.0.0
ports:
- containerPort: 8080
env:
- name: ASPNETCORE_ENVIRONMENT
value: "Production"
- name: ConnectionStrings__DefaultConnection
valueFrom:
secretKeyRef:
name: product-db-secret
key: connection-string
resources:
requests:
cpu: "100m"
memory: "128Mi"
limits:
cpu: "500m"
memory: "512Mi"
livenessProbe:
httpGet:
path: /health/live
port: 8080
initialDelaySeconds: 15
periodSeconds: 10
readinessProbe:
httpGet:
path: /health/ready
port: 8080
initialDelaySeconds: 5
periodSeconds: 5
startupProbe:
httpGet:
path: /health/live
port: 8080
failureThreshold: 30
periodSeconds: 10
Service 設定
# k8s/product-service/service.yaml
apiVersion: v1
kind: Service
metadata:
name: product-service
namespace: eshop
spec:
selector:
app: product-service
ports:
- port: 80
targetPort: 8080
type: ClusterIP
Ingress 設定
# k8s/ingress.yaml
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: eshop-ingress
namespace: eshop
annotations:
nginx.ingress.kubernetes.io/rewrite-target: /$2
spec:
ingressClassName: nginx
rules:
- host: api.eshop.example.com
http:
paths:
- path: /products(/|$)(.*)
pathType: ImplementationSpecific
backend:
service:
name: product-service
port:
number: 80
- path: /orders(/|$)(.*)
pathType: ImplementationSpecific
backend:
service:
name: order-service
port:
number: 80
📌 Helm Charts 管理
Helm 是 Kubernetes 的套件管理工具,用模板化的方式管理 K8s 資源。
# helm/product-service/values.yaml
replicaCount: 3
image:
repository: myregistry.azurecr.io/product-service
tag: "v1.0.0"
pullPolicy: IfNotPresent
service:
type: ClusterIP
port: 80
resources:
requests:
cpu: 100m
memory: 128Mi
limits:
cpu: 500m
memory: 512Mi
autoscaling:
enabled: true
minReplicas: 2
maxReplicas: 10
targetCPUUtilizationPercentage: 70
# helm/product-service/templates/deployment.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: {{ include "product-service.fullname" . }}
spec:
replicas: {{ .Values.replicaCount }}
selector:
matchLabels:
app: {{ include "product-service.name" . }}
template:
spec:
containers:
- name: {{ .Chart.Name }}
image: "{{ .Values.image.repository }}:{{ .Values.image.tag }}"
resources:
{{- toYaml .Values.resources | nindent 12 }}
# Helm 常用指令
helm install product-service ./helm/product-service -n eshop
helm upgrade product-service ./helm/product-service -n eshop
helm rollback product-service 1 -n eshop # 回滾到版本 1
helm list -n eshop # 列出所有部署
📌 CI/CD Pipeline(GitHub Actions)
# .github/workflows/deploy-product-service.yml
name: Deploy Product Service
on:
push:
branches: [main]
paths:
- 'src/ProductService/**'
env:
REGISTRY: myregistry.azurecr.io
IMAGE_NAME: product-service
jobs:
build-and-deploy:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Setup .NET
uses: actions/setup-dotnet@v4
with:
dotnet-version: '8.0.x'
- name: Run Tests
run: |
cd src/ProductService
dotnet test --configuration Release
- name: Build Docker Image
run: |
docker build -t $REGISTRY/$IMAGE_NAME:${{ github.sha }} \
-t $REGISTRY/$IMAGE_NAME:latest \
./src/ProductService
- name: Login to Container Registry
uses: docker/login-action@v3
with:
registry: ${{ env.REGISTRY }}
username: ${{ secrets.ACR_USERNAME }}
password: ${{ secrets.ACR_PASSWORD }}
- name: Push Docker Image
run: |
docker push $REGISTRY/$IMAGE_NAME:${{ github.sha }}
docker push $REGISTRY/$IMAGE_NAME:latest
- name: Deploy to Kubernetes
uses: azure/k8s-deploy@v5
with:
namespace: eshop
manifests: k8s/product-service/
images: |
${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}:${{ github.sha }}
📌 藍綠部署 / 金絲雀發布
金絲雀發布(Canary Deployment)
# 先部署少量新版本 Pod 測試
apiVersion: apps/v1
kind: Deployment
metadata:
name: product-service-canary
spec:
replicas: 1 # 只部署 1 個新版本 Pod
selector:
matchLabels:
app: product-service
version: canary
template:
metadata:
labels:
app: product-service
version: canary
spec:
containers:
- name: product-service
image: myregistry.azurecr.io/product-service:v2.0.0-rc1
// 在 .NET 中配合 Feature Flags 控制流量
builder.Services.AddFeatureManagement()
.AddFeatureFilter<PercentageFilter>();
// appsettings.json
// "FeatureManagement": {
// "NewCheckoutFlow": {
// "EnabledFor": [{
// "Name": "Percentage",
// "Parameters": { "Value": 10 } // 10% 流量使用新版
// }]
// }
// }
📌 Service Mesh 概念
Dapr(分散式應用執行環境)
// 使用 Dapr 簡化微服務開發
// 不需要直接依賴 RabbitMQ、Redis 等具體技術
// 透過 Dapr 呼叫其他服務
app.MapGet("/api/orders/{id}", async (int id, DaprClient dapr) =>
{
// Dapr 自動處理服務發現和負載平衡
var product = await dapr.InvokeMethodAsync<ProductDto>(
HttpMethod.Get,
"product-service", // 服務名稱,不需要知道 IP/Port
$"api/products/{id}");
return Results.Ok(product);
});
// 透過 Dapr 發布事件
app.MapPost("/api/orders", async (CreateOrderDto dto, DaprClient dapr) =>
{
var order = CreateOrder(dto);
// Dapr 抽象了 Message Broker(RabbitMQ、Kafka、Azure Service Bus...)
await dapr.PublishEventAsync(
"pubsub", // Pub/Sub 組件名稱
"order-created", // Topic 名稱
new OrderCreatedEvent(order.Id, order.Items));
return Results.Created($"/api/orders/{order.Id}", order);
});
📌 從程式碼到部署的全流程總結
完整的微服務開發到部署流程:
1. 設計階段
└── DDD 分析 → 定義 Bounded Context → 劃分服務
2. 開發階段
├── 建立 ASP.NET Core API
├── 實作業務邏輯
├── 撰寫單元測試與整合測試
└── 設定韌性策略(Polly)
3. 容器化
├── 撰寫 Dockerfile
├── 建立 docker-compose.yml
└── 本地測試所有服務
4. 可觀測性
├── 設定 Serilog + Seq
├── 設定 OpenTelemetry + Jaeger
└── 設定 Prometheus + Grafana
5. 部署
├── 建立 K8s manifests / Helm Charts
├── 設定 CI/CD Pipeline
├── 金絲雀發布
└── 監控與告警
Done! 🎉 你已經完成了微服務架構的完整學習路線!
恭喜完成! 你已經學會了從微服務設計到 Kubernetes 部署的所有核心知識。建議從小型專案開始實踐,逐步累積經驗。