簡介
最後一課:將整個電子商務平台部署到 Kubernetes,使用 GitHub Actions CI/CD 自動化,使用 Prometheus & Grafana 監控生產。 Quarkus 有擴展 quarkus-kubernetes 自生成清單。
Kubernetes 上的架構
┌─── Ingress (Nginx) ───┐
│ ecommerce.xdev.asia │
└──────┬────────────────┘
│
┌──────────────┼──────────────┐
▼ ▼ ▼
┌────────────┐ ┌───────────┐ ┌────────────┐
│ Product │ │ Order │ │ Payment │
│ Service │ │ Service │ │ Service │
│ (3 pods) │ │ (3 pods) │ │ (2 pods) │
└──────┬─────┘ └─────┬─────┘ └──────┬─────┘
│ │ │
▼ ▼ ▼
┌────────────────────────────────────┐
│ PostgreSQL (StatefulSet) │
│ Kafka (Strimzi Operator) │
│ Keycloak (Operator) │
│ Redis (StatefulSet) │
└────────────────────────────────────┘
│
┌──────┴────────────────────────────┐
│ Monitoring Namespace │
│ Prometheus + Grafana + Jaeger │
└──────────────────────────────────┘
Quarkus Kubernetes 擴充
<dependency>
<groupId>io.quarkus</groupId>
<artifactId>quarkus-kubernetes</artifactId>
</dependency>
應用程式.屬性
# Kubernetes deployment config
quarkus.kubernetes.deployment-target=kubernetes
quarkus.kubernetes.namespace=ecommerce
# Container image
quarkus.container-image.group=xdev
quarkus.container-image.name=product-service
quarkus.container-image.tag=${quarkus.application.version}
quarkus.container-image.registry=ghcr.io
# Deployment settings
quarkus.kubernetes.replicas=3
quarkus.kubernetes.image-pull-policy=always
# Resources
quarkus.kubernetes.resources.requests.cpu=100m
quarkus.kubernetes.resources.requests.memory=64Mi
quarkus.kubernetes.resources.limits.cpu=500m
quarkus.kubernetes.resources.limits.memory=128Mi
# Health probes (auto-configured từ SmallRye Health)
quarkus.kubernetes.liveness-probe.http-action-path=/q/health/live
quarkus.kubernetes.readiness-probe.http-action-path=/q/health/ready
quarkus.kubernetes.startup-probe.http-action-path=/q/health/started
# Service
quarkus.kubernetes.service-type=cluster-ip
quarkus.kubernetes.ports.http.container-port=8080
# Labels
quarkus.kubernetes.labels."app.kubernetes.io/part-of"=ecommerce
quarkus.kubernetes.labels."app.kubernetes.io/managed-by"=quarkus
# Env from ConfigMap & Secret
quarkus.kubernetes.env.configmaps=product-service-config
quarkus.kubernetes.env.secrets=product-service-secret
建構生成 target/kubernetes/kubernetes.yml:
./mvnw package -Dnative \
-Dquarkus.container-image.build=true \
-Dquarkus.container-image.push=true
Kubernetes 清單
命名空間和 ConfigMap
# k8s/base/namespace.yaml
apiVersion: v1
kind: Namespace
metadata:
name: ecommerce
labels:
app.kubernetes.io/part-of: ecommerce
---
# k8s/base/configmap.yaml
apiVersion: v1
kind: ConfigMap
metadata:
name: product-service-config
namespace: ecommerce
data:
QUARKUS_DATASOURCE_JDBC_URL: >-
jdbc:postgresql://postgres:5432/productdb
QUARKUS_OIDC_AUTH_SERVER_URL: >-
http://keycloak:8080/realms/ecommerce
QUARKUS_LOG_LEVEL: INFO
QUARKUS_OTEL_EXPORTER_OTLP_ENDPOINT: >-
http://jaeger-collector:4317
秘密(密封)
# k8s/base/secret.yaml
apiVersion: v1
kind: Secret
metadata:
name: product-service-secret
namespace: ecommerce
type: Opaque
stringData:
QUARKUS_DATASOURCE_USERNAME: product
QUARKUS_DATASOURCE_PASSWORD: "${DB_PASSWORD}"
生產:使用密封的秘密或外部秘密操作員而不是普通的秘密。
HPA — 水平 Pod 自動縮放器
# k8s/base/hpa.yaml
apiVersion: autoscaling/v2
kind: HorizontalPodAutoscaler
metadata:
name: product-service
namespace: ecommerce
spec:
scaleTargetRef:
apiVersion: apps/v1
kind: Deployment
name: product-service
minReplicas: 2
maxReplicas: 10
metrics:
- type: Resource
resource:
name: cpu
target:
type: Utilization
averageUtilization: 70
- type: Resource
resource:
name: memory
target:
type: Utilization
averageUtilization: 80
behavior:
scaleUp:
stabilizationWindowSeconds: 30
policies:
- type: Pods
value: 2
periodSeconds: 60
scaleDown:
stabilizationWindowSeconds: 300
policies:
- type: Pods
value: 1
periodSeconds: 120
入口
# k8s/base/ingress.yaml
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: ecommerce-ingress
namespace: ecommerce
annotations:
nginx.ingress.kubernetes.io/rewrite-target: /$2
cert-manager.io/cluster-issuer: letsencrypt-prod
spec:
ingressClassName: nginx
tls:
- hosts:
- api.ecommerce.xdev.asia
secretName: ecommerce-tls
rules:
- host: api.ecommerce.xdev.asia
http:
paths:
- path: /products(/|$)(.*)
pathType: ImplementationSpecific
backend:
service:
name: product-service
port:
number: 8080
- path: /orders(/|$)(.*)
pathType: ImplementationSpecific
backend:
service:
name: order-service
port:
number: 8080
- path: /payments(/|$)(.*)
pathType: ImplementationSpecific
backend:
service:
name: payment-service
port:
number: 8080
頭盔圖表
ecommerce-chart/
├── Chart.yaml
├── values.yaml
├── values-staging.yaml
├── values-production.yaml
└── templates/
├── _helpers.tpl
├── deployment.yaml
├── service.yaml
├── configmap.yaml
├── secret.yaml
├── hpa.yaml
└── ingress.yaml
值.yaml
# values.yaml
global:
namespace: ecommerce
imageRegistry: ghcr.io/xdev
services:
product:
name: product-service
image:
tag: latest
replicas: 2
resources:
requests:
cpu: 100m
memory: 64Mi
limits:
cpu: 500m
memory: 128Mi
hpa:
enabled: true
minReplicas: 2
maxReplicas: 10
targetCPU: 70
order:
name: order-service
image:
tag: latest
replicas: 2
resources:
requests:
cpu: 100m
memory: 64Mi
limits:
cpu: 500m
memory: 128Mi
payment:
name: payment-service
image:
tag: latest
replicas: 2
notification:
name: notification-service
image:
tag: latest
replicas: 1
ingress:
enabled: true
host: api.ecommerce.xdev.asia
tls: true
值-生產.yaml
# values-production.yaml
services:
product:
replicas: 3
resources:
limits:
cpu: "1"
memory: 256Mi
hpa:
minReplicas: 3
maxReplicas: 20
order:
replicas: 3
payment:
replicas: 2
部署
# Install
helm install ecommerce ./ecommerce-chart \
-n ecommerce --create-namespace \
-f values-production.yaml
# Upgrade
helm upgrade ecommerce ./ecommerce-chart \
-n ecommerce \
-f values-production.yaml \
--set services.product.image.tag=v1.2.0
# Rollback
helm rollback ecommerce 1 -n ecommerce
GitHub 操作 CI/CD
# .github/workflows/ci-cd.yml
name: CI/CD Pipeline
on:
push:
branches: [main]
pull_request:
branches: [main]
env:
REGISTRY: ghcr.io
IMAGE_PREFIX: ghcr.io/${{ github.repository_owner }}
jobs:
test:
runs-on: ubuntu-latest
strategy:
matrix:
service:
- product-service
- order-service
- payment-service
- notification-service
steps:
- uses: actions/checkout@v4
- uses: actions/setup-java@v4
with:
java-version: '21'
distribution: 'temurin'
cache: maven
- name: Run tests
run: |
cd ${{ matrix.service }}
./mvnw verify
contract-test:
needs: test
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/setup-java@v4
with:
java-version: '21'
distribution: 'temurin'
- name: Consumer contract tests
run: |
cd order-service
./mvnw test -Dtest="*ContractTest"
- name: Provider verification
run: |
cd product-service
./mvnw test -Dtest="*ContractVerificationTest"
build-and-push:
needs: [test, contract-test]
if: github.ref == 'refs/heads/main'
runs-on: ubuntu-latest
permissions:
contents: read
packages: write
strategy:
matrix:
service:
- product-service
- order-service
- payment-service
- notification-service
steps:
- uses: actions/checkout@v4
- uses: actions/setup-java@v4
with:
java-version: '21'
distribution: 'temurin'
cache: maven
- name: Login to GHCR
uses: docker/login-action@v3
with:
registry: ghcr.io
username: ${{ github.actor }}
password: ${{ secrets.GITHUB_TOKEN }}
- name: Build native image & push
run: |
cd ${{ matrix.service }}
./mvnw package -Dnative \
-Dquarkus.native.container-build=true \
-Dquarkus.container-image.build=true \
-Dquarkus.container-image.push=true \
-Dquarkus.container-image.registry=ghcr.io \
-Dquarkus.container-image.group=\
${{ github.repository_owner }} \
-Dquarkus.container-image.tag=\
${{ github.sha }} \
-DskipTests
deploy-staging:
needs: build-and-push
runs-on: ubuntu-latest
environment: staging
steps:
- uses: actions/checkout@v4
- name: Set up kubectl
uses: azure/setup-kubectl@v4
- name: Set K8s context
uses: azure/k8s-set-context@v4
with:
kubeconfig: ${{ secrets.KUBE_CONFIG_STAGING }}
- name: Deploy to staging
run: |
helm upgrade --install ecommerce \
./ecommerce-chart \
-n ecommerce-staging \
--create-namespace \
-f ecommerce-chart/values-staging.yaml \
--set global.imageTag=${{ github.sha }}
deploy-production:
needs: deploy-staging
runs-on: ubuntu-latest
environment: production
steps:
- uses: actions/checkout@v4
- name: Set up kubectl
uses: azure/setup-kubectl@v4
- name: Set K8s context
uses: azure/k8s-set-context@v4
with:
kubeconfig: ${{ secrets.KUBE_CONFIG_PRODUCTION }}
- name: Deploy to production
run: |
helm upgrade --install ecommerce \
./ecommerce-chart \
-n ecommerce \
--create-namespace \
-f ecommerce-chart/values-production.yaml \
--set global.imageTag=${{ github.sha }}
- name: Verify deployment
run: |
kubectl rollout status deployment/product-service \
-n ecommerce --timeout=300s
kubectl rollout status deployment/order-service \
-n ecommerce --timeout=300s
Kubernetes 上的監控
普羅米修斯服務監視器
apiVersion: monitoring.coreos.com/v1
kind: ServiceMonitor
metadata:
name: quarkus-services
namespace: ecommerce
labels:
release: prometheus
spec:
selector:
matchLabels:
app.kubernetes.io/part-of: ecommerce
endpoints:
- port: http
path: /q/metrics
interval: 15s
Grafana 儀表板
匯入儀表板 ID 14370(Quarkus Microprofile Metrics)或建立自訂:
{
"dashboard": {
"title": "E-Commerce Platform",
"panels": [
{
"title": "Request Rate",
"targets": [{
"expr": "rate(http_server_requests_seconds_count{namespace='ecommerce'}[5m])"
}]
},
{
"title": "P99 Latency",
"targets": [{
"expr": "histogram_quantile(0.99, rate(http_server_requests_seconds_bucket{namespace='ecommerce'}[5m]))"
}]
},
{
"title": "Error Rate",
"targets": [{
"expr": "rate(http_server_requests_seconds_count{namespace='ecommerce',status=~'5..'}[5m])"
}]
}
]
}
}
生產清單
| 類別 | 項目 | 狀態 |
|---|---|---|
| 安全性 | 加密的秘密(封印的秘密) | ○ |
| 安全性 | 網路策略配置 | ○ |
| 安全性 | 服務帳號的 RBAC | ○ |
| 可靠性 | 已配置運轉狀況探測器 | ○ |
| 可靠性 | HPA 配置 | ○ |
| 可靠度 | PodDisruptionBudget 設定 | ○ |
| 可觀察性 | 分散式追蹤 (Jaeger) | ○ |
| 可觀察性 | 指標(普羅米修斯 + Grafana) | ○ |
| 可觀察性 | 集中式日誌記錄(EFK/Loki) | ○ |
| CI/CD | 自動化測試 | ○ |
| CI/CD | 合約測試 | ○ |
| CI/CD | 自動化部署 | ○ |
| CI/CD | 回滾策略 | ○ |
練習
- 產生 Kubernetes 清單
quarkus-kubernetes延伸 - 為電商平台創建Helm圖表
- 設定 GitHub Actions CI/CD 管道 4.部署到本地Kubernetes(minikube/kind) 5.配置HPA並檢查自動縮放 6.設定Prometheus + Grafana監控
系列總結
透過 22 節課程,您已經完全建立了:
- Quarkus 平台 — REST API、PostgreSQL、驗證
- 微服務設計 - DDD,每個服務資料庫,4個實用服務
- 安全性 — Keycloak OIDC、RBAC、代幣傳播
- 通訊 — REST 用戶端、gRPC、Kafka 事件驅動
- 彈性與可觀察性 — 容錯、OpenTelemetry、緩存
- 測試 — @QuarkusTest,合約測試
- 生產 — GraalVM Native、Kubernetes、CI/CD
後續步驟:
- 為分散式交易新增 Saga 模式
- GraphQL API 閘道 (quarkus-smallrye-graphql)
- 服務網格(Istio)用於流量管理
- GitOps 與 ArgoCD
- Quarkus 虛擬執行緒 (Project Loom) 用於反應性工作負載