Spring Boot: Kubernetes 部署

最后更新:2026-08-26

Kubernetes 是容器编排的操作系统——自动伸缩、滚动更新、自愈恢复,让应用永远在线。

1. 你将学到


2. 一个云原生运维的真实故事

(1) 痛点:手动运维不堪重负

OrderFlow 生产环境运行在 3 台服务器上,Bob 手动管理每台服务器的 Docker 容器。一次服务器宕机,Bob 凌晨 3 点手动在其他服务器上启动新容器。大促时需要扩容,Bob 手动启动更多容器然后配置负载均衡,每次扩容耗时 30 分钟。Charlie 要求自动伸缩,Bob 说"我做不到"。

(2) Kubernetes 的解法

K8s 声明式配置,自动管理:

YAML
apiVersion: apps/v1
kind: Deployment
metadata:
  name: orderflow
spec:
  replicas: 3
  template:
    spec:
      containers:
      - name: orderflow
        image: orderflow-service:latest
        livenessProbe:
          httpGet: { path: /actuator/health/liveness, port: 8080 }
        readinessProbe:
          httpGet: { path: /actuator/health/readiness, port: 8080 }

节点宕机?K8s 自动在其他节点重启 Pod。流量激增?HPA 自动扩容。

(3) 收益

Bob 用 K8s 部署 OrderFlow 后:节点故障自动恢复(MTTR 从 2 小时降到 30 秒),HPA 自动伸缩(扩容从 30 分钟降到 2 分钟),Bob 再也不用凌晨修服务器了。


3. K8s 核心资源

(1) 资源依赖关系

100%
graph TD
    A[Ingress<br/>External Access] --> B[Service<br/>Internal LB]
    B --> C[Deployment<br/>Pod Template]
    C --> D[ReplicaSet<br/>Pod Replicas]
    D --> E[Pod<br/>Container Group]
    E --> F[Container<br/>OrderFlow App]
    G[ConfigMap] --> F
    H[Secret] --> F
资源 职责 类比
Pod 最小部署单元,包含容器 一个进程组
Deployment 管理 Pod 副本数和更新策略 进程管理器
Service 为 Pod 提供稳定访问入口 负载均衡器
Ingress HTTP 路由规则 Nginx 反向代理
ConfigMap 非敏感配置 配置文件
Secret 敏感配置 加密配置文件

4. Deployment 与滚动更新

▶ 示例: OrderFlow Deployment

YAML
apiVersion: apps/v1
kind: Deployment
metadata:
  name: orderflow
  labels:
    app: orderflow
spec:
  replicas: 3
  selector:
    matchLabels:
      app: orderflow
  strategy:
    type: RollingUpdate
    rollingUpdate:
      maxUnavailable: 1
      maxSurge: 1
  template:
    metadata:
      labels:
        app: orderflow
    spec:
      containers:
      - name: orderflow
        image: registry.example.com/orderflow-service:1.0.0
        ports:
        - containerPort: 8080
        - containerPort: 8081
        env:
        - name: SPRING_PROFILES_ACTIVE
          value: "prod"
        - name: DB_HOST
          valueFrom:
            configMapKeyRef:
              name: orderflow-config
              key: database.host
        - name: DB_PASSWORD
          valueFrom:
            secretKeyRef:
              name: orderflow-secrets
              key: database.password
        resources:
          requests:
            memory: "512Mi"
            cpu: "250m"
          limits:
            memory: "1Gi"
            cpu: "500m"

输出:

TEXT 📖 仅展示
Deployment.apps/my-app created
Service/my-app-service exposed
Ingress/my-app-ingress created
滚动更新参数 含义 推荐值
maxUnavailable 最多不可用 Pod 数 1(或 25%)
maxSurge 最多超出目标副本数 1(或 25%)

▶ 示例: 滚动更新与回滚

BASH
# Update image version (triggers rolling update)
kubectl set image deployment/orderflow orderflow=registry.example.com/orderflow-service:2.0.0

# Check rollout status
kubectl rollout status deployment/orderflow

# Rollback to previous version
kubectl rollout undo deployment/orderflow

# View rollout history
kubectl rollout history deployment/orderflow

输出:

TEXT 📖 仅展示
# 命令执行成功

5. Service 与 Ingress

▶ 示例: Service 定义

YAML
# ClusterIP Service (internal access)
apiVersion: v1
kind: Service
metadata:
  name: orderflow
