Skip to content

第10章 CI/CD 基础与支持岗视角 【对应简历:技能第10条"熟悉 Git、Jenkins CI/CD 持续集成交付流程与 Ansible 自动化批量配置管理"】 ​

支持版定位:本章是"够用+诚实"章。你简历对 CI/CD 的动词是"熟悉",真实水位是课程实验 + 生产上配套过业务发布(不是流水线的建设者)。支持岗面试官问 CI/CD,多数不是考你搭流水线,而是考你发布失败时会不会判断"是应用问题还是发布问题"、发布窗口你该怎么配合——本章就按这个视角准备。

10.1 CI/CD 是什么、五大阶段 【必背】 ​

标准回答: CI/CD 我按"一条流水线五个阶段"来讲:提(提交代码)——开发把代码提交到 GitLab/Git 这类代码仓库;拉(拉取代码)——Jenkins 通过 Webhook 感知到提交,自动从仓库拉取最新代码;编(编译构建)——按项目类型编译打包,Java 出 war/jar、前端出 dist 静态文件,容器化项目在这一步打 Docker 镜像;测(自动化测试)——跑单元测试和集成测试,测试不过流水线直接终止,拦住有问题的代码;查(质量检查)——用 SonarQube 这类工具做静态代码扫描,看有没有安全漏洞和坏味道。CI 解决的是"代码怎么又快又稳地变成可部署的产物",CD 再往后接一步:产物自动部署到测试/预发/生产环境。我的理解不止是概念:移动云项目的业务发布我是配套方——应用以容器方式部署在我维护的 K8s 集群里,发布的最后一步(镜像拉取、滚动更新)发生在我的平台上,发布窗口我要盯集群资源、盯 Pod 滚动状态、发布异常时配合回滚。所以这条链上我最熟的是"最后一公里",前面几段是课程实验搭过 GitLab+Jenkins 的完整流程(见 10.3 的诚实口径)。

追问链:

  • 追问1:CI 和 CD 的区别?→ 答:CI(持续集成)关注"代码合进去之后自动构建和测试",目标是尽早发现集成问题,产出一个可信的制品;CD(持续交付/部署)关注"这个制品怎么自动、可控地到达生产环境",交付到人工点一下按钮为止叫持续交付,一键直达生产叫持续部署。两者的分界在于"制品"这个词:CI 的产出是制品,CD 的输入是制品。我在项目里感受最深的是制品管理——镜像打好推到私有仓库打上版本 tag,发布出问题就回滚到上一个 tag,这就是 CD 给运维的底气。
  • 追问2:Webhook 是什么?→ 答:是一种"事件反向通知"机制:我配置好 GitLab 仓库的 Webhook 指向 Jenkins 的地址,开发一 push,GitLab 就主动发一个 HTTP 请求告诉 Jenkins"有新提交了",Jenkins 不用轮询仓库。对运维的意义是排除法思维——如果"提交了但流水线没动",第一查 Webhook 配置和连通性(Jenkins 收到请求没有),第二查 Jenkins 任务本身,把"触发问题"和"构建问题"分开定位。

10.2 Git 必会命令与支持岗视角 【理解】 ​

标准回答: Git 我按三层说。日常层:clone 拉仓库、pull 更新、add/commit 提交、push 推送、log 看历史、diff 看改动——这六个命令覆盖日常 90% 的操作。分支层:branch 建分支、checkout/switch 切分支、merge 合并,常见模型是 master 主干保持可发布、feature 分支开发、release 分支发布。补救层:reset 回退提交(--soft 保留改动/--hard 彻底丢弃)、revert 生成一条"反向提交"更安全、stash 临时存工作现场。支持岗视角的真实用法有两个:一是看发布内容——发布出问题,git log 和 git diff 能告诉我们"这次上了什么改动",这是我给二线和开发提供的第一手信息;二是配置管理——集群的 YAML、脚本、文档我都放 Git 管理,改过什么、谁改的一目了然,这本身就是"变更可追溯"。我用的深度到"熟练使用+能讲清模型",没做过 Git 服务器运维(GitLab 的部署是课程实验做过),这个边界我主动说明。

