Skip to content

DevOps 从零到生产级掌握

DevOps 不是“会用 Docker 命令”或“会点 Jenkins 发布按钮”。商业项目真正需要的是:代码能稳定构建,制品能追踪,配置能隔离,发布能回滚,服务能观测,故障能定位,权限和密钥不乱放。

一句话建立主线:

DevOps 是把开发、测试、构建、制品、部署、运行、监控、告警、回滚、复盘连接成闭环,让软件可以稳定、可重复、可审计地交付到生产环境。

学习目标

学完这一页,你要能做到:

  1. 说清楚代码从提交到用户访问的全过程。
  2. 区分源码、构建产物、镜像、容器、Pod、服务入口。
  3. 解释 Docker 镜像分层、容器隔离、端口映射、数据卷和网络。
  4. 解释 Nginx 反向代理、负载均衡、限流、HTTPS 和静态资源缓存。
  5. 解释 Jenkins Pipeline 如何拉代码、测试、打包、构建镜像、部署和回滚。
  6. 解释 Kubernetes 中 Pod、Deployment、ReplicaSet、Service、Ingress、ConfigMap、Secret、Probe、Volume 的关系。
  7. 能写最小 Dockerfile、docker-compose、Jenkinsfile、K8s Deployment/Service YAML。
  8. 能排查“服务访问不了、发布失败、Pod 起不来、接口变慢、磁盘打满、配置不生效、健康检查失败”。
  9. 能把 DevOps 用到订单、支付、采集、搜索、网关、后台管理等商业系统。

如果要按“零基础能学会、面试能讲清、生产能排查”的标准验收,请配合阅读 DevOps 从零到精通验收清单。本页负责串主线,验收清单负责把 Docker、Nginx、Jenkins、Kubernetes、发布回滚和排障拆成可检查的学习目标。

全链路流程

mermaid
flowchart TD
    A["开发提交代码"] --> B["Git 仓库"]
    B --> C["CI 触发流水线"]
    C --> D["编译和单元测试"]
    D --> E["打包产物<br/>jar 或 dist"]
    E --> F["构建 Docker 镜像"]
    F --> G["推送镜像仓库"]
    G --> H["部署到 Kubernetes"]
    H --> I["Pod 启动和健康检查"]
    I --> J["Service 提供集群内访问"]
    J --> K["Ingress 或 Nginx 暴露入口"]
    K --> L["用户访问服务"]
    L --> M["日志、指标、链路追踪"]
    M --> N["告警、回滚、复盘"]

这条链路里,任何一层出问题,表现都可能是“访问不了”。所以排查不能只盯应用日志,要先确定请求走到了哪一层。

第一层:从源码到构建产物

源码不能直接发布到生产。生产运行的应该是可重复构建出来的产物,例如:

项目类型构建命令产物
Spring Bootmvn clean packageapp.jar
Vue/VitePressnpm run builddist 静态文件
Go 服务go build二进制文件
Python 服务构建镜像或打包依赖镜像或 wheel

为什么不能手动复制代码到服务器:

  1. 服务器环境不可控,同一份代码在不同机器表现可能不同。
  2. 依赖版本可能漂移。
  3. 无法审计这次发布来自哪个提交。
  4. 出问题时不知道该回滚到哪个版本。

最小构建脚本:

bash
#!/usr/bin/env bash
set -e

