大家好,我是程序员柏风,AI 最全的 Vibecoding 学习地图 http://coderoadmap.cn 作者。
云与设计模式
这一课你将能做到
- 写出本站的 Dockerfile 和 K8s Deployment 清单,理解每个字段的作用
- 设计一条完整的 CI/CD 流水线:代码提交到生产发布的全部环节
- 说出至少 5 个云设计模式(熔断、重试、舱壁等)并说明本站哪里用得上
为什么要学
云原生改变了架构的边界条件:以前「加服务器」要采购流程几个月,现在一条命令扩容 10 台。架构师必须理解云的能力边界,才能设计出「弹得起、挂不了、回得去」的系统。
人话:传统部署像自己盖房子——一砖一瓦都自己管;云像住酒店——房间随便换、保洁有人做,但你得遵守酒店的规矩(无状态、可中断、声明式配置)。
先建立图像
本站上云演进路线:
【阶段一:单机部署】 【阶段二:容器化】
一台 ECS: Dockerfile → 镜像仓库
├── java -jar app.jar K8s 集群:
├── MySQL ├── Deployment(app) × 3 副本
├── Redis ├── Service(负载均衡)
└── Nginx ├── HPA(CPU>70% 自动扩容)
└── RDS + 云 Redis(托管)
【阶段三:完整云原生】
GitHub Push → CI(测试/构建镜像) → CD(金丝雀发布)
→ 监控(Prometheus) → 告警 → 自动回滚
跟着做
步骤 1:容器化本站应用
# 多阶段构建:编译和运行分离,镜像从 500MB 降到 200MB
FROM maven:3.9-eclipse-temurin-21 AS build
COPY pom.xml .
COPY src ./src
RUN mvn package -DskipTests
FROM eclipse-temurin:21-jre-alpine
WORKDIR /app
COPY --from=build target/app.jar app.jar
# 关键:非 root 运行 + JVM 容器感知
USER 1000
ENTRYPOINT ["java", "-XX:MaxRAMPercentage=75", "-jar", "app.jar"]
步骤 2:K8s 部署清单
apiVersion: apps/v1
kind: Deployment
metadata:
name: course-service
spec:
replicas: 3 # 3 副本保证高可用
strategy:
rollingUpdate:
maxSurge: 1 # 滚动更新:先多启 1 个
maxUnavailable: 0 # 全程不减少可用实例
template:
spec:
containers:
- name: app
image: registry/course-service:v1.2.0
resources:
requests: # 调度依据:保证分到的资源
cpu: 500m
memory: 512Mi
limits: # 上限:防止吃光节点
cpu: "1"
memory: 1Gi
readinessProbe: # 就绪探针:没就绪不接流量
httpGet:
path: /actuator/health/readiness
port: 8080
livenessProbe: # 存活探针:挂了自动重启
httpGet:
path: /actuator/health/liveness
port: 8080
步骤 3:CI/CD 流水线
代码 Push
→ 阶段1 构建:编译 + 单元测试(失败即终止)
→ 阶段2 质检:SonarQube 扫描 + 依赖漏洞检查
→ 阶段3 打包:docker build + 推镜像仓库(tag 用 commit hash)
→ 阶段4 部署测试环境:自动部署 + 接口自动化测试
→ 阶段5 生产金丝雀:先发布 1 个副本 → 观察 10 分钟指标
→ 阶段6 全量:无异常则滚动更新全部;有异常自动回滚
讲清楚要点
- 云设计模式是应对「云会挂」的现实:云厂商 SLA 99.95% 意味着每月允许 22 分钟故障。设计必须假设任何单点都会挂:重试(瞬时故障)、熔断(持续故障)、舱壁(隔离故障域)。
- 无状态是云原生的入场券:Session 存 Redis 不存本地内存,文件存对象存储不写本地磁盘。只有这样,Pod 才能随意被销毁重建、水平扩容。
- 声明式 > 命令式:K8s 的 YAML 描述「我要 3 个副本」,而不是「启动 3 个进程」。系统持续向期望状态收敛,挂了自动拉起——这就是声明式的自愈能力。
- Serverless 的边界:FaaS 适合事件驱动、突发流量、低频任务(本站可以用函数处理「课程封面图压缩」);不适合长运行任务、低延迟要求、有状态服务。
- Service Mesh 解决什么:把熔断、限流、链路追踪、加密从业务代码剥离到 Sidecar 代理(Istio)。代价是架构复杂度大增——服务少于 20 个时,用 Spring Cloud 组件足够。
你可能会懵的地方
-
Docker 和 K8s 是什么关系? Docker 是集装箱(打包标准),K8s 是港口调度系统(决定集装箱放哪艘船、船沉了怎么转移)。可以只用 Docker 不用 K8s(小项目 docker-compose 就够),但 K8s 管理的一定是容器。
-
虚拟机部署好好的,为什么要容器化? 三个核心价值:环境一致性(开发/测试/生产同一镜像,消灭「我本地是好的」)、启动速度(秒级 vs 分钟级,弹性伸缩的前提)、资源利用率(一台机器跑几十个容器)。
-
金丝雀发布和蓝绿发布区别? 蓝绿:两套完整环境,流量一次性切换,回滚快但资源翻倍。金丝雀:新版本先接 5% 流量,逐步放大,发现问题影响面小。本站用金丝雀,因为 K8s 原生支持且省资源。
-
托管服务(RDS、云 Redis)比自己搭贵,值吗? 算总账:RDS 贵 30%,但自动备份、主从切换、监控告警、补丁升级都省了。小团队没有专职 DBA,托管几乎总是更划算——你的时间比机器贵。
-
IaC(基础设施即代码)解决什么痛点? 手工控制台点出来的环境,没人记得配了什么、无法复现、无法评审。Terraform/Pulumi 把基础设施写成代码:环境可一键重建、变更可 Code Review、多环境一致性有保证。
错法对照
| 错法 | 问题 | 正解 |
|---|---|---|
| 容器里跑多进程(app+nginx+agent) | 违背单一职责,探针无法判断健康 | 一容器一进程,辅助功能用 Sidecar |
| 用 latest 标签部署 | 不知道线上跑的是哪个版本 | 镜像 tag 用 git commit hash |
| 没配 resources requests | 调度失衡,节点资源被挤爆 | 必须配 requests/limits |
| 探针路径是业务接口 | 业务慢导致误判,引发重启雪崩 | 专用健康端点,和业务解耦 |
| 有状态服务直接上 Deployment | Pod 重建后数据丢失 | MySQL 等用 StatefulSet 或直接托管 |
卡点急救
- Pod 一直 CrashLoopBackOff:
kubectl logs看启动日志 +kubectl describe pod看事件,90% 是配置错误(环境变量、连接串)或 OOM(limits 太小)。 - 发布后部分请求 502:滚动更新时旧 Pod 还没处理完请求就被杀。解法:preStop 钩子先 sleep 几秒等 LB 摘除,应用实现优雅停机(Spring Boot 的
server.shutdown=graceful)。 - HPA 扩容不及时:HPA 从检测到扩容完成要几分钟,突发流量扛不住。解法:基于 QPS 指标扩缩(而非 CPU),或活动前手动预扩容。
面试常问
-
K8s 的核心组件和一次部署的完整流程? 答题路径:kubectl 提交 YAML → API Server 接收存 etcd → Scheduler 选节点(看 requests)→ Kubelet 拉镜像启动容器 → Controller 持续对比期望与实际状态。组件记四个:API Server(总入口)、etcd(存储)、Scheduler(调度)、Controller Manager(控制循环)。加分:提到 readinessProbe 控制 Service 流量接入时机。
-
什么是熔断和降级?怎么实现的? 熔断:调用下游失败率达到阈值,熔断器打开,直接走 fallback 不再调用,半开状态试探恢复。类比电路保险丝——防止故障蔓延。降级:系统压力大时主动关掉非核心功能(本站大促时关闭推荐模块,保住下单链路)。实现:Resilience4j/Sentinel,核心参数是滑动窗口、错误率阈值、恢复时长。
-
如何设计一个高可用系统? 分层答:接入层(多地域 DNS + LB)、应用层(多副本无状态 + 跨可用区)、数据层(主从 + 自动切换 + 定期备份演练)、架构层(熔断限流降级 + 故障隔离)。最后强调:高可用是设计出来的,也是演练出来的——没做过故障演练的容灾预案等于没有。
自测三问
- 为什么容器化要求应用无状态?本站的 Session 改造方案是什么?
- readinessProbe 和 livenessProbe 配错(比如配反了)会发生什么?
- 如果不用 K8s,3 个微服务的项目用什么部署方案最合理?
小结一句话
云原生架构的核心是「假设一切会挂」:用无状态和声明式获得弹性,用熔断重试舱壁消化故障,用 CI/CD 和金丝雀控制变更风险。
延伸
- 《云原生模式》(Cloud Native Patterns, Cornelia Davis)
- 12-Factor App——云原生应用的十二要素
- K8s 官方文档:Production-Grade 章节
- 下一课:网络基础——OSI、HTTP/TLS 与代理,排查线上问题的语言。