附录:一次真实搭建的全过程记录与故障复盘——那些教程不会告诉你的 11 个坑
附录一次真实搭建的全过程记录与故障复盘——那些教程不会告诉你的 11 个坑前面 9 篇讲的是应该怎么做。这一篇讲的是实际发生了什么。我用 4 台华为云 ECS在不到 2 小时的窗口期里从零搭一套 GitLab Jenkins Ansible 的持续交付台。过程中失败了 11 次其中 3 次是方案级返工整个安装路线推倒重来1 次是把我彻底挡在门外的网络故障。我把每一次失败的原始报错、排查路径、根因判断和最终解法都原样记下来。如果你只想看一键成功的教程前 9 篇够了如果你要在真实环境里干这件事这一篇的价值可能比前 9 篇加起来还大。一、约束条件为什么这是一次高压实战先说清楚前提否则很多决策看起来会很奇怪。约束具体情况带来的影响时间窗口机器可用时长1 小时 50 分钟没有慢慢查文档的余地失败要在 2 分钟内决定修还是换方案带宽公网 5 Mbit/sGitLab 1.3 GB 的包理论下载 ≥ 35 分钟占掉三分之一窗口网络位置本地 Windows → 公网 → 华为云北京四每一次交互都受运营商链路影响操作方式纯 SSH无控制台、无 VNC一旦 SSH 不通等于完全失联机器规格FlexusX 8 vCPU / 16 GB × 4Ubuntu 24.04内存够但 GitLab 全家桶默认配置仍然吃紧关键决策一所有操作脚本化不手敲。时间窗口太短手敲命令的最大问题不是慢而是失败后无法精确重放。所以第一件事不是装 GitLab是写一个远程执行器。关键决策二所有脚本幂等。因为一定会失败一定会重跑。不幂等的脚本重跑一次就会制造新的脏状态。二、真实时间线22:15 拿到 4 台机器开始探活 22:21 写完 rx.pyparamiko 并行执行器 00-base.sh4 节点并行初始化 —— 成功 22:22 GitLab apt 源方案 —— 失败 #1 #2 22:25 n3/n4 目标运行环境JRE/Nginx/systemd —— 成功 22:28 GitLab 改 deb 直装方案开始下载 1.3G —— 进行中 22:29 n2 生成 ed25519 部署密钥并分发到 n1/n3/n4 —— 成功 22:34 Jenkins apt 源方案 —— 失败 #4 22:36 n4 蓝绿双实例blue 8081 / green 8082 —— 成功 22:37 Jenkins deb 装完但起不来 —— 失败 #5 22:38 Java 21 适配 —— 成功Jenkins 8080 返回 200 22:40 Jenkins CLI 装插件 —— 失败 #6 #7 #8 22:43 GitLab deb 包校验发现截断 —— 失败 #3 22:45 断点续传 SHA256 校验重下update-center 手动注入 22:52 **本地到 4 台机器全部失联** —— 失败 #9 #10 #11 23:05 链路诊断确认安全组来源白名单静默丢包 23:1x 机器停机/释放转入交付整理一句话总结基础设施层网络、目录、systemd、密钥、蓝绿骨架100% 完成软件安装层因为镜像源和网络问题反复返工最后倒在了网络出口 IP 变更上。三、失败 #1 / #2GitLab 的 apt 源方案现象配置好镜像源后apt-getupdate# ...# W: GPG error: https://mirror/gitlab/gitlab-ce/ubuntu noble InRelease:# The following signatures were invalid: NODATA 1 NODATA 2# E: The repository ... noble InRelease is not signed.apt-getinstall-ygitlab-ce# E: Unable to locate package gitlab-ce排查两个报错其实是同一个因果链NODATA说明InRelease文件下载到了但内容不是有效的 PGP 签名数据——大概率是镜像站返回了一个 HTML 错误页或空文件签名校验失败 → apt 拒绝使用该仓库 → 包索引根本没建立 →Unable to locate package是必然结果。用curl -I直接看那个 InRelease 的 URL返回的Content-Type不是application/pgp-signature实锤。根因镜像站对gitlab-ce这个第三方仓库的同步不完整或 noble 发行版目录未建立。这类第三方 repo 的镜像同步质量普遍不如官方 Ubuntu 源。解法与思考放弃 apt改 deb 直装。这个决策的依据是GitLab Omnibus 包是自包含的——它把 PostgreSQL、Redis、NGINX、Puma、Sidekiq 全打进了一个 deb 里几乎不依赖系统 apt 源。既然 apt 唯一的价值依赖解析在这里不成立那就没必要为一个坏掉的源纠缠。# 南京大学镜像直接取 debURLhttps://mirror.nju.edu.cn/gitlab-ce/ubuntu/pool/noble/main/g/gitlab-ce/gitlab-ce_18.10.3-ce.0_amd64.debcurl-fSL-o/tmp/gitlab-ce.deb$URLdpkg-i/tmp/gitlab-ce.deb经验遇到第三方 apt 源签名问题先判断我到底需不需要 apt。自包含的大包GitLab、Jenkins、Zabbix直接下 deb/rpm 往往比修源更快。四、失败 #31.3 GB 的包下载成功却是坏的这是本次最有代表性的一个坑。现象dpkg-i/tmp/gitlab-ce.deb# dpkg-deb: error: decompress subprocess returned error exit status 2# lzma error: unexpected end of input# dpkg: error processing archive /tmp/gitlab-ce.deb (--install)curl没有报错退出码 0文件也确实存在。排查stat-c%s /tmp/gitlab-ce.deb# 1078448480# 对比服务端声明的大小curl-sI$URL|grep-icontent-length# Content-Length: 1402522986差了整整 324 MB。下载在中途被截断但 curl 认为连接是正常结束的。根因curl -fsSL -o file url这种最常见的写法有三个隐患没有-C -连接中断后无法续传只能从头再来没有校验curl 的退出码只表示HTTP 层面没出错服务端提前关闭连接尤其在 5 Mbit/s 长连接、经过多层 CDN 时不一定被判定为失败-s静默把进度和异常都吞了人看不到异常。在 35 分钟量级的大文件下载上这三点叠加就是灾难。解法下载三板斧写进12-gitlab-resume.sh的通用片段任何大文件下载都建议照抄URLhttps://mirror.nju.edu.cn/gitlab-ce/ubuntu/pool/noble/main/g/gitlab-ce/gitlab-ce_18.10.3-ce.0_amd64.debDEB/tmp/gitlab-ce.debEXPECT_SIZE1402522986EXPECT_SHAe46618ac47e9459133c029f8a19f21f18765f147540afeb5356d386f6ac336eb# 板斧 1断点续传 自动重试curl-C--fL--retry8--retry-delay5--retry-all-errors\--speed-limit10240--speed-time60\-o$DEB$URL# 板斧 2字节数比对最快的第一道关SIZE$(stat-c%s$DEB)echoSIZE$SIZEEXPECT$EXPECT_SIZE[$SIZE$EXPECT_SIZE]||{echoSIZE_MISMATCH;exit11;}# 板斧 3SHA256 摘要校验防止内容错乱而非仅截断SHA$(sha256sum$DEB|awk{print $1})echoSHA$SHA[$SHA$EXPECT_SHA]||{echoCHECKSUM_MISMATCH;exit12;}echoCHECKSUMok, start dpkgdpkg-i$DEB几个细节值得说--speed-limit 10240 --speed-time 60连续 60 秒速度低于 10 KB/s 就判定失败并触发重试避免挂着不动但也不断开的僵死连接白白耗掉窗口期--retry-all-errors默认--retry只对部分错误重试加上这个才覆盖连接层错误字节数比对放在 SHA256 之前算 1.3 GB 的 SHA256 要十几秒先用stat一秒排除掉最常见的截断。经验任何超过 100 MB 的下载都必须续传 校验。curl 退出码 0不等于文件是完整的。五、失败 #4 / #5Jenkins 的两连击#4apt 源同样不可用apt-getupdate# Err:x https://mirror/jenkins/debian-stable binary/ Packages# 404 Not Foundapt-getinstall-yjenkins# E: Unable to locate package jenkins根因和 GitLab 类似镜像站的 Debian 风格仓库目录binary/Packages没同步。解法一致——直接下 debcurl-C--fL--retry5-o/tmp/jenkins.deb\https://mirrors.tuna.tsinghua.edu.cn/jenkins/debian-stable/jenkins_2.568.1_all.debdpkg-i/tmp/jenkins.deb||apt-get-finstall-y#5装完起不来——Java 版本systemctl status jenkins# Active: failed (Result: exit-code)journalctl-ujenkins --no-pager-n30# Running with Java 17 from /usr/lib/jvm/java-17-openjdk-amd64,# which is older than the minimum required version (Java 21).# Supported Java versions are: [21, 25]Ubuntu 24.04 的default-jre是 Java 17而 Jenkins 2.5xx 新版本线已经把最低要求提到 Java 21。解法有两步缺一不可# 步骤 1装 Java 21 并切换系统默认apt-getinstall-yopenjdk-21-jdk-headless update-alternatives--setjava/usr/lib/jvm/java-21-openjdk-amd64/bin/java# 步骤 2显式给 jenkins 服务指定 JAVA_HOME关键mkdir-p/etc/systemd/system/jenkins.service.dcat/etc/systemd/system/jenkins.service.d/override.confEOF [Service] EnvironmentJAVA_HOME/usr/lib/jvm/java-21-openjdk-amd64 EnvironmentPATH/usr/lib/jvm/java-21-openjdk-amd64/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin EOFsystemctl daemon-reload systemctl restart jenkins为什么只做步骤 1 不够因为 systemd 服务不走交互式 shell 的初始化流程它的环境变量来自 unit 定义和/etc/default/jenkins。update-alternatives改的是/usr/bin/java软链Jenkins 的 systemd unit 里如果显式引用了$JAVA_HOME或某个绝对路径改软链就无效。改 service 的 Environment 才是确定性的做法。这里还顺带解决了另一个问题应用本身用 Spring Boot 3.3.5 Java 17 编译而 Jenkins 本体要 Java 21。两套 JDK 必须共存——系统默认给 Jenkins 用 21Maven 编译时通过JAVA_HOME或 toolchain 指到 17。这不是问题是常态。验证curl-s-o/dev/null-w%{http_code}\nhttp://127.0.0.1:8080/login# 200六、失败 #6 / #7 / #8Jenkins CLI 与插件的三连坑#6Jenkins URL is not configuredjava-jarjenkins-cli.jar-shttp://127.0.0.1:8080/-authadmin:*** list-jobs# ERROR: anonymous is missing the Overall/Read permission ... 403# 或# Jenkins URL is not configured根因Jenkins 全局配置里的Jenkins URL 为空CLI 的根 URL 校验直接拒绝。解法——用启动时执行的 Groovy 脚本固化Configuration as Code 的轻量版// /var/lib/jenkins/init.groovy.d/02-location.groovyimportjenkins.model.JenkinsLocationConfigurationdeflocJenkinsLocationConfiguration.get()loc.setUrl(http://124.70.29.36:8080/)loc.setAdminAddress(admincd-lab.local)loc.save()println-- Jenkins URL configured:${loc.getUrl()}#7Unexpected request origin (check your reverse proxy settings)配好 URL 后再调 CLI换了个 403ERROR: Unexpected request origin (check your reverse proxy settings). ... 403这个坑非常隐蔽。根因是CLI 连的地址http://127.0.0.1:8080/与 Jenkins 全局配置的 URLhttp://124.70.29.36:8080/不一致触发了 Jenkins 的 origin 校验防 CSRF / DNS rebinding。解法一行字CLI 必须用与 Jenkins URL 完全一致的地址调用包括协议、主机、端口和结尾的斜杠。# 错误java-jarjenkins-cli.jar-shttp://127.0.0.1:8080/...# 正确java-jarjenkins-cli.jar-shttp://124.70.29.36:8080/...经验Jenkins 里凡是遇到莫名其妙的 403先检查我访问的 URL和Jenkins 自己认为的 URL是不是同一个。#8No update center data is retrievedjava-jarjenkins-cli.jar-s$JURL-auth$AUTHinstall-plugingitworkflow-aggregator# ERROR: git is neither a valid file, URL, nor a plugin artifact name in the update center# No update center data is retrieved, so plugin installation is impossible.根因Jenkins 无法访问updates.jenkins.io本地一份 update-center 元数据都没有install-plugin git这种按名字装的方式无从解析。前两次尝试改hudson.model.UpdateCenter.xml、直接 sed 替换default.json都因为 Jenkins 已缓存/未加载而没生效。最终可用的方案是 postBack 注入UChttps://mirrors.tuna.tsinghua.edu.cn/jenkins/updates/update-center.jsonMIRRORhttps://mirrors.tuna.tsinghua.edu.cn/jenkins/plugins# 1. 下载 JSONP 格式的 update-center.jsoncurl-fsSL-o/tmp/uc.jsonp$UC# 2. 剥掉 JSONP 外壳 updateCenter.post( {...} ); 并把下载地址换成镜像python3 -PY import re, io raw open(/tmp/uc.jsonp, encodingutf-8).read().strip() raw re.sub(r^updateCenter\.post\(\s*, , raw) raw re.sub(r\)\s*;?\s*$, , raw) raw raw.replace(https://updates.jenkins.io/download/plugins, https://mirrors.tuna.tsinghua.edu.cn/jenkins/plugins) open(/tmp/uc.json, w, encodingutf-8).write(raw) print(UC_JSON_BYTES, len(raw)) PY# 3. 把元数据 POST 回 Jenkins 的 update centercurl-s-XPOST-u$JUSER:$JPASS\-HContent-Type: application/json\--data-binary /tmp/uc.json\${JURL}updateCenter/byId/default/postBack# 4. 现在可以按名字装插件了java-jarjenkins-cli.jar-s$JURL-auth$AUTHinstall-plugin\gitworkflow-aggregator pipeline-stage-view credentials-binding\ssh-credentials ssh-agent timestamper ws-cleanup junit\build-timeout gitlab-plugin matrix-auth-deploy三种改法的对比方案做法优点缺点改hudson.model.UpdateCenter.xml把url换成镜像的 update-center.json配置持久化需重启且首次仍要在线拉取才生效sed 替换updates/default.json直接改磁盘上的缓存文件不需要外网Jenkins 内存里可能已加载旧数据时机难把握postBack 注入用 API 把 JSON 灌进运行中的 Jenkins立即生效、可脚本化、不需重启JSONP 外壳要自己剥经验内网/弱网环境下部署 Jenkins插件怎么装往往比Jenkins 怎么装更耗时。最稳的兜底是离线 hpi 包在能上网的机器上把 hpi 及其依赖全下好打包传进去丢到$JENKINS_HOME/plugins/再重启。七、失败 #9nohup 起的后台任务SSH 一断就没了现象用 paramiko 的exec_command启动长任务client.exec_command(nohup bash /tmp/12-gitlab-resume.sh /tmp/x.log 21 )命令立刻返回但过一会儿去查ps-ef|grep12-gitlab-resume# 没有进程cat/tmp/x.log# 只有开头几行退出码取到-1通道异常关闭。根因SSH 的 exec 通道和交互式 shell 不同通道关闭时该会话的进程组会收到SIGHUP。nohup理论上能屏蔽SIGHUP但通过 exec 通道启动时进程并没有真正脱离会话没有 setsid、stdin/stdout 仍绑在通道上通道一关就被连带清理。paramiko 这类库执行完命令立刻关通道问题被放大。解法交给 systemd 托管systemd-run--unitgl-resume--collectbash/tmp/12-gitlab-resume.sh好处是全方位的维度nohup systemd-run --unit是否脱离会话不可靠彻底脱离由 PID 1 接管状态可查ps猜systemctl status gl-resume日志自己重定向journalctl -u gl-resume -f自动轮转退出码拿不到systemctl show gl-resume -p ExecMainStatus资源限制无可加-p MemoryMax-p CPUQuota清理残留--collect退出后自动回收 unit配套的查询命令systemctl status gl-resume --no-pager systemctl show gl-resume-pActiveState-pSubState-pExecMainStatus journalctl-ugl-resume --no-pager-n50经验云上远程运维凡是超过 60 秒的任务一律systemd-run托管。这个习惯在后面救了我一次——SSH 完全断掉之后服务器上的 GitLab 安装任务仍在继续跑。八、失败 #10 / #11出口 IP 一变全军覆没这是压垮窗口期的最后一根稻草也是最值得写的一条。现象搭建进行到一半突然所有rx.py调用超时。逐项探测$curl-s-o/dev/null-w%{http_code}\n--max-time8http://124.70.29.36:8080/login 000 $curl-s-o/dev/null-w%{http_code}\n--max-time8https://www.baidu.com200$curl-s-o/dev/null-w%{http_code}\n--max-time10https://gitcode.com200公网正常但 4 台机器全挂。四台机器同时故障的概率极低所以问题几乎一定在链路或访问控制而不在服务器本身。排查第一步看是不是端口级问题——用 bash 内建的/dev/tcp快速探 22 端口比 telnet/nc 更通用不用装东西forhin124.70.84.208124.70.29.36119.3.248.27124.70.110.32;dotimeout4bash-cecho /dev/tcp/$h/222/dev/null\echo$h:22 OK||echo$h:22 FAILdone# 124.70.84.208:22 FAIL# 124.70.29.36:22 FAIL# 119.3.248.27:22 FAIL# 124.70.110.32:22 FAIL第二步ICMP 也不通124.70.29.36 的 Ping 统计信息: 数据包: 已发送 3已接收 0丢失 3 (100% 丢失)第三步看路径断在哪通过最多 12 个跃点跟踪到 124.70.29.36 的路由 1 1 毫秒 1 毫秒 1 毫秒 192.168.3.1 2 3 ms 11 ms 7 ms 113.90.145.65 3 3 ms 6 ms 8 ms 202.105.155.189 4 * * * 请求超时。 5 * * * 请求超时。 6 * * * 请求超时。 7 37 ms 37 ms 37 ms 106.38.244.114 8 * * * 请求超时。 ... 12 * * * 请求超时。第 7 跳37ms已经到了北方骨干之后全部静默没有任何 ICMP unreachable 回包。第四步查本机出口 IP$curl-shttps://myip.ipip.net 当前 IP113.90.145.122 来自于中国 广东 深圳 电信和最初建立连接时的出口 IP不一致——宽带重新拨号/NAT 池切换导致公网 IP 变了。根因判断把四条证据串起来四台机器同时失联 → 不是单机故障公网其它站点正常 → 不是本地断网路径能进骨干网但在云厂商边界前静默消失、无 ICMP 拒绝回包→ 典型的防火墙 DROP丢弃而非 REJECT拒绝本机出口 IP 发生了变更。结论安全组入方向规则按来源 IP 白名单放行我的新出口 IP 不在白名单里所有包被静默丢弃。这里有个很实用的判断法则端口不通但立刻返回Connection refused→ 服务没起网络是通的端口不通且卡到超时、traceroute 静默中断 → 大概率是防火墙/安全组 DROP只有个别端口不通 → 安全组端口规则所有端口 ICMP 全不通 → 来源 IP 被整体挡掉。应对已经发生时能做的立刻确认服务器侧任务不受影响——因为长任务用了systemd-run托管SSH 断了它照跑这就是第七节那个习惯的回报启动带退避的自动重连探测避免人工反复试foriin$(seq1120);doforhin124.70.29.36124.70.84.208;doiftimeout4bash-cecho /dev/tcp/$h/222/dev/null;thenechoSSH_RECOVERED host$hattempt$i;exit0fidoneprintf.;sleep8doneechoprobe-end (not recovered)把不依赖服务器的工作切到前台继续做本次是整理脚本、写文档、推代码仓库不让窗口期空转。下次如何避免措施说明安全组按网段而非单 IP 放行家宽/办公网出口通常在一个 /24 里放113.90.145.0/24比放单 IP 稳得多22 端口走堡垒机/VPN把白名单固定成堡垒机的固定 IP本地 IP 怎么变都不影响准备带外通道云厂商的 VNC / 远程登录走控制台不经安全组是最后的救命稻草关键任务服务器侧自治用 systemd/cron 托管让任务不依赖控制端在线提前把制品和源码放到公网可达的仓库服务器可以自己git clone不依赖本地 → 服务器的文件传输通道最后一条尤其重要。本次我把演示应用和全部脚本推到了 GitCode50-gitlab-seed.sh里 GitLab 的代码种子是这样取的gitclone--depth1https://gitcode.com/cpyaxjq/continuous-delivery-in-action.git srcSRC/tmp/seedsrc/src/cd-demo-app这样只要服务器能上网即使我本地传不上去文件服务器也能自己把代码拉全。把控制端从关键路径上移除是远程运维一个很值钱的设计原则。九、11 个坑的速查表#现象根因解法1apt-get update报NODATA镜像站 InRelease 非有效签名数据放弃 aptdeb 直装2Unable to locate package gitlab-ce仓库被拒 → 索引未建立同上3dpkg报lzma error: unexpected end of input1.3G 包下载被截断curl 未报错续传 字节比对 SHA2564Jenkins 源Packages 404镜像 Debian 目录未同步直接下jenkins_2.568.1_all.deb5Java 17 is older than minimum required (Java 21)Ubuntu 24.04 默认 JDK 17装 JDK21 update-alternativesservice override6CLI 403Jenkins URL is not configured全局 URL 为空init.groovy.d里JenkinsLocationConfiguration.setUrl()7CLI 403Unexpected request originCLI 地址与全局 URL 不一致CLI 必须用完全一致的 URL8No update center data is retrieved拉不到 update-center.json剥 JSONP 换镜像 URL postBack注入9nohup 起的任务 SSH 断即死exec 通道关闭触发 SIGHUP进程未脱离会话systemd-run --unitx --collect104 台机器同时全端口不通出口 IP 变更安全组白名单静默 DROP按网段放行 / 堡垒机 / 带外通道11内联 shell 命令多层引号转义失败Python → SSH → bash 三层转义改为 SFTP 上传.sh再bash执行关于 #11 补充一句一开始我用client.exec_command(fbash -c {cmd})这种内联方式下发命令只要命令里带引号、$、反引号就必然出问题排查成本极高。改成先把脚本 SFTP 上去再执行文件之后转义问题一次性归零而且脚本还留在服务器上可以复查、可以重跑。这是本次最省事的一个改动。defrun_script(host,local_path,timeout600):上传脚本再执行彻底规避多层引号转义remotef/tmp/{os.path.basename(local_path)}sftpclient.open_sftp()sftp.put(local_path,remote)sftp.close()returnrun(host,fbash{remote},timeouttimeout)十、完成度盘点诚实地说清楚做到了哪一步技术文章最忌讳的是把设计好了说成跑通了。这里逐项对账组件 / 能力状态说明4 节点基础环境主机名、hosts、时区、内核参数、工具✅ 已验证00-base.sh四机并行执行成功节点间内网互通✅ 已验证同 VPC内网 IP 互 ping/ssh 通ed25519 部署密钥生成与分发✅ 已验证n2 → n1/n3/n4 免密登录验证通过n3 测试环境JRE17 / Nginx / appuser / 目录规范 / systemd✅ 已验证30-target.sh执行成功n4 生产环境 蓝绿双实例骨架8081/8082 / upstream / active_color✅ 已验证31-prod-bluegreen.sh执行成功Jenkins 安装并启动✅ 已验证curl :8080/login返回 200Jenkins 插件安装⚠️ 中断postBack 方案已跑通元数据注入插件下载阶段遇上断网GitLab 安装⚠️ 中断deb 续传任务由systemd-run托管中断网后无法验证结果演示应用工程Spring Boot 单测 build-info✅ 已完成代码完整见仓库cd-demo-app/Ansible 剧本deploy / bluegreen / rollback✅ 已完成剧本完整含 block/rescue 自动回滚Jenkinsfile 十阶段流水线✅ 已完成见仓库cd-demo-app/JenkinsfileGitLab 项目/分支/Webhook 自动化种子脚本✅ 已编写50-gitlab-seed.sh未获得执行窗口Jenkins Job/凭据自动化脚本✅ 已编写51-jenkins-setup.sh未获得执行窗口端到端流水线跑通❌ 未完成断网 机器回收窗口期用尽没跑通就是没跑通。但这次失败暴露出来的 11 个坑恰恰是任何一篇顺利成功的教程给不了的东西——因为顺利的时候你根本遇不到它们。如果你拿这套脚本去自己的环境里跑上面每一个坑我都已经在脚本里做了防御续传校验、幂等重跑、systemd 托管、URL 一致性、update-center 注入。你大概率会比我顺利。十一、把这次经历抽象成方法论最后留三条我认为最有普适价值的结论。第一把失败当成默认路径来设计流程。不是如果失败了怎么办而是失败之后如何低成本重来。这次能在 2 小时里返工三次方案还保住大部分成果靠的就是所有操作脚本化、所有脚本幂等、所有长任务托管、所有下载校验。这四条本身就是持续交付的核心思想——可重复、可验证、可回滚——只不过这次它们用在了搭平台上而不是发版上。第二控制端是最脆弱的一环要主动削弱对它的依赖。本地网络、本地 IP、本地 SSH 会话任何一个出问题都会让你从在干活变成完全失联。把任务下沉到服务器侧自治systemd、把物料放到双方都能访问的第三方代码仓库能显著提高整体韧性。第三遇到莫名其妙的问题先分清是网络层、权限层还是应用层。本次 11 个坑里有 4 个第一反应会以为是应用配置错了GPG NODATA、dpkg lzma、CLI 403、插件装不上实际根因分别在镜像同步、传输完整性、URL 一致性、外网可达性。养成先看报错发生在哪一层的习惯比记住任何具体解法都重要。附本文涉及的全部脚本所有脚本、Ansible 剧本、Jenkinsfile 与演示应用源码已开源https://gitcode.com/cpyaxjq/continuous-delivery-in-actionops/rx.py paramiko 并行远程执行器含 run_script 防转义方案 ops/00-base.sh 四节点幂等初始化 ops/11-gitlab-deb.sh GitLab deb 直装 gitlab.rb 轻量化调优 ops/12-gitlab-resume.sh 大文件下载三板斧续传/字节比对/SHA256 ops/21-jenkins-deb.sh Jenkins deb 直装 init.groovy.d 安全初始化 ops/22-jenkins-java21.sh Java 21 适配含 service override ops/26-jenkins-uc.sh update-center postBack 注入 ops/30-target.sh 目标环境标准化 ops/31-prod-bluegreen.sh 蓝绿双实例骨架 ops/40-sshkey.sh 部署密钥生成分发 ops/50-gitlab-seed.sh GitLab 项目/分支保护/Webhook/DeployKey/代码种子 ops/51-jenkins-setup.sh Jenkins 凭据/Job/首次构建 ops/52-e2e-evidence.sh 端到端实操证据采集含蓝绿零中断验证欢迎在自己的环境里复现也欢迎把你踩到的新坑提 Issue 补充进来。

相关新闻

最新新闻

日新闻

周新闻

月新闻