git rev-parse --short HEAD
mvn clean test package
ls -lh target/*.jar

set -e 的作用是前一步失败后立即停止。如果不停止,测试失败也继续发布,生产风险会非常高。

第二层:Docker 镜像和容器

镜像是只读模板,容器是镜像运行起来后的进程环境。

mermaid
flowchart TD
    A["Dockerfile"] --> B["docker build"]
    B --> C["镜像 image"]
    C --> D["docker run"]
    D --> E["容器 container"]

镜像为什么有分层

Dockerfile 每条关键指令通常形成一层。相同层可以复用缓存,减少构建时间和传输体积。

dockerfile
FROM eclipse-temurin:8-jre
WORKDIR /app
COPY target/app.jar /app/app.jar
EXPOSE 8080
ENTRYPOINT ["java", "-jar", "/app/app.jar"]

这里用 JDK8 运行时是因为很多企业项目仍以 JDK8 为主。学习 DevOps 时不要只看最新版本,生产中常见的是 JDK8、JDK11、JDK17 混用。

容器不等于虚拟机

容器本质上仍是宿主机上的进程,只是通过 namespace 做隔离,通过 cgroup 做资源限制,通过镜像层提供文件系统。

概念解决什么问题不理解会怎样
namespace隔离进程、网络、挂载点误以为容器是完整虚拟机
cgroup限制 CPU、内存容器 OOM 不知道为什么
image layer复用文件系统层镜像越打越大
volume持久化数据容器删了数据也没了
bridge network容器间通信服务连不上依赖

最小运行 Demo

bash
docker build -t order-api:1.0.0 .
docker run -d --name order-api -p 8080:8080 \
  -e SPRING_PROFILES_ACTIVE=prod \
  order-api:1.0.0
docker logs -f order-api
curl http://127.0.0.1:8080/actuator/health

常见坑:

现象常见原因排查命令
容器启动后马上退出入口命令错误、应用启动失败docker logs 容器名
本机访问不到端口没有 -p 映射docker ps
配置没生效环境变量名或 profile 错docker inspect
容器内连不上外部 DB网络、防火墙、地址写 localhostdocker exec 进入容器测试
磁盘越来越大日志无限写、镜像没清理docker system df

第三层:Docker Compose

Compose 适合本地开发、测试环境或单机部署,把多个容器组合起来。

mermaid
flowchart TD
    A["Compose项目"] --> B["order-api"]
    A --> C["mysql"]
    A --> D["redis"]
    B --> E["服务名DNS访问mysql和redis"]
    C --> F["Secret提供初始化密码"]
    C --> G["Named Volume保存数据"]
    C --> H["Healthcheck表达启动状态"]

完整配置不应使用明文root密码,也不应默认把MySQL、Redis端口暴露到所有宿主机接口。请完成 Compose商业栈DemoMySQL容器化Demodepends_on 和健康检查只改善初始顺序,生产代码仍要有连接超时、退避重试和连接池恢复。

第四层:Nginx 入口层

Nginx 常见职责:

  1. 反向代理:把外部请求转发给后端服务。
  2. 负载均衡:多个后端实例分摊流量。
  3. 静态资源:直接返回前端文件、图片、下载文件。
  4. HTTPS 终止:处理 TLS 证书。
  5. 限流:保护后端不被突发流量打垮。
  6. 缓存:缓存低频变化内容。
mermaid
flowchart TD
    A["用户请求"] --> B["Nginx"]
    B --> C{"路径判断"}
    C -- "/api" --> D["后端服务集群"]
    C -- "/static" --> E["静态资源目录"]
    C -- "HTTPS" --> F["证书和 TLS"]

最小反向代理:

nginx
upstream order_api {
    server 10.0.0.11:8080;
    server 10.0.0.12:8080;
}

server {
    listen 80;
    server_name example.com;

    location /api/ {
        proxy_pass http://order_api/;
        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
    }
}

如果不设置 X-Forwarded-For,后端看到的可能只有 Nginx IP,审计、风控、限流都会受影响。

Nginx 排查顺序

现象排查点
404location 是否匹配、静态目录是否存在
502后端服务不可达、端口不通、upstream 错
504后端超时、网关超时太短、服务太慢
客户端真实 IP 丢失请求头没有透传
上传大文件失败client_max_body_size 太小
接口被打爆没有限流、没有连接数限制

第五层:Jenkins Pipeline

Jenkins 不只是“点按钮发布”,核心是把发布过程变成可审计的流水线。

mermaid
flowchart TD
    A["拉代码"] --> B["编译"]
    B --> C["测试"]
    C --> D["构建镜像"]
    D --> E["推送镜像"]
    E --> F["部署"]
    F --> G["健康检查"]
    G --> H{"是否成功"}
    H -- "成功" --> I["通知"]
    H -- "失败" --> J["回滚或停止发布"]

最小 Jenkinsfile:

groovy
pipeline {
  agent any

  environment {
    APP_NAME = 'order-api'
    REGISTRY = 'registry.example.com/backend'
    IMAGE_TAG = "${env.BUILD_NUMBER}"
  }

  stages {
    stage('Checkout') {
      steps {
        checkout scm
      }
    }

    stage('Test and Package') {
      steps {
        sh 'mvn clean test package'
      }
    }

    stage('Build Image') {
      steps {
        sh 'docker build -t $REGISTRY/$APP_NAME:$IMAGE_TAG .'
      }
    }

    stage('Push Image') {
      steps {
        sh 'docker push $REGISTRY/$APP_NAME:$IMAGE_TAG'
      }
    }

    stage('Deploy') {
      steps {
        sh 'kubectl set image deployment/order-api order-api=$REGISTRY/$APP_NAME:$IMAGE_TAG'
        sh 'kubectl rollout status deployment/order-api --timeout=120s'
      }
    }
  }
}

生产注意:

  1. 凭据必须放 Jenkins Credentials,不要写在 Jenkinsfile。
  2. 镜像标签不要只用 latest,要用版本号、构建号或 Git commit。
  3. 发布后必须做健康检查。
  4. 失败要能停止或回滚。
  5. 流水线日志不能打印密码、token、私钥。

第六层:Kubernetes 核心对象

K8s 用来管理容器集群。它解决的是:多实例、自动拉起、滚动更新、服务发现、配置管理、扩缩容和故障恢复。

mermaid
flowchart TD
    A["Deployment"] --> B["ReplicaSet"]
    B --> C["Pod 1"]
    B --> D["Pod 2"]
    B --> E["Pod 3"]
    F["Service"] --> C
    F --> D
    F --> E
    G["Ingress"] --> F
    H["ConfigMap 和 Secret"] --> C
对象作用初学者要记住
Pod最小调度单位容器运行在 Pod 里
Deployment管理副本和发布一般不要直接手写裸 Pod
ReplicaSet维持副本数通常由 Deployment 管
Service稳定访问入口Pod IP 会变,Service 名稳定
Ingress集群外入口通常配合 Nginx Ingress
ConfigMap普通配置不放密码
Secret敏感配置仍要结合权限和加密
Probe健康检查决定是否接流量或重启
Volume持久化数据Pod 重建后数据不丢

最小部署:

yaml
apiVersion: apps/v1
kind: Deployment
metadata:
  name: order-api
spec:
  replicas: 3
  selector:
    matchLabels:
      app: order-api
  template:
    metadata:
      labels:
        app: order-api
    spec:
      containers:
        - name: order-api
          image: registry.example.com/backend/order-api:1.0.0
          ports:
            - containerPort: 8080
          env:
            - name: SPRING_PROFILES_ACTIVE
              value: prod
          readinessProbe:
            httpGet:
              path: /actuator/health/readiness
              port: 8080
            initialDelaySeconds: 20
            periodSeconds: 5
          livenessProbe:
            httpGet:
              path: /actuator/health/liveness
              port: 8080
            initialDelaySeconds: 60
            periodSeconds: 10
---
apiVersion: v1
kind: Service
metadata:
  name: order-api
spec:
  selector:
    app: order-api
  ports:
    - port: 80
      targetPort: 8080

为什么要 readiness 和 liveness 分开:

探针表示什么失败后果
readiness是否准备好接流量Service 暂时不转发给它
liveness进程是否活着K8s 重启容器

如果把慢启动服务的 liveness 配太激进,应用还没启动完就被反复杀掉,会进入 CrashLoopBackOff。

第七层:灰度发布和回滚

生产发布不能只追求“快”,还要能控制风险。

mermaid
flowchart TD
    A["新版本镜像"] --> B["少量实例或少量流量"]
    B --> C["观察错误率和延迟"]
    C --> D{"指标正常"}
    D -- "是" --> E["扩大流量"]
    D -- "否" --> F["回滚旧版本"]

K8s 回滚命令:

bash
kubectl rollout history deployment/order-api
kubectl rollout undo deployment/order-api
kubectl rollout status deployment/order-api

回滚依赖一个前提:旧镜像还在,配置兼容,数据库变更可回退或向前兼容。很多事故不是代码不能回滚,而是数据库表结构已经不可逆。

第八层:可观测性

线上系统至少要有三类证据:

类型回答的问题例子
日志某次请求具体发生了什么异常堆栈、业务参数、traceId
指标系统整体是否健康QPS、P99、错误率、CPU、内存
链路追踪请求经过哪些服务网关 -> 订单 -> 库存 -> 支付
mermaid
flowchart TD
    A["用户请求"] --> B["网关生成 traceId"]
    B --> C["订单服务"]
    C --> D["库存服务"]
    C --> E["支付服务"]
    C --> F["写日志和指标"]
    F --> G["日志平台和监控系统"]

没有可观测性会怎样:

  1. 用户说慢,但不知道哪个接口慢。
  2. 接口报错,但没有请求上下文。
  3. 发布后错误率升高,但没有自动告警。
  4. 多服务调用失败,只能靠猜。

商业项目场景

订单系统发布

订单系统通常涉及订单、库存、支付、MQ 和数据库。发布时要重点关注:

  1. 数据库变更要先兼容旧代码。
  2. 消息格式要兼容旧消费者。
  3. 支付回调接口不能随意中断。
  4. 发布后观察错误率、支付成功率、订单状态卡住数量。
  5. 回滚时不能让订单状态机出现逆向流转。

医疗数据采集平台

采集平台通常有设备接入、数据清洗、异步入库、文件归档和查询服务。DevOps 重点:

  1. 采集网关要滚动发布,避免大量设备同时断连。
  2. 原始报文和清洗结果要有日志和归档。
  3. 消息队列堆积要告警。
  4. 数据库连接池、磁盘、对象存储要监控。
  5. 配置变更要可审计,避免采集规则误改。

生产排查总流程

mermaid
flowchart TD
    A["线上故障"] --> B{"用户表现"}
    B -- "访问不了" --> C["查 DNS、Nginx、Ingress、Service"]
    B -- "接口报错" --> D["查应用日志和依赖状态"]
    B -- "接口变慢" --> E["查 P99、线程池、DB、Redis、MQ"]
    B -- "发布失败" --> F["查流水线、镜像、权限、K8s 事件"]
    B -- "Pod 起不来" --> G["查 describe、logs、探针、资源"]
    C --> H["确认请求到达哪一层"]
    D --> I["根据 traceId 找完整链路"]
    E --> J["定位瓶颈层而不是盲目扩容"]
    F --> K["停止发布或回滚"]

常用命令:

bash
kubectl get pod -n prod
kubectl describe pod order-api-xxx -n prod
kubectl logs order-api-xxx -n prod --tail=200
kubectl get events -n prod --sort-by=.metadata.creationTimestamp
kubectl rollout status deployment/order-api -n prod
kubectl top pod -n prod

面试标准回答

DevOps 是什么

text
DevOps 是把开发、测试、构建、部署、运行、监控和反馈连接起来的工程实践。它的目标不是单纯自动发布,而是让软件交付可重复、可追踪、可回滚、可观测,减少环境差异和人工操作风险。

Docker 和虚拟机有什么区别

text
虚拟机虚拟完整操作系统,隔离强但启动慢、资源重;Docker 容器共享宿主机内核,通过 namespace 和 cgroup 隔离进程、网络和资源,启动快、镜像轻,适合应用交付和弹性部署。但容器不是完整虚拟机,数据持久化、网络和资源限制需要单独设计。

Kubernetes 为什么需要 Service

text
Pod 是动态的,重建后 IP 会变化。Service 提供稳定的访问入口,通过标签选择一组 Pod,并把流量转发到健康 Pod。没有 Service,调用方需要感知 Pod IP 变化,服务发现和负载均衡都会很困难。

发布失败怎么处理

text
先停止继续放量,确认失败发生在构建、镜像推送、部署、启动、健康检查还是流量入口。再看流水线日志、镜像标签、K8s events、Pod logs 和探针状态。若已经影响生产,优先回滚到上一稳定版本,同时保留现场证据再分析根因。

关联知识点

知识点继续学习
DevOps 总览运维工具
从零到精通验收DevOps 从零到精通验收清单
商业场景训练营DevOps 商业场景训练营
Docker 入门Docker 入门路线
Docker第一次运行CLI、hello-world、run、端口、日志、可写层与Volume实验
Docker安装与权限组件、仓库签名、systemd、rootless和升级
Docker daemon配置配置来源、data-root、日志、网络、代理、安全变更与回滚
Docker命令体系对象、生命周期、诊断与安全清理
Docker底层原理namespace、cgroup、OverlayFS与生命周期
DockerfileDockerfile构建原理、JDK 8/17与生产镜像
Docker Compose项目模型、生命周期、依赖健康与商业编排
Spring Boot容器化JDK 8/17、资源预算、探针和优雅停机
MySQL容器化初始化、Volume、内存、备份恢复和升级
Redis容器化ACL、RDB/AOF、内存预算、备份与高可用边界
Nginx容器化启动链、配置挂载、反向代理、TLS、优雅重载与排障
Docker生产排障按状态、网络、资源、存储和事故取证的Runbook
Docker容器信息容器状态、inspect、资源与日志
Docker网络原理namespace、veth、bridge、DNS、SNAT与端口发布
Docker存储原理可写层、Volume、Bind、权限、备份与恢复
NginxNginx 总览
Nginx事件模型Master、Worker、epoll、状态机、连接容量与平滑reload
Nginx配置匹配listen、server_name、location、rewrite、静态文件与proxy_pass全过程
Nginx 负载均衡算法、健康判断、重试幂等、连接复用、动态节点与故障排查
Nginx限流rate、burst、delay、并发、真实IP、多实例和商业策略
Nginx日志排障Request ID、分段耗时、499/502/504、轮转和生产取证
Nginx代理缓存Key、TTL、stale、缓存锁、多实例与一致性
Jenkins PipelineCPS、Agent、并发、凭据、制品、审批与可靠发布
Jenkins执行架构Controller、Agent、Queue、Executor、Workspace与制品生命周期
Jenkins Shared Library加载、信任、版本、API、测试与多项目升级治理
Jenkins商业发布不可变制品、数据库兼容、灰度、指标闸门、多对象回滚与前滚
K8s 从零入口对象心智模型、第一个应用、执行链路、故障实验与完整学习路线
K8s 架构API请求、控制循环、调度、CRI/CNI/CSI与Pod创建全过程
K8s 工作负载Deployment滚动更新、优雅终止、StatefulSet、DaemonSet与批任务
K8s 网络Pod网络、Service、EndpointSlice、DNS、kube-proxy与NetworkPolicy
K8s IngressIngressClass、Controller、Host/Path、TLS与4xx/5xx排障
K8s 配置与密钥ConfigMap/Secret注入、投射更新、加密、权限与零停机轮换
K8s 存储PV/PVC、StorageClass、CSI供应挂载、扩容、快照与恢复
K8s 探针kubelet执行、Startup门控、Readiness流量与Liveness重启全过程
K8s HelmChart、Values、模板渲染、Release、Hook、CRD与生产发布
K8s 可观测性日志、指标、Trace、Event、资源口径与生产排障证据链
K8s 面试题面试题

本章小结

DevOps 的核心不是堆工具,而是把软件交付变成闭环:源码可构建,产物可追踪,镜像可复现,配置可隔离,发布可回滚,服务可观测,故障可定位。小白学习时要先把“代码怎么变成线上服务”这条链路走通,再逐个深入 Docker、Nginx、Jenkins 和 Kubernetes。