强曰为道
与天地相似,故不违。知周乎万物,而道济天下,故不过。旁行而不流,乐天知命,故不忧.
文档目录

微服务拆分精讲 / 第 15 章:容器化与编排

第 15 章:容器化与编排

容器化是微服务的交付标准,Kubernetes 是微服务的运行平台。不懂容器化,就无法真正实践微服务。


15.1 为什么需要容器化

15.1.1 “在我机器上能跑"问题

  传统部署:
  ┌──────────┐  ┌──────────┐  ┌──────────┐
  │ Dev 环境  │  │ Staging  │  │ Prod     │
  │ JDK 17   │  │ JDK 11   │  │ JDK 17   │
  │ MySQL 8  │  │ MySQL 5.7│  │ MySQL 8  │
  │ Ubuntu   │  │ CentOS   │  │ RHEL     │
  └──────────┘  └──────────┘  └──────────┘
  (环境不一致导致 "在我机器上能跑")

  容器化部署:
  ┌──────────┐  ┌──────────┐  ┌──────────┐
  │ Dev 环境  │  │ Staging  │  │ Prod     │
  │          │  │          │  │          │
  │ ┌──────┐ │  │ ┌──────┐ │  │ ┌──────┐ │
  │ │Container│ │ │Container│ │ │Container│ │
  │ │JDK 17│ │  │ │JDK 17│ │  │ │JDK 17│ │
  │ │MySQL 8│ │  │ │MySQL 8│ │  │ │MySQL 8│ │
  │ │App   │ │  │ │App   │ │  │ │App   │ │
  │ └──────┘ │  │ └──────┘ │  │ └──────┘ │
  └──────────┘  └──────────┘  └──────────┘
  (环境完全一致)

15.1.2 容器化的核心价值

价值 说明
环境一致性 开发/测试/生产使用相同的镜像
快速部署 秒级启动(vs 虚拟机分钟级)
资源高效 共享内核,资源开销小
版本管理 镜像版本 = 应用版本
不可变基础设施 镜像一旦构建不可修改
DevOps 基石 CI/CD 的标准交付物

15.2 Docker 最佳实践

15.2.1 Dockerfile 优化

# ❌ 不好的 Dockerfile
FROM ubuntu:22.04
RUN apt-get update
RUN apt-get install -y openjdk-17-jdk maven git
COPY . /app
WORKDIR /app
RUN mvn clean package
CMD ["java", "-jar", "target/order-service.jar"]
# 问题:镜像大、包含构建工具、不安全

# ✅ 好的 Dockerfile(多阶段构建)
# 构建阶段
FROM eclipse-temurin:21-jdk-alpine AS builder
WORKDIR /app
COPY pom.xml .
COPY src ./src
RUN --mount=type=cache,target=/root/.m2 \
    mvn clean package -DskipTests

# 运行阶段
FROM eclipse-temurin:21-jre-alpine
RUN addgroup -S app && adduser -S app -G app
WORKDIR /app
COPY --from=builder /app/target/order-service.jar app.jar
USER app
EXPOSE 8080
HEALTHCHECK --interval=30s --timeout=3s \
  CMD wget -qO- http://localhost:8080/actuator/health || exit 1
ENTRYPOINT ["java", "-XX:+UseContainerSupport", "-jar", "app.jar"]

15.2.2 Dockerfile 最佳实践

实践 说明
多阶段构建 构建镜像和运行镜像分离
最小基础镜像 使用 Alpine 或 distroless
非 root 用户 安全最佳实践
健康检查 HEALTHCHECK 指令
.dockerignore 排除不需要的文件
层缓存优化 不常变的层放前面
固定版本号 FROM image:tag 使用具体版本

15.2.3 镜像大小对比

  基础镜像选择:

  ┌─────────────────────┬───────────┐
  │ 镜像                │ 大小      │
  ├─────────────────────┼───────────┤
  │ ubuntu:22.04        │ ~77 MB    │
  │ eclipse-temurin:21  │ ~460 MB   │
  │ eclipse-temurin:21-alpine │ ~180 MB │
  │ eclipse-temurin:21-jre-alpine │ ~120 MB │
  │ gcr.io/distroless/java21 │ ~130 MB │
  └─────────────────────┴───────────┘
  推荐:JRE Alpine 或 distroless

15.3 Kubernetes 核心概念

15.3.1 K8s 架构