追问链:

  • 追问1:merge 和 rebase 的区别?→ 答:merge 是把两条分支的改动"汇合"生成一个合并提交,历史是真实的网状结构;rebase 是把我的提交"搬到"目标分支末尾重放,历史变成一条直线更干净,但改写了提交历史。团队规范通常是:个人分支同步主干用 rebase 保持整洁,合入主干的正式合并用 merge 保留记录。我没在团队级规范制定里做过决策,这是我课程学习和团队文档里学到的实践口径。

10.3 Jenkins 与一条典型流水线 【理解·课程口径】 ​

标准回答: Jenkins 我课程实验里完整搭过一次:Java 环境装 Jenkins,装插件(Git、Pipeline、Maven),配凭据连 GitLab。它自己是 Java 写的 CI 服务器,核心概念两层:Job 是一个构建任务,FreeStyle 风格是页面上点选配置,适合简单场景;Pipeline 是用 Jenkinsfile(Groovy 语法的文本)把流程写成代码,好处是流程可版本化、可评审、可复制。一条典型的流水线长这样:stages 里依次是 Checkout(拉代码)→ Build(mvn package 编译)→ Image(docker build 打镜像打 tag)→ Push(推到 Harbor 私有仓库)→ Deploy(到测试环境部署验证),每一步失败都会终止并通知。我的诚实口径:这套我在课程环境端到端跑通过,也在生产上"消费"过它——公司发布时我负责的是 Jenkins 之后的环节(镜像到我集群的拉取与滚动更新、发布窗口保障、异常回滚配合),流水线本身的搭建和维护不是我在生产上的主责。支持岗如果被问"你们发布怎么上的线",我能把全链路讲清楚;如果被问"Jenkins 怎么装怎么调优",我会如实说明是课程级实践。

追问链:

  • 追问1:发布失败你怎么判断是代码问题还是发布问题?→ 答:我按四步分流:第一看发布记录——这次发布改了什么(新镜像 tag 对不对、配置有没有变更、是不是换了基础镜像);第二看现象范围——只这一个服务异常还是一批异常,单个服务多半是应用或配置,一批异常先怀疑环境和平台;第三看日志特征——启动即崩(ClassNotFound、配置项缺失)偏发布产物问题,运行一段时间后报错(连接超时、OOM)偏运行环境问题;第四看回滚对照——回滚到上一版本恢复正常就是本次变更引入的,回滚也异常就要往平台层查(镜像仓库、存储、网络)。这套分流我在移动云的发布窗口实战用过,核心思想是"变更三角":任何异常先问代码、配置、环境这三者谁变了。
  • 追问2:蓝绿发布和灰度发布的区别?→ 答:蓝绿是两套对等环境,新版本部署到蓝(或绿)另一套,验证后把流量整体切过去,出问题整流切回——切换快但资源要双份;灰度(金丝雀)是让一小部分流量先走新版本(比如 5%→20%→100%),按批观察指标再放量,出问题影响面小但周期长。K8s 里灰度天然好做——Deployment 滚动更新本身就是逐批替换 Pod,配合就绪探针保证流量只进就绪的实例;更精细的按比例分流要靠 Ingress 或服务网格。我项目里的实践是滚动更新+就绪探针这一层,蓝绿灰度是概念与选型层面的理解。

10.4 Ansible 基础 【理解·课程口径】 ​

