第8章:微服务的部署(Deploying Microservices)
一、导读
1.1 本章学习目标
微服务的独立部署特性对部署基础设施提出了更高要求。第8章介绍了多种部署模式,重点讲解了基于 Kubernetes 的容器化部署和 CI/CD 流水线设计。
本章的核心学习目标包括:
- 理解微服务的部署模式:多服务实例模式 vs 服务实例共享模式。
- 掌握容器化部署:Docker + Kubernetes 的核心概念和配置。
- 学会 Kubernetes 核心资源:Pod、Deployment、Service、Ingress 的配置。
- 理解 CI/CD 流水线设计:构建、测试、部署的自动化。
- 掌握部署策略:蓝绿部署、金丝雀发布、滚动更新。
- 了解基础设施即代码:Terraform、Pulumi 的使用。
1.2 为什么本章如此重要
Richardson 指出:微服务的价值只有通过高效的部署才能实现。如果几十个微服务仍然使用手动部署,运维复杂度将远超单体架构。容器化(Docker)和容器编排(Kubernetes)是微服务部署的事实标准,它们提供了服务隔离、弹性伸缩、自动恢复、滚动更新等关键能力。
1.3 核心问题引导
微服务的部署模式有哪些?各自适用于什么场景?
Kubernetes 的 Pod、Deployment、Service 之间是什么关系?
如何设计一个完整的 CI/CD 流水线?
蓝绿部署和金丝雀发布有什么区别?如何选择?
健康检查和就绪检查的区别是什么?
如何实现微服务的自动伸缩?
二、核心概念详解
2.1 部署模式
2.1.1 多服务实例模式
每个服务有自己的独立实例(虚拟机或容器)。
// 模式1:每个服务一个虚拟机
// [VM1: order-service] [VM2: payment-service] [VM3: inventory-service]
// 优点:完全隔离
// 缺点:资源利用率低,管理成本高
// 模式2:每个服务一个容器(推荐)
// [Host1: Docker]
// ├── order-service container (3 replicas)
// ├── payment-service container (2 replicas)
// └── inventory-service container (2 replicas)
// 优点:轻量级隔离,资源利用率高
// 缺点:需要容器编排工具
// 模式3:Serverless(函数计算)
// 每个服务部署为云函数(AWS Lambda、阿里云函数计算)
// 优点:零运维,按需付费,自动伸缩
// 缺点:冷启动延迟,执行时间限制2.1.2 服务实例共享模式
多个服务共享同一组实例(类似 PaaS)。
// 模式:应用服务器集群
// [Application Server Cluster]
// ├── order-service.war
// ├── payment-service.war
// └── inventory-service.war
// 优点:资源利用率高
// 缺点:隔离性差,资源争抢2.2 容器化部署
2.2.1 Docker 基础
# 多阶段构建 Dockerfile
FROM eclipse-temurin:17-jdk-alpine AS builder
WORKDIR /app
COPY build.gradle settings.gradle ./
COPY src ./src
RUN ./gradlew bootJar --no-daemon
FROM eclipse-temurin:17-jre-alpine
WORKDIR /app
COPY --from=builder /app/build/libs/*.jar app.jar
RUN addgroup -S appgroup && adduser -S appuser -G appgroup
USER appuser
EXPOSE 8080
HEALTHCHECK --interval=30s --timeout=3s --retries=3 \
CMD wget -qO- http://localhost:8080/actuator/health || exit 1
ENTRYPOINT ["java", "-jar", "app.jar"]# 构建和运行
docker build -t ftgo/order-service:1.0.0 .
docker run -d -p 8080:8080 \
-e SPRING_PROFILES_ACTIVE=prod \
-e EUREKA_CLIENT_SERVICE_URL_DEFAULTZONE=http://eureka:8761/eureka/ \
--name order-service \
ftgo/order-service:1.0.02.2.2 Kubernetes 核心概念
# Deployment:管理 Pod 副本
apiVersion: apps/v1
kind: Deployment
metadata:
name: order-service
labels:
app: order-service
spec:
replicas: 3
selector:
matchLabels:
app: order-service
strategy:
type: RollingUpdate
rollingUpdate:
maxSurge: 1
maxUnavailable: 0
template:
metadata:
labels:
app: order-service
spec:
containers:
- name: order-service
image: ftgo/order-service:1.0.0
ports:
- containerPort: 8080
resources:
requests:
memory: "256Mi"
cpu: "250m"
limits:
memory: "512Mi"
cpu: "500m"
env:
- name: SPRING_PROFILES_ACTIVE
value: "prod"
- name: EUREKA_CLIENT_SERVICE_URL_DEFAULTZONE
valueFrom:
configMapKeyRef:
name: app-config
key: eureka-url
livenessProbe:
httpGet:
path: /actuator/health/liveness
port: 8080
initialDelaySeconds: 60
periodSeconds: 10
readinessProbe:
httpGet:
path: /actuator/health/readiness
port: 8080
initialDelaySeconds: 30
periodSeconds: 5# Service:暴露网络访问
apiVersion: v1
kind: Service
metadata:
name: order-service
spec:
selector:
app: order-service
ports:
- port: 80
targetPort: 8080
type: ClusterIP
# Ingress:外部访问入口
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: ftgo-ingress
annotations:
nginx.ingress.kubernetes.io/rewrite-target: /
spec:
rules:
- host: api.ftgo.com
http:
paths:
- path: /api/orders
pathType: Prefix
backend:
service:
name: order-service
port:
number: 80
- path: /api/payments
pathType: Prefix
backend:
service:
name: payment-service
port:
number: 80# HPA:自动伸缩
apiVersion: autoscaling/v2
kind: HorizontalPodAutoscaler
metadata:
name: order-service-hpa
spec:
scaleTargetRef:
apiVersion: apps/v1
kind: Deployment
name: order-service
minReplicas: 3
maxReplicas: 20
metrics:
- type: Resource
resource:
name: cpu
target:
type: Utilization
averageUtilization: 70
- type: Resource
resource:
name: memory
target:
type: Utilization
averageUtilization: 802.3 CI/CD 流水线
2.3.1 GitHub Actions
# .github/workflows/deploy-order-service.yml
name: Deploy Order Service
on:
push:
branches: [main]
paths:
- 'order-service/**'
pull_request:
branches: [main]
paths:
- 'order-service/**'
env:
SERVICE_NAME: order-service
REGISTRY: registry.example.com
jobs:
test:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/setup-java@v3
with:
java-version: '17'
distribution: 'temurin'
- name: Run Tests
working-directory: ./order-service
run: ./gradlew test
build:
needs: test
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Build Docker Image
working-directory: ./order-service
run: |
docker build -t ${{ env.REGISTRY }}/${{ env.SERVICE_NAME }}:${{ github.sha }} .
- name: Push to Registry
run: |
echo "${{ secrets.REGISTRY_PASSWORD }}" | docker login ${{ env.REGISTRY }} -u "${{ secrets.REGISTRY_USERNAME }}" --password-stdin
docker push ${{ env.REGISTRY }}/${{ env.SERVICE_NAME }}:${{ github.sha }}
deploy-staging:
needs: build
runs-on: ubuntu-latest
environment: staging
steps:
- name: Deploy to Staging
run: |
kubectl set image deployment/$SERVICE_NAME \
$SERVICE_NAME=${{ env.REGISTRY }}/${{ env.SERVICE_NAME }}:${{ github.sha }} \
-n staging
- name: Smoke Test
run: |
sleep 30
curl -f https://staging-api.ftgo.com/api/orders/health || exit 1
deploy-production:
needs: deploy-staging
runs-on: ubuntu-latest
environment: production
steps:
- name: Canary Deploy (10%)
run: |
kubectl set image deployment/$SERVICE_NAME \
$SERVICE_NAME=${{ env.REGISTRY }}/${{ env.SERVICE_NAME }}:${{ github.sha }} \
-n production
kubectl scale deployment/$SERVICE_NAME --replicas=1 -n production
- name: Verify Canary
run: |
sleep 60
curl -f https://api.ftgo.com/api/orders/health || exit 1
- name: Full Deploy
run: |
kubectl scale deployment/$SERVICE_NAME --replicas=3 -n production2.4 部署策略
2.4.1 蓝绿部署
// 蓝绿部署:
// [Blue: v1.0] ← 当前生产流量
// [Green: v2.0] ← 新版本,无流量
//
// 切换:将负载均衡器指向 Green
// [Blue: v1.0] ← 保留,用于回滚
// [Green: v2.0] ← 接收全部流量
//
// 回滚:将负载均衡器指回 Blue
// 优点:零停机,快速回滚
// 缺点:需要双倍资源2.4.2 金丝雀发布
// 金丝雀发布:
// 阶段1:90% → v1.0, 10% → v2.0
// 阶段2:观察 10 分钟,检查错误率和延迟
// 阶段3:70% → v1.0, 30% → v2.0
// 阶段4:继续观察
// 阶段5:0% → v1.0, 100% → v2.0
//
// 优点:渐进式发布,风险可控
// 缺点:需要流量分割能力2.4.3 滚动更新
# Kubernetes 滚动更新配置
spec:
strategy:
type: RollingUpdate
rollingUpdate:
maxSurge: 1 # 最多多出1个Pod
maxUnavailable: 0 # 不允许有Pod不可用
replicas: 3
# 更新过程:
# 1. 创建1个新Pod(v2.0)→ 共4个Pod(3旧+1新)
# 2. 新Pod就绪后,删除1个旧Pod → 共3个Pod(2旧+1新)
# 3. 创建1个新Pod → 共4个Pod(2旧+2新)
# 4. 重复直到全部更新完成三、实战案例
3.1 案例一:完整的 Kubernetes 部署
# ConfigMap
apiVersion: v1
kind: ConfigMap
metadata:
name: app-config
data:
eureka-url: "http://eureka-server:8761/eureka/"
kafka-brokers: "kafka-0:9092,kafka-1:9092,kafka-2:9092"
# Secret
apiVersion: v1
kind: Secret
metadata:
name: db-credentials
type: Opaque
data:
username: ZnRnb191c2Vy # base64 encoded
password: c2VjdXJlX3Bhc3M=
# 完整 Deployment
apiVersion: apps/v1
kind: Deployment
metadata:
name: order-service
spec:
replicas: 3
selector:
matchLabels:
app: order-service
template:
spec:
containers:
- name: order-service
image: ftgo/order-service:1.0.0
env:
- name: SPRING_DATASOURCE_USERNAME
valueFrom:
secretKeyRef:
name: db-credentials
key: username
- name: SPRING_DATASOURCE_PASSWORD
valueFrom:
secretKeyRef:
name: db-credentials
key: password
- name: KAFKA_BOOTSTRAP_SERVERS
valueFrom:
configMapKeyRef:
name: app-config
key: kafka-brokers
resources:
requests:
memory: "256Mi"
cpu: "250m"
limits:
memory: "512Mi"
cpu: "500m"3.2 案例二:使用 Helm 管理部署
# Chart.yaml
apiVersion: v2
name: order-service
version: 1.0.0
# values.yaml
replicaCount: 3
image:
repository: ftgo/order-service
tag: "1.0.0"
resources:
requests:
memory: "256Mi"
cpu: "250m"
limits:
memory: "512Mi"
cpu: "500m"
service:
port: 80
targetPort: 8080
ingress:
enabled: true
hosts:
- host: api.ftgo.com
paths:
- /api/orders
autoscaling:
enabled: true
minReplicas: 3
maxReplicas: 20
targetCPUUtilization: 70# 部署
helm install order-service ./charts/order-service -n production
# 升级
helm upgrade order-service ./charts/order-service -n production --set image.tag=1.1.0
# 回滚
helm rollback order-service 1 -n production四、本章小结
本章讲解了微服务的部署策略和工具:
核心知识点:
- 容器化(Docker + Kubernetes)是微服务部署的事实标准。
- Kubernetes 的 Pod、Deployment、Service、Ingress 各有分工。
- CI/CD 流水线应包含构建、测试、部署的完整自动化。
- 蓝绿部署实现零停机切换,金丝雀发布实现渐进式上线。
- HPA 实现基于 CPU/内存的自动伸缩。
- Helm 简化 Kubernetes 应用的管理和部署。
五、思考与练习
思考题
你的项目适合使用蓝绿部署还是金丝雀发布?
Kubernetes 的 liveness 和 readiness 探针应该如何设计?
如何实现微服务的零停机部署?
练习题
编写一个多阶段 Dockerfile,构建一个 Spring Boot 微服务。
编写 Kubernetes Deployment、Service、Ingress 配置。
设计一个 GitHub Actions CI/CD 流水线,包含测试、构建、部署步骤。