┌──────────────────────────────────────────────────────────────────┐
│                    Kubernetes 架构                                │
├──────────────────────────────────────────────────────────────────┤
│                                                                  │
│  Control Plane (控制平面)                                        │
│  ┌────────────────────────────────────────────────────────────┐ │
│  │ ┌──────────┐ ┌──────────┐ ┌──────────┐ ┌──────────┐      │ │
│  │ │ API      │ │ Scheduler│ │Controller│ │  etcd    │      │ │
│  │ │ Server   │ │          │ │ Manager  │ │ (KV存储) │      │ │
│  │ └──────────┘ └──────────┘ └──────────┘ └──────────┘      │ │
│  └────────────────────────────────────────────────────────────┘ │
│                          │                                       │
│  ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ┼ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─  │
│                          ▼                                       │
│  Worker Nodes (工作节点)                                         │
│  ┌─────────────────────────┐  ┌─────────────────────────┐      │
│  │  Node 1                 │  │  Node 2                 │      │
│  │  ┌───────────────────┐ │  │  ┌───────────────────┐ │      │
│  │  │  kubelet          │ │  │  │  kubelet          │ │      │
│  │  │  kube-proxy       │ │  │  │  kube-proxy       │ │      │
│  │  │  Container Runtime│ │  │  │  Container Runtime│ │      │
│  │  │  (containerd)     │ │  │  │  (containerd)     │ │      │
│  │  └───────────────────┘ │  │  └───────────────────┘ │      │
│  │  ┌─────┐ ┌─────┐      │  │  ┌─────┐ ┌─────┐      │      │
│  │  │Pod A│ │Pod B│      │  │  │Pod C│ │Pod D│      │      │
│  │  └─────┘ └─────┘      │  │  └─────┘ └─────┘      │      │
│  └─────────────────────────┘  └─────────────────────────┘      │
└──────────────────────────────────────────────────────────────────┘

15.3.2 核心资源对象

资源 说明 用途
Pod 最小调度单元 运行一个或多个容器
Deployment 声明式部署管理 管理 ReplicaSet,滚动更新
Service 服务发现和负载均衡 稳定的网络访问入口
Ingress HTTP(S) 入口 域名路由、SSL 终止
ConfigMap 配置管理 非敏感配置
Secret 敏感信息管理 密码、Token
StatefulSet 有状态应用 数据库、MQ
DaemonSet 每节点一个 Pod 日志收集、监控 Agent
HPA 水平自动扩容 按 CPU/内存/自定义指标扩容

15.4 微服务 K8s 部署配置

15.4.1 Deployment 配置

apiVersion: apps/v1
kind: Deployment
metadata:
  name: order-service
  namespace: production
  labels:
    app: order-service
    version: v2.1.0
spec:
  replicas: 3
  strategy:
    type: RollingUpdate
    rollingUpdate:
      maxSurge: 1
      maxUnavailable: 0
  selector:
    matchLabels:
      app: order-service
  template:
    metadata:
      labels:
        app: order-service
        version: v2.1.0
      annotations:
        prometheus.io/scrape: "true"
        prometheus.io/port: "8080"
        prometheus.io/path: "/actuator/prometheus"
    spec:
      serviceAccountName: order-service
      securityContext:
        runAsNonRoot: true
        runAsUser: 1000
      containers:
        - name: order-service
          image: registry.example.com/order-service:v2.1.0
          ports:
            - containerPort: 8080
              name: http
          env:
            - name: SPRING_PROFILES_ACTIVE
              value: "production"
            - name: DB_PASSWORD
              valueFrom:
                secretKeyRef:
                  name: order-db-credentials
                  key: password
          resources:
            requests:
              cpu: "250m"
              memory: "512Mi"
            limits:
              cpu: "1000m"
              memory: "1Gi"
          livenessProbe:
            httpGet:
              path: /actuator/health/liveness
              port: 8080
            initialDelaySeconds: 30
            periodSeconds: 10
          readinessProbe:
            httpGet:
              path: /actuator/health/readiness
              port: 8080
            initialDelaySeconds: 15
            periodSeconds: 5
          startupProbe:
            httpGet:
              path: /actuator/health
              port: 8080
            failureThreshold: 30
            periodSeconds: 2

15.4.2 Service 配置

apiVersion: v1
kind: Service
metadata:
  name: order-service
  namespace: production
spec:
  selector:
    app: order-service
  ports:
    - name: http
      port: 80
      targetPort: 8080
  type: ClusterIP

15.4.3 HPA 自动扩容

apiVersion: autoscaling/v2
kind: HorizontalPodAutoscaler
metadata:
  name: order-service-hpa
  namespace: production
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: 80
    - type: Pods
      pods:
        metric:
          name: http_requests_per_second
        target:
          type: AverageValue
          averageValue: "1000"
  behavior:
    scaleUp:
      stabilizationWindowSeconds: 60
      policies:
        - type: Pods
          value: 4
          periodSeconds: 60
    scaleDown:
      stabilizationWindowSeconds: 300
      policies:
        - type: Pods
          value: 1
          periodSeconds: 60

15.5 Helm Chart 管理

15.5.1 Helm Chart 结构

  order-service-chart/
  ├── Chart.yaml           # Chart 元数据
  ├── values.yaml          # 默认配置值
  ├── templates/
  │   ├── deployment.yaml  # Deployment 模板
  │   ├── service.yaml     # Service 模板
  │   ├── ingress.yaml     # Ingress 模板
  │   ├── hpa.yaml         # HPA 模板
  │   └── _helpers.tpl     # 模板助手函数
  └── charts/              # 依赖的子 Chart

15.5.2 Helm 常用命令

# 安装 Chart
helm install order-service ./order-service-chart \
  -n production \
  --set image.tag=v2.1.0 \
  --set replicaCount=3

# 升级
helm upgrade order-service ./order-service-chart \
  -n production \
  --set image.tag=v2.2.0

