接手一套陌生 CI/CD 平台:四步取证梳理全景拓扑(脱敏实录)
接手别人维护多年、文档不全、网络上还够不着的 CI/CD 平台,最忌上来就改。 这篇记录一次完整的接管梳理实录:平台横跨内外两个网络分区、四台 Jenkins 实例、425 个任务、20 条产品线(数据库安全/数据网关/安全审计/终端安全/备份等方向)。全部操作只读,没有改过任何配置——梳理清楚之前,不动生产是底线。敏感信息已全部脱敏:主机以 <占位符> 表示,仓库名、产品线、人名、凭据一概不出现。
一、起点:两份交接文档能给你什么
Section titled “一、起点:两份交接文档能给你什么”交接材料只有两份:一份配置手册(含大量截图)、一份设备台账(Excel)。细读后能拿到三类关键情报:
| 情报类型 | 能拿到什么 | 局限 |
|---|---|---|
| 系统地址 | 各平台入口 URL、FTP 制品库 | 手册可能过时(后面实测证实了) |
| 责任边界 | 每个阶段谁是主责谁是协助 | 只到角色级,不到系统级 |
| 操作方法 | 手动触发任务、查日志的入口 | 不涉及架构与数据流 |
设备台账的价值常被低估:编译机、KVM 宿主机、测试执行机的 IP/规格/用途表格,后面和 Jenkins 节点名逐一对照上了——这是“三方交叉验证”的一环。
但两份文档都没有回答最关键的问题:调度在哪、怎么串起来的、断了影响什么。这些只能靠自己取证。
二、四步取证法(全程只读)
Section titled “二、四步取证法(全程只读)”第一步:API 匿名探测——往往比想象中开放
Section titled “第一步:API 匿名探测——往往比想象中开放”拿到 Jenkins 地址列表后,先别急着要账号。Jenkins 的 /api/json 在不少企业实例上对匿名是可读的(管理员常放开只读)。实测结果:
- 两台在网 Jenkins 的任务树、节点列表、视图分组全部可匿名枚举:上游编译实例 197 个任务(194 个 Pipeline + 50 节点)、下游测试实例 228 个任务(213 个自由风格 + 36 节点)
whoAmI接口确认匿名身份;config.xml 这类深度配置返回 403——权限边界清晰
这一步拿到了“任务清单级”的画像:上游管编译打包(夜间定时阵型触发),下游管部署测试(纯调度触发、几乎无定时)——两台 Jenkins 是按流水线阶段分工的,不是测试/生产分离。这个认知直接纠正了文档阅读阶段的一个错误猜测。
第二步:宿主机只读勘察—— 设备台账的密码就是钥匙
Section titled “第二步:宿主机只读勘察—— 设备台账的密码就是钥匙”设备台账里记录了各主机的系统账号。用 SSH 登录后(严格 只读),一次勘察能拿到的比 API 多得多:
- JENKINS_HOME 里
jobs/、nodes/、plugins/、users/的真实规模 grep所有任务 config.xml,统计出定时触发阵型、Git 仓库引用分布、凭据 ID 引用频次——全部指向现役 GitLab,而手册写的旧地址只剩 6 处遗留引用(该机实测已不可达,实锤“手册过时”)- 节点名与设备台账的 IP 一一对应(
euler_build_<IP后缀>这类命名习惯帮了大忙)
第三步:顺着日志抓“看不见的主机”
Section titled “第三步:顺着日志抓“看不见的主机””手册里提到一个“调度程序”,但没说它跑在哪。两台 Jenkins 宿主机上都没有可疑进程——突破口在构建日志:运维任务的 console output 里明明白白记录着它向 http://<调度主机>:443/<路径>/ci_push 推消息。回宿主机一查 ss -tlnp:一个 Python 进程监听 443,工作目录就是某个内部仓库的部署目录。调度程序实体、源码仓、部署方式三点连成线。
第四步:源码对照——README 就是现成的架构文档
Section titled “第四步:源码对照——README 就是现成的架构文档”申请到代码仓只读权限后 clone 调度平台仓库,发现它的 README 写得极好:16 个 HTTP 接口、状态机设计(等待池 4 小时超时、同产品新包替换排队)、十步测试主流程、配置热加载机制一应俱全。手册里的每一条“玄学行为”都在代码里找到了出处。
再拿源码里的常量回查配置(内网桥接主机地址、双 FTP 端点),连设备台账上都没有的内网 FTP 主机都挖出来了。
交叉验证:为什么敢信
Section titled “交叉验证:为什么敢信”设备台账 IP ↔ Jenkins 节点名 ↔ 手册行为描述,三方吻合;构建日志、源码常量、配置文件互相印证。单一来源都可能有假,三方一致才敢当结论。
三、平台全景拓扑(脱敏版)
Section titled “三、平台全景拓扑(脱敏版)”━━━━━━━━━━ 外网区(办公测试侧)━━━━━━━━━━
代码层 编译层 调度层 环境层┌──────────┐ ┌─────────────┐ ┌──────────────┐ ┌────────────────┐│GitLab │ │Jenkins-A │ │ 调度程序 │ │ KVM 宿主机×3 ││<外网GitLab>│─>│:8080 编译侧 │ │ server.py:443│ │ (qcow2模板复制) ││ 平台仓+ │ │194 pipeline │<───│ 状态机: │─>│ 动态VM按需创建 ││ 用例仓群 │ │50 编译节点 │push│ ·等待池4h超时 │ │ IP/VNC 预分配 │└──────────┘ └──────┬──────┘ │ ·同产品替换排队│ └───────┬────────┘ │产物 └──────┬───────┘ │ ▼ │驱动 ▼ ┌─────────────┐ ┌──────┴───────┐ ┌────────────────┐ │FTP 制品中枢 │<───│ 授权/扫描调度 │ │Jenkins-B │ │<FTP制品库> │ └──────────────┘ │:8080 测试侧 │ │ 包/报告/授权 │ │213 freestyle │ └──────┬──────┘ │CI/Deploy 成对 │ ▼ └───────┬────────┘ ┌─────────────┐ │ │ 报告归档目录 │<──── 测试执行机×9 ────────────┘ └──────┬──────┘ ▼ 展示/通知层: 看板(每日拉FTP→HTML汇总→邮件) + 钉钉机器人(实时群通知)
━━━━━━━━━━ 内网区(生产研发侧)━━━━━━━━━━内网GitLab → 内网Jenkins+桥接代理(<内网桥接主机>) → 内网编译机×21 → 内网FTP │ client:443 与外网调度程序互通结构性认知两条(排查故障时决定先看哪边):
- 编译侧靠定时、测试侧靠调度。夜间编译阵型(0 点/1 点/2 点分组触发)出问题看 Jenkins-A 的定时任务;白天包“卡住不动”看调度程序状态机和等待池。
- FTP 制品库是全局咽喉:编译产物出、五类扫描报告归档、看板数据进、授权文件走,全经它。单点、无冗余。
四、流水线生命周期时序
Section titled “四、流水线生命周期时序”| 时刻 | 动作 | 要点 |
|---|---|---|
| T0 | 夜间定时触发编译任务 | 定时阵型错峰,避免节点 IO 争抢 |
| T1 | 编译节点拉流水线脚本+代码 | 脚本统一归档 GitLab,模板+产品目录 |
| T2 | 代码扫描随流水线执行 | SonarQube(Java/JS)+ TscanCode(C/C++) |
| T3 | 产品包外传 FTP | 包信息文件随传,是看板判“成败”的依据 |
| T4 | 编译机代理转发 ci_push 给调度程序 | 内外网桥接的关键链路 |
| T5 | 状态机入队 | 同产品新包替换排队;等待池 4h 超时丢弃 |
| T6 | 包外传校验 → ISO/BIN 打包 → checksec 检查 | 校验不过直接终止流程 |
| T7 | 动态环境:KVM 池复制模板建 VM | 配 IP/网关/盘/网卡,产品特例表驱动 |
| T8 | 取机器码→授权文件→FTP(现多改接口授权) | HA 主备环境有特例 |
| T9 | 调度部署任务 | 部署只到服务启动,不做任何测试 |
| T10 | 部署稳定后触发测试任务 | pytest → xml 报告 + Allure → FTP |
| T11 | 五类安全扫描(0~9 点窗口) | 不论测试成败都执行;绿盟有 IP 配额 |
| T12 | 环境清理(关闭/挂起动态 VM) | 可用运维任务恢复做问题分析 |
| T13 | 钉钉实时通知 + 次日看板汇总邮件 | xml 报告数据为准,Allure 仅展示 |
五、梳理中挖出的典型隐患(每个平台都值得自查)
Section titled “五、梳理中挖出的典型隐患(每个平台都值得自查)”- 手册指向的“主入口”已下线,但脚本里还留着 6 处旧地址引用——文档过时不可怕,可怕的是没人知道它过时了
- 调度程序以手工 SSH 会话进程运行(非 systemd/容器)——那个终端一断,全平台部署测试停摆
- 生产 Jenkins 容器用“backup”命名的镜像在跑——镜像管理规范缺失
- 两个任务的构建历史占掉实例磁盘 63%(112GB)——构建保留策略形同虚设
- 一个 JDK 压缩包被误建成 Jenkins 任务目录——目录被当网盘用
- 匿名 API 可枚举全部任务与节点——便利与暴露面是一体两面
- 几十处任务共享同一个节点 SSH 凭据——单一凭据暴露面过大
六、可复制的梳理清单
Section titled “六、可复制的梳理清单”- 先文档后系统:手册/台账细读一遍,列出“系统地址表 + 责任边界表 + 疑点清单”
- API 探测先行:
/api/json、/whoAmI、/computer/api/json匿名试一轮,能拿多少拿多少 - 台账 ↔ 节点名交叉对照:命名习惯(IP 后缀、用途前缀)是天然的映射线索
- 宿主机只读勘察:进程/端口/挂载/JENKINS_HOME 四板斧;
ss -tlnp找隐藏服务 - 构建日志当侦探小说读:console output 里有所有下游地址
- 源码对照收口:调度/编排类系统通常有配套仓库,README 常常就是没人维护的架构文档
- 全程只读,三方验证才下结论;产出一张“拓扑 + 生命周期 + 断链影响矩阵”作为接管总纲
接管不是推倒重来,是先画出它的心脏和血管。这张图画清楚之前,任何优化都是赌博。