标准回答: Ansible 我按"三个一"讲:一个架构特点——无 Agent,控制机通过 SSH 直连被管节点执行任务,被管端什么都不用装,这点比 SaltStack/Puppet(要装客户端)轻得多,也意味着只要 SSH 通、Python 在(2.7/3.x),Ansible 就能用;一个核心文件——inventory 主机清单,把机器按分组管理([web]、[db]),命令和剧本都按组执行;一套剧本语法——playbook 是 YAML 写的任务清单,task 按顺序执行,每个 task 调一个模块(shell 执行命令、copy 分发文件、yum 装包、service 管服务、template 渲染配置),支持 handlers(变更后触发的重启动作)和 roles(按目录结构复用)。它最重要的特性是幂等性:多数模块描述的是"期望状态"而不是"执行动作"——同一本 playbook 跑十遍,结果一致,不会重复安装已经装好的包。我的课程实践:写过部署 Nginx 的 playbook(装包、渲染配置文件、启动服务、验证端口),生产上我配套用过的场景是集群节点的标准化初始化——把初始化步骤脚本化本身就是 IaC 思想,和 Ansible 的状态化理念一脉相承。支持岗视角:如果客户环境要用 Ansible 批量改配置,我能看懂 playbook、能执行、能排查失败原因(通常先看报错发生在哪个 task、SSH 通不通、权限够不够),从零编写复杂 playbook 不是我的强项,我不装懂。

追问链:

  • 追问1:Ansible 幂等性怎么理解?command 模块幂等吗?→ 答:幂等指"执行一次和执行 N 次结果相同"。Ansible 的多数模块(yum、copy、service)是状态化实现——它先检查当前状态,符合期望就跳过,所以天然幂等;但 command/shell 模块是"盲目执行",跑几次就执行几次,不幂等。实践上要么用 state 化的模块替代,要么在 shell 里加 creates/removes 参数做条件执行。这个区分我在写巡检脚本时就想过——巡检是"只读"天然幂等,部署脚本要刻意设计成可重跑。
  • 追问2:playbook 执行报错你怎么排查?→ 答:三板斧:一看报错在哪个 task、哪个主机——Ansible 的输出会明确到 host 和 task 名,先确认是个别主机还是全部(个别主机查那台的环境差异,全部主机查剧本本身);二用 -v/--check——--check 是干跑模式只报告会改什么不真改,用来验证剧本安全性和预期;三看连接层——UNREACHABLE 类报错先查 SSH 连通、密钥、sudo 权限,这类占失败的大头。课程实验里我踩过的典型是密钥权限太开放被 SSH 拒绝(chmod 600 解决)和 Python 解释器路径问题。

10.5 支持岗与发布窗口的配合纪律 【必背】 ​

标准回答: 这是我本章最想讲的实战点:发布窗口里支持/运维不是旁观者,我的纪律是"事前三确认、事中三盯、事后三验"。事前三确认:确认发布内容和影响范围(哪些服务、哪些节点、预计时长)——影响面决定我值班的警觉等级;确认回滚方案(上一个稳定版本号、回滚步骤、多久能回);确认集群资源水位(滚动更新需要缓冲资源,资源紧张要提前腾)。事中三盯:盯滚动更新进度(新 Pod 起没起、就绪探针过没过、有没有 CrashLoop);盯业务指标(错误率、延迟有没有抬头,抬头立即叫停);盯告警通道(发布期的每条告警都要和发布关联判断)。事后三验:业务验证(让应用方或自己实际请求验证功能,不只看监控变绿);指标对比(和发布前基线比,延迟、错误率有没有劣化趋势);记录归档(发布时间线写进工单,异常处理过程沉淀成复盘)。这套纪律我在移动云项目多次发布窗口执行过——有一次发布后 Pod 反复重启,我按"退出码 137=OOM"快速定位是新版本内存限额不足,配合开发调大 limits 后恢复,整个过程十分钟闭环,就是因为事前把回滚方案和限额基线都确认过。支持岗的价值不在"会不会搭流水线",而在发布这条最危险的链路上,你能不能让每一步都有人盯着、出了事有人兜着。