# 回滚
helm rollback order-service 1 -n production

# 查看历史
helm history order-service -n production

15.6 有状态服务编排

15.6.1 数据库部署

# MySQL StatefulSet
apiVersion: apps/v1
kind: StatefulSet
metadata:
  name: mysql
spec:
  serviceName: mysql
  replicas: 3
  selector:
    matchLabels:
      app: mysql
  template:
    metadata:
      labels:
        app: mysql
    spec:
      containers:
        - name: mysql
          image: mysql:8.0
          ports:
            - containerPort: 3306
          env:
            - name: MYSQL_ROOT_PASSWORD
              valueFrom:
                secretKeyRef:
                  name: mysql-secret
                  key: root-password
          volumeMounts:
            - name: mysql-data
              mountPath: /var/lib/mysql
  volumeClaimTemplates:
    - metadata:
        name: mysql-data
      spec:
        accessModes: ["ReadWriteOnce"]
        storageClassName: "fast-ssd"
        resources:
          requests:
            storage: 100Gi

15.7 Kustomize vs Helm

维度 Kustomize Helm
模板方式 Overlay (覆盖) Template (模板)
学习曲线
K8s 原生 kubectl apply -k 需要安装
复杂逻辑 不支持 支持 (Go Template)
多环境管理 优秀 (Base + Overlay) 良好 (values-xxx.yaml)
社区生态 增长中 极丰富

15.8 业务场景:电商 K8s 部署全景

  ┌──────────────────────────────────────────────────────────────┐
  │              电商 K8s 部署架构                                │
  ├──────────────────────────────────────────────────────────────┤
  │                                                              │
  │  Ingress Layer                                               │
  │  ┌──────────────────────────────────────────────────────┐   │
  │  │  NGINX Ingress Controller / Istio Gateway            │   │
  │  │  *.pkold.com → 各服务路由                             │   │
  │  └──────────────────────────┬───────────────────────────┘   │
  │                             │                                │
  │  Service Layer              ▼                                │
  │  ┌──────┐ ┌──────┐ ┌──────┐ ┌──────┐ ┌──────┐            │
  │  │ User │ │Order │ │Product│ │Payment│ │Notif │            │
  │  │  SVC │ │  SVC │ │  SVC │ │  SVC │ │  SVC │            │
  │  └──┬───┘ └──┬───┘ └──┬───┘ └──┬───┘ └──┬───┘            │
  │     │        │        │        │        │                  │
  │  Pod Layer   ▼        ▼        ▼        ▼                  │
  │  ┌────┐┌────┐┌────┐┌────┐┌────┐┌────┐┌────┐┌────┐        │
  │  │U-1 ││U-2 ││O-1 ││O-2 ││P-1 ││P-2 ││Py-1││N-1 │        │
  │  └────┘└────┘└────┘└────┘└────┘└────┘└────┘└────┘        │
  │     (HPA: 2-10)    (HPA: 3-20)  (HPA: 2-10)               │
  │                                                              │
  │  Data Layer                                                  │
  │  ┌──────┐ ┌──────┐ ┌──────┐ ┌──────┐                      │
  │  │MySQL │ │Redis │ │Kafka │ │ ES   │                      │
  │  │(StatefulSet)│ │      │ │      │ │      │                      │
  │  └──────┘ └──────┘ └──────┘ └──────┘                      │
  │                                                              │
  │  Platform Layer                                              │
  │  ┌──────┐ ┌──────┐ ┌──────┐ ┌──────┐ ┌──────┐            │
  │  │Prom  │ │Grafana│ │Jaeger│ │Loki │ │Vault │            │
  │  └──────┘ └──────┘ └──────┘ └──────┘ └──────┘            │
  └──────────────────────────────────────────────────────────────┘

⚠️ 注意事项

  1. Pod 不是虚拟机——不要在一个 Pod 中放太多容器
  2. 资源请求和限制——必须设置,避免资源争抢
  3. 健康检查——liveness + readiness + startup probe 三件套
  4. 优雅关闭——处理 SIGTERM,完成正在进行的请求
  5. 日志输出到 stdout——不要写日志文件,让 K8s 收集
  6. 配置外部化——使用 ConfigMap/Secret,不硬编码在镜像中

📖 扩展阅读

  1. Kubernetes Documentation (kubernetes.io) — K8s 官方文档
  2. Docker Best Practices (docs.docker.com) — Dockerfile 最佳实践
  3. Helm Documentation (helm.sh) — Helm 包管理器
  4. Kubernetes Patterns — Bilgin Ibryam, Roland Huß — K8s 设计模式
  5. Production Kubernetes — O’Reilly — 生产级 K8s 实践

本章小结

要点 说明
Docker 最佳实践 多阶段构建、最小镜像、非 root
K8s 核心资源 Deployment, Service, HPA, Ingress
Helm Chart 微服务 K8s 部署的标准化方案
自动扩容 HPA 基于 CPU/Memory/自定义指标
有状态服务 StatefulSet + PVC

📌 下一章第 16 章:单体拆分实践 — 绞杀者模式、防腐层、渐进迁移实战。