DevOps 基础——为什么你的系统部署总是出问题 / DevOps Fundamentals and Reliable Deployment
📅 创建时间:2026-05-08 🏷️ 标签:#Docker #K8s #CI-CD #监控 #蓝绿部署 #金丝雀 📚 前置知识:[[00-backend-overview]] [[05-middleware]](网关) 📚 相关知识:[[12-devops-basics]](DevOps 基础)
场景:发布一次,报警一小时
┌─────────────────────────────────────────────────────────────┐
│ │
│ 凌晨 2 点,你开始发布新版本。 │
│ │
│ 步骤: │
│ 1. 停止旧服务(用户请求报错) │
│ 2. 部署新版本(10 分钟) │
│ 3. 启动服务 │
│ 4. 发现问题,回滚(10 分钟) │
│ 5. 用户已经被影响了 20 分钟。 │
│ │
│ CTO:下次能不能不要停机发布? │
│ │
└─────────────────────────────────────────────────────────────┘这一章,我们理解 DevOps 工具链:Docker 容器化、K8s 编排、蓝绿/金丝雀部署、监控告警。
第1节:Docker——让"在我机器上能跑"成为历史
问题:为什么开发环境好好的,线上就挂了
┌─────────────────────────────────────────────────────────────┐
│ │
│ 开发环境: │
│ • macOS │
│ • Python 3.10 │
│ • Node.js 18 │
│ • MySQL 8.0 │
│ │
│ 生产环境: │
│ • Ubuntu 22.04 │
│ • Python 3.11 │
│ • Node.js 20 │
│ • MySQL 5.7 │
│ │
│ 差异:版本不同、系统不同、配置不同。 │
│ → "在我机器上能跑" ≠ "在生产环境能跑" │
│ │
└─────────────────────────────────────────────────────────────┘Docker 的核心价值
┌─────────────────────────────────────────────────────────────┐
│ Docker 核心概念 │
├─────────────────────────────────────────────────────────────┤
│ │
│ 镜像(Image):只读模板 │
│ → 包含:操作系统 + 依赖 + 代码 │
│ → 例如:python:3.11-slim、nginx:1.25 │
│ │
│ 容器(Container):镜像的运行实例 │
│ → 容器是隔离的(进程、网络、文件系统) │
│ → 容器是轻量的(共用宿主机内核) │
│ │
│ 仓库(Registry):存储和分发镜像 │
│ → Docker Hub(官方仓库) │
│ → 私有仓库(Harbor) │
│ │
│ ┌─────────────────────────────────────────────────────┐ │
│ │ Dockerfile:描述镜像如何构建 │ │
│ │ │ │
│ │ FROM python:3.11-slim │ │
│ │ WORKDIR /app │ │
│ │ COPY requirements.txt . │ │
│ │ RUN pip install -r requirements.txt │ │
│ │ COPY . . │ │
│ │ CMD ["python", "main.py"] │ │
│ └─────────────────────────────────────────────────────┘ │
│ │
└─────────────────────────────────────────────────────────────┘Docker 核心命令
bash
# 构建镜像
docker build -t myapp:1.0.0 .
# 运行容器
docker run -d -p 8080:8080 --name myapp-container myapp:1.0.0
# 查看运行中的容器
docker ps
# 进入容器调试
docker exec -it myapp-container /bin/bash
# 查看日志
docker logs -f myapp-container
# 构建优化:减少镜像大小
# ❌ 错误:FROM ubuntu(太大,几十个 GB)
# ✅ 正确:FROM python:3.11-slim(几百 MB)
# 多阶段构建
FROM golang:1.21 AS builder
WORKDIR /app
COPY . .
RUN go build -o main
FROM alpine
COPY --from=builder /app/main /main
CMD ["/main"]
# 最终镜像只有几 MB(而不是几 GB)第2节:Kubernetes——容器编排的事实标准
问题:Docker 只能跑一个容器,生产环境要跑很多
┌─────────────────────────────────────────────────────────────┐
│ │
│ Docker Compose:管理多个容器(但不能跨机器) │
│ │
│ 生产环境需求: │
│ • 10 台服务器,每台跑 20 个容器 │
│ • 某个容器挂了,自动重启 │
│ • 某个服务器挂了,自动迁移容器 │
│ • 需要负载均衡 │
│ • 需要滚动更新 │
│ │
│ → 这些都需要 Kubernetes(K8s)来解决 │
│ │
└─────────────────────────────────────────────────────────────┘K8s 核心概念
┌─────────────────────────────────────────────────────────────┐
│ Kubernetes 核心对象 │
├─────────────────────────────────────────────────────────────┤
│ │
│ Pod:最小调度单元 │
│ → 一个 Pod 包含一个或多个容器 │
│ → 同一 Pod 内的容器共享网络和存储 │
│ → 通常一个 Pod 只跑一个容器 │
│ │
│ Deployment:管理 Pod 的副本数 │
│ → 定义:3 个副本 Pod │
│ → K8s 自动维护 3 个副本 │
│ → 支持滚动更新、回滚 │
│ │
│ Service:服务发现 + 负载均衡 │
│ → 给一组 Pod 一个固定 IP 和 DNS 名 │
│ → 自动负载均衡到多个 Pod │
│ │
│ ┌─────────────────────────────────────────────────────┐ │
│ │ Deployment:定义 Pod 模板 │ │
│ │ └─ ReplicaSet:管理 Pod 副本 │ │
│ │ └─ Pod × 3:实际运行的容器 │ │
│ │ │ │
│ │ Service:负载均衡到 3 个 Pod │ │
│ └─────────────────────────────────────────────────────┘ │
│ │
└─────────────────────────────────────────────────────────────┘Service 三种类型
┌─────────────────────────────────────────────────────────────┐
│ K8s Service 类型 │
├─────────────────────────────────────────────────────────────┤
│ │
│ ClusterIP(默认): │
│ → 集群内部访问,给其他服务用 │
│ → IP: 10.96.x.x(仅集群内可见) │
│ │
│ NodePort: │
│ → 通过节点 IP + 端口访问 │
│ → 每个节点暴露 30000-32767 端口 │
│ → 测试环境用 │
│ │
│ LoadBalancer: │
│ → 对接云厂商负载均衡器(AWS ELB / 阿里 SLB) │
│ → 生产环境推荐 │
│ → 自动创建外部可访问的 IP │
│ │
│ ┌─────────────────────────────────────────────────────┐ │
│ │ apiVersion: v1 │ │
│ │ kind: Service │ │
│ │ spec: │ │
│ │ type: LoadBalancer │ │
│ │ selector: │ │
│ │ app: order-service │ │
│ │ ports: │ │
│ │ - port: 80 │ │
│ │ targetPort: 8080 │ │
│ └─────────────────────────────────────────────────────┘ │
│ │
└─────────────────────────────────────────────────────────────┘滚动更新 vs 蓝绿部署 vs 金丝雀
┌─────────────────────────────────────────────────────────────┐
│ 部署策略对比 │
├─────────────────────────────────────────────────────────────┤
│ │
│ 滚动更新(Rolling Update): │
│ → 逐步替换旧版本 Pod → 新版本 Pod │
│ → 始终有 Pod 在运行,用户无感知 │
│ → 缺点:新旧版本同时存在,可能有兼容问题 │
│ │
│ ┌─────────────────────────────────────────────────────┐ │
│ │ v1 v1 v1 v1 → v2 v1 v1 v1 → v2 v2 v1 v1 │ │
│ │ → v2 v2 v2 v1 → v2 v2 v2 v2 │ │
│ └─────────────────────────────────────────────────────┘ │
│ │
│ 蓝绿部署(Blue-Green): │
│ → 准备一套完整的新版本(绿) │
│ → 流量一次性切换(旧=蓝 / 新=绿) │
│ → 回滚:一键切回 │
│ → 缺点:需要双倍资源 │
│ │
│ ┌─────────────────────────────────────────────────────┐ │
│ │ 旧版本 v1 (Blue) ────── 流量 ──▶ 新版本 v2 (Green) │ │
│ │ 如果有问题,一键切回 │ │
│ └─────────────────────────────────────────────────────┘ │
│ │
│ 金丝雀部署(Canary): │
│ → 先让少量用户(5%)使用新版本 │
│ → 观察没问题,逐步扩大比例(10% → 50% → 100%) │
│ → 风险最小 │
│ │
│ ┌─────────────────────────────────────────────────────┐ │
│ │ 95% v1 ───▶ │ ◀── 5% v2(灰度) │ │
│ └─────────────────────────────────────────────────────┘ │
│ │
└─────────────────────────────────────────────────────────────┘第3节:监控告警——问题发生后才知道
问题:用户投诉了,你才知道系统出问题了
┌─────────────────────────────────────────────────────────────┐
│ │
│ 凌晨 3 点,用户打电话投诉:APP 打不开。 │
│ │
│ 你开始排查: │
│ → 看日志?日志分散在 10 台服务器上 │
│ → 看数据库?不知道查什么 │
│ → 看监控?没有监控 │
│ │
│ 花了 2 小时,才发现是 Redis 挂了。 │
│ │
│ 如果有监控,应该在 Redis 挂的那一刻就报警。 │
│ │
└─────────────────────────────────────────────────────────────┘黄金指标
┌─────────────────────────────────────────────────────────────┐
│ 监控黄金指标(RED + USE) │
├─────────────────────────────────────────────────────────────┤
│ │
│ For Services(服务类): │
│ Rate(请求率):每秒处理的请求数 │
│ Errors(错误率):失败的请求比例 │
│ Duration(延迟):请求的响应时间(P50/P95/P99) │
│ │
│ For Systems(系统类): │
│ Utilization(利用率):资源使用百分比 │
│ Saturation(饱和度):资源排队情况 │
│ Errors(错误数) │
│ │
│ ┌─────────────────────────────────────────────────────┐ │
│ │ Prometheus + Grafana 监控方案: │ │
│ │ │ │
│ │ Prometheus(采集):定时拉取指标 │ │
│ │ Node Exporter(系统):CPU/内存/磁盘/网络 │ │
│ │ MySQL Exporter(数据库):QPS/连接数/慢查询 │ │
│ │ Redis Exporter(缓存):内存/命中率/连接数 │ │
│ │ │ │
│ │ Grafana(展示):仪表盘 + 告警 │ │
│ │ │ │
│ │ AlertManager(告警):邮件/钉钉/Slack/PagerDuty │ │
│ └─────────────────────────────────────────────────────┘ │
│ │
└─────────────────────────────────────────────────────────────┘第4节:CI/CD——自动化构建和部署
┌─────────────────────────────────────────────────────────────┐
│ CI/CD 流程 │
├─────────────────────────────────────────────────────────────┤
│ │
│ CI(持续集成): │
│ 代码提交 → 自动构建 → 自动测试 → 单元测试 → 代码扫描 │
│ → 每次提交都验证,不让问题累积 │
│ │
│ CD(持续交付/部署): │
│ 构建成功 → 自动部署到测试环境 → 自动部署到预发布 │
│ → 人工审批 → 自动部署到生产环境 │
│ │
│ ┌─────────────────────────────────────────────────────┐ │
│ │ GitHub Actions 示例: │ │
│ │ │ │
│ │ name: CI Pipeline │ │
│ │ on: push │ │
│ │ jobs: │ │
│ │ test: │ │
│ │ runs-on: ubuntu-latest │ │
│ │ steps: │ │
│ │ - uses: actions/checkout@v4 │ │
│ │ - run: pip install -r requirements.txt │ │
│ │ - run: pytest tests/ │ │
│ │ - run: pylint **/*.py # 代码检查 │ │
│ │ build: │ │
│ │ needs: test │ │
│ │ steps: │ │
│ │ - run: docker build -t myapp:${{ github.sha }} │ │
│ │ - run: docker push registry/myapp:${{ github.sha }} │ │
│ └─────────────────────────────────────────────────────┘ │
│ │
└─────────────────────────────────────────────────────────────┘升华:DevOps 的本质
┌─────────────────────────────────────────────────────────────┐
│ DevOps 的三个核心价值 │
├─────────────────────────────────────────────────────────────┤
│ │
│ 1. 自动化: │
│ 减少人工操作,减少人为错误 │
│ → Docker 消除环境差异 │
│ → CI/CD 消除部署人工 │
│ │
│ 2. 可观测性: │
│ 出现问题时能快速定位 │
│ → 日志(结构化日志) │
│ → 指标(Prometheus + Grafana) │
│ → 链路追踪(OpenTelemetry) │
│ │
│ 3. 快速反馈: │
│ 问题越早发现,修复成本越低 │
│ → 单元测试(代码提交时发现) │
│ → 集成测试(合并时发现) │
│ → 监控告警(生产时发现,但能快速响应) │
│ │
│ 一句话总结: │
│ DevOps 不是工具,是文化——让开发和运维不再是两个对立团队。 │
│ │
└─────────────────────────────────────────────────────────────┘"AI 可查 vs 必须理解"清单
AI 可查:
✅ Docker / Kubernetes 的详细命令参数
✅ Helm Chart 模板语法
✅ CI/CD 配置文件的具体语法
必须理解:
🔴 Docker 镜像和容器的区别
🔴 K8s Service 三种类型的应用场景
🔴 滚动更新 vs 蓝绿 vs 金丝雀的区别
🔴 监控的黄金指标(RED / USE)
🔴 为什么 K8s 能实现不停机发布学习状态:🟢 已完成 Backend 系列