强曰为道

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

第 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服务发现和负载均衡稳定的网络访问入口
IngressHTTP(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

维度KustomizeHelm
模板方式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 章:单体拆分实践 — 绞杀者模式、防腐层、渐进迁移实战。