spec:
  selector:
    app: orderflow
  ports:
  - name: http
    port: 80
    targetPort: 8080
  - name: management
    port: 8081
    targetPort: 8081
  type: ClusterIP

输出:

TEXT 📖 仅展示
Configuration applied successfully
Service 类型 访问范围 适用场景
ClusterIP 集群内部 微服务间调用
NodePort 集群外部(节点 IP:端口) 简单外部访问
LoadBalancer 云厂商负载均衡器 生产环境(云)
ExternalName DNS CNAME 引用外部服务

▶ 示例: Ingress 路由

YAML
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: orderflow-ingress
  annotations:
    nginx.ingress.kubernetes.io/rewrite-target: /
spec:
  ingressClassName: nginx
  rules:
  - host: api.orderflow.example.com
    http:
      paths:
      - path: /
        pathType: Prefix
        backend:
          service:
            name: orderflow
            port:
              number: 80
  tls:
  - hosts:
    - api.orderflow.example.com
    secretName: orderflow-tls

输出:

TEXT 📖 仅展示
Deployment.apps/my-app created
Service/my-app-service exposed
Ingress/my-app-ingress created

6. ConfigMap 与 Secret

▶ 示例: ConfigMap 和 Secret

YAML
# ConfigMap: non-sensitive configuration
apiVersion: v1
kind: ConfigMap
metadata:
  name: orderflow-config
data:
  database.host: "mysql-service"
  database.name: "orderflow"
  redis.host: "redis-service"
  spring.profiles.active: "prod"
  management.server.port: "8081"
---
# Secret: sensitive configuration (base64 encoded)
apiVersion: v1
kind: Secret
metadata:
  name: orderflow-secrets
type: Opaque
data:
  database.password: b3JkZXJmbG93MTIz   # base64 of "orderflow123"
  redis.password: cmVkaXNwYXNz          # base64 of "redispass"
  jwt.private-key: LS0tLS1CRUdJTi...    # base64 of private key

输出:

TEXT 📖 仅展示
Configuration applied successfully
维度 ConfigMap Secret
数据类型 明文 Base64 编码
适用内容 非敏感配置 密码、密钥、证书
存储方式 etcd 明文 etcd 可加密
大小限制 1MB 1MB
🔒 安全: Secret 只是 Base64 编码,不是加密。生产环境应启用 etcd 加密,或使用 Vault 等外部密钥管理。


7. Liveness 与 Readiness 探针

▶ 示例: 探针配置

YAML
spec:
  containers:
  - name: orderflow
    livenessProbe:
      httpGet:
        path: /actuator/health/liveness
        port: 8080
      initialDelaySeconds: 60
      periodSeconds: 30
      timeoutSeconds: 3
      failureThreshold: 3
    readinessProbe:
      httpGet:
        path: /actuator/health/readiness
        port: 8080
      initialDelaySeconds: 30
      periodSeconds: 10
      timeoutSeconds: 3
      failureThreshold: 3
    startupProbe:
      httpGet:
        path: /actuator/health/liveness
        port: 8080
      initialDelaySeconds: 10
      periodSeconds: 5
      failureThreshold: 30

输出:

TEXT 📖 仅展示
配置文件已生效
YAML
# application-prod.yml: Enable liveness/readiness groups
management:
  endpoint:
    health:
      show-details: always
      group:
        liveness:
          include: livenessState
        readiness:
          include: readinessState, db, redis
探针类型 用途 失败后果
livenessProbe 检测进程是否存活 重启容器
readinessProbe 检测是否准备好接收流量 从 Service 摘除
startupProbe 检测应用是否启动完成 启动期间禁用其他探针

8. 综合示例:OrderFlow K8s 完整部署

YAML
# k8s/namespace.yaml
apiVersion: v1
kind: Namespace
metadata:
  name: orderflow

---
# k8s/configmap.yaml
apiVersion: v1
kind: ConfigMap
metadata:
  name: orderflow-config
  namespace: orderflow
data:
  SPRING_PROFILES_ACTIVE: "prod"
  DB_HOST: "mysql-service"
  DB_NAME: "orderflow"
  REDIS_HOST: "redis-service"
  MANAGEMENT_SERVER_PORT: "8081"

---
# k8s/secret.yaml
apiVersion: v1
kind: Secret
metadata:
  name: orderflow-secrets
  namespace: orderflow
type: Opaque
data:
  DB_PASSWORD: b3JkZXJmbG93MTIz

---
# k8s/deployment.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
  name: orderflow
  namespace: orderflow