追问链:

  • 追问1:发布过程中业务方突然说"现在不能发,客户在用",怎么处理?→ 答:立即暂停未执行的批次,已滚动的部分先观察——K8s 滚动更新是逐批的,暂停时已有的新版本 Pod 在跑,我要评估"半新半旧"状态的风险:如果新旧版本接口兼容,保持现状等窗口;如果不兼容(库表变更、接口变更),和开发立即决策是继续推完还是回滚已更新部分。然后把变更窗口的沟通问题记录下来——这次暴露的是"发布前和业务方的确认环节缺失",复盘时把"发布前业务方确认"固化进 checklist。处理原则是先止险、再追因,不当场追责。
  • 追问2:如果面试官继续问"你们发布是运维发布还是开发自己发"?→ 答:如实说:我们公司规模小(15 人左右),发布是开发和运维协同——开发构建出镜像推到仓库,容器平台的发布操作(改镜像 tag、滚动更新)由我做或我授权开发在 Kuboard 上操作,权限和审计可控。这种模式下我更强调"平台护栏":RBAC 按命名空间分权、生产环境操作留痕、发布走我定的窗口纪律。小公司的全栈协作和大公司的分工制各有利弊,我都经历过(银行项目是大团队分层协作,外包项目是小团队全栈),这个对比本身是我在面试里愿意主动讲的。

本章案例 ​

【真实项目】发布窗口 OOM 十分钟闭环 移动云集群某业务夜间发布,新 Pod 起来几秒就重启。我作为平台支持按流程处理:kubectl get pods 看到重启次数上涨→kubectl describe pod 看 Last State: Terminated, Reason: OOMKilled, Exit Code 137→确认是新版本内存用量超过 limits(上一版本 512M 够用,新版本功能增加内存翻倍)→两种方案:调大 limits 或回滚镜像。和开发确认调大 limits 到 1G 是正解(回滚只是掩盖)→改 YAML apply→Pod 稳定 Running→验证业务正常→写复盘:新版本发布前要评估资源需求变化,把"资源基线确认"加进发布 checklist。全程 10 分钟,业务影响为零——因为滚动更新只影响部分副本,且我盯得紧。面试讲这个案例的核心不是"我修了 OOM",是"发布窗口的支持纪律让问题在影响业务前被抓住"。

【经典故障】回滚之后还是异常(话术库变体) 某服务发布失败回滚到旧版本,但服务依然异常。排查发现回滚只回滚了应用镜像,但本次发布同时改了 ConfigMap(数据库连接指向新库)——配置和应用版本不匹配导致连接失败。解决:配置一并回滚,恢复正常。教训:发布是"应用+配置+依赖"的整体,回滚必须三者对齐;根因是发布清单里没有把配置变更列进去。预防:发布 checklist 增加"本次变更涉及哪些对象(镜像/配置/密钥/库表)"一项。这个案例是话术库经典"变更三角"的标准故事,面试回答"回滚了为什么还不行"这类问题时直接可用。

章末自测(一句话答案) ​

  1. CI/CD 五阶段?→ 提、拉、编、测、查,从提交代码到质量检查的自动化流水线。
  2. Webhook 的作用?→ 代码仓库主动通知 Jenkins 触发构建,免轮询。
  3. merge 和 rebase 区别?→ merge 保留网状历史,rebase 重放成直线(改写历史)。
  4. Jenkinsfile 是什么?→ 用 Groovy 把流水线写成代码,可版本化可评审。
  5. 制品库举例?→ Harbor 存 Docker 镜像、Nexus 存 jar,按版本 tag 管理。
  6. Ansible 为什么无 Agent?→ 通过 SSH 直连执行,被管端只需 SSH 和 Python。
  7. playbook 幂等性?→ 状态化模块描述期望状态,重复执行结果一致。
  8. command 模块幂等吗?→ 不幂等,盲目执行,需 creates 参数或状态模块替代。
  9. 蓝绿 vs 灰度?→ 蓝绿整体切换双份资源,灰度小比例放量周期长影响小。
  10. 发布失败第一件事?→ 看变更三角:代码、配置、环境谁变了,先分流再动手。
  11. 回滚后仍异常想什么?→ 回滚不完整——配置、密钥、库表等依赖对象没一起回。
  12. 滚动更新中谁保证流量不进未就绪 Pod?→ 就绪探针(readinessProbe),未就绪摘出 Service 端点。