spec:
  replicas: 3
  selector:
    matchLabels: { app: orderflow }
  strategy:
    rollingUpdate: { maxUnavailable: 1, maxSurge: 1 }
  template:
    metadata:
      labels: { app: orderflow }
    spec:
      containers:
      - name: orderflow
        image: registry.example.com/orderflow-service:1.0.0
        ports:
        - { containerPort: 8080 }
        - { containerPort: 8081 }
        envFrom:
        - configMapRef: { name: orderflow-config }
        - secretRef: { name: orderflow-secrets }
        resources:
          requests: { memory: "512Mi", cpu: "250m" }
          limits: { memory: "1Gi", cpu: "500m" }
        livenessProbe:
          httpGet: { path: /actuator/health/liveness, port: 8080 }
          initialDelaySeconds: 60; periodSeconds: 30; failureThreshold: 3
        readinessProbe:
          httpGet: { path: /actuator/health/readiness, port: 8080 }
          initialDelaySeconds: 30; periodSeconds: 10; failureThreshold: 3

---
# k8s/service.yaml
apiVersion: v1
kind: Service
metadata:
  name: orderflow
  namespace: orderflow
spec:
  selector: { app: orderflow }
  ports:
  - { name: http, port: 80, targetPort: 8080 }
  type: ClusterIP

---
# k8s/ingress.yaml
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: orderflow-ingress
  namespace: orderflow
spec:
  ingressClassName: nginx
  rules:
  - host: api.orderflow.example.com
    http:
      paths:
      - path: /
        pathType: Prefix
        backend:
          service: { name: orderflow, port: { number: 80 } }

❓ 常见问题

Q Deployment 和 StatefulSet 有什么区别?
A Deployment 管理无状态应用(可随意替换),StatefulSet 管理有状态应用(固定网络标识、持久存储)。OrderFlow 是无状态服务,用 Deployment。MySQL 是有状态服务,用 StatefulSet 或 Operator。
Q 如何实现零停机部署?
A 1)配置 readinessProbe,Pod 就绪后才加入 Service;2)滚动更新策略 maxUnavailable=0;3)preStop hook 优雅关闭(sleep 10 等待流量排空);4)应用实现优雅停机(server.shutdown=graceful)。
Q ConfigMap 更新后 Pod 会自动获取新配置吗?
A 环境变量方式不会自动更新(需要重启 Pod)。Volume 挂载方式会自动更新(延迟约 60 秒)。Spring Cloud Kubernetes 支持配置热刷新。
Q 如何选择 CPU/内存的 requests 和 limits?
A requests 决定调度和最小保障,limits 决定最大可用。建议 limits = 2 × requests。设置过低导致 OOM Kill 或 CPU 限流,过高浪费资源。先观察实际用量再调优。
Q Helm Chart 的优势是什么?
A Helm 是 K8s 的包管理器,把所有 YAML 模板化,支持变量替换、版本管理、一键部署/升级/回滚。适合管理复杂的多资源部署。
Q 如何排查 Pod 启动失败?
A 1)kubectl describe pod <name> 查看 Events;2)kubectl logs <name> 查看容器日志;3)kubectl get events --sort-by=.metadata.creationTimestamp 查看集群事件。

📖 小节


📝 作业

  1. 基础题(难度⭐):为 OrderFlow 编写 Deployment + Service YAML,部署到本地 K8s(minikube 或 kind),验证应用可访问。

  2. 进阶题(难度⭐⭐):添加 ConfigMap + Secret + Ingress 配置,实现外部域名访问。配置 Liveness 和 Readiness 探针,模拟 Pod 故障验证自动恢复。

  3. 挑战题(难度⭐⭐⭐):使用 Helm Chart 管理 OrderFlow 的 K8s 部署,支持 values.yaml 变量替换(镜像版本、副本数、资源配置),实现 helm upgrade 滚动更新和 helm rollback 回滚。

Web-Tutorial.com

Web-Tutorial 技术团队

由多位开发者共同维护的编程教程平台。每篇教程由对应领域的开发者编写和审核,确保内容准确可靠。如发现任何问题,欢迎向我们反馈。

100%

🙏 帮我们做得更好

我们是刚上线的编程教程站,几个人的小团队,精力有限。页面虽经检查,难免还有疏漏——链接失效、排版错乱、内容有误、语言生硬……

如果您发现了,麻烦告诉我们,我们会在收到反馈后第一时间进行修复,再次感谢您的光临 🙏