跨境研发团队最隐形成本不是机器贵,是构建在等网络:
git clone 卡、Docker Hub 限流、npm install 跨洋重拉、Maven 中央仓偶发超时、Runner 排队。
把香港服务器从“业务机”改成“DevOps 中间层”,思路就变了:
- 代码仓库镜像放香港
- 依赖代理(npm/PyPI/Maven/Harbor)本地命中
- CI Runner 就近执行
- 构建缓存跨 Job 复用
- 敏感源码不落公网,制品加密回传
本文给一套可复制的“香港 CI 缓存中枢”架构,附 Nexus + Harbor + GitLab Runner + BuildKit 缓存配置,顺带把合规边界讲清。
一、先算一笔“等网络”的账
某 30 人跨境团队(北京+新加坡+伦敦):
- 每次 pipeline:
clone 40s + npm 90s + docker build 120s - 每天 200 次构建 → 每天浪费在跨洋拉取上的时间 ≈ 2.5 人天
香港节点介入后:
- clone 走亚太内网(香港中转)≈ 5s
- 依赖命中本地缓存 ≈ npm 15s、镜像层命中 70%+
- 构建缓存复用 → 重复编译几乎为 0
香港节点的价值不是“快一点”,是把网络等待从构建关键路径里删掉。
二、整体架构:三层分离
text
开发者(境内/海外) │ git push ▼ 代码主仓(境内私有 Git / 海外 GitLab) │ Webhook 触发 ▼ 香港 DevOps 中间层 ├─ Gitea 镜像仓(只读同步,加速 clone/fetch) ├─ Nexus:npm / PyPI / Maven 代理缓存 ├─ Harbor:Docker 镜像代理缓存 + 本地构建仓 ├─ GitLab Runner / Actions Runner:就近执行 └─ BuildKit 缓存卷(NVMe) │ 构建完 ▼ 制品加密回传境内对象存储 / 部署到边缘
原则:
- 香港不存“业务数据库”
- 香港只留“可重建的缓存与中间产物”
- 源码明文不长期落盘,构建完清 workspace
三、依赖代理:先挡住 80% 网络等待
1. Nexus 组仓(npm/PyPI/Maven)
bash
docker run -d --name nexus -p 8081:8081 -v /data/nexus:/nexus-data sonatype/nexus3
配置三个 proxy repo:
- npm → registry.npmjs.org
- pypi → pypi.org
- maven → repo1.maven.org
再建 group repo 聚合,客户端只配一个地址:
bash
npm config set registry https://hk-ci.internal/repository/npm-group/ pip config set global.index-url https://hk-ci.internal/repository/pypi-group/simple
Maven settings.xml:
xml
<mirror> <id>hk-nexus</id> <url>https://hk-ci.internal/repository/maven-group/</url> <mirrorOf>central</mirrorOf> </mirror>
命中效果:
- 首次拉取跨境,后续全本地
- 夜间预热脚本把主流包预拉一遍
- Docker Hub 限流?Harbor 代理缓存挡前面
2. Harbor 做镜像代理缓存
yaml
# harbor.yml 开 proxy cache proxy: remote_url: https://registry-1.docker.io username: "" password: ""
项目级配置:
library/*走 proxy cache- 内部镜像推
hk-harbor/internal/* - 复制策略:夜间把基础镜像预拉到本地
bash
# 预热 docker pull hk-harbor.internal/library/nginx:1.27 docker pull hk-harbor.internal/library/python:3.12-slim
四、CI Runner:就近跑,别让开发者等
GitLab Runner(香港节点)
toml
[[runners]] name = "hk-builder" url = "https://gitlab.internal/" token = "<runner-token>" executor = "docker" [runners.docker] image = "docker:27" privileged = false volumes = ["/cache/buildkit:/var/lib/buildkit", "/var/run/docker.sock:/var/run/docker.sock"]
GitHub Actions 自托管 Runner
bash
./config.sh --url https://github.com/org --token <T> --labels hk-builder ./run.sh
标签路由:
yaml
jobs: build: runs-on: [self-hosted, hk-builder]
境内开发者 push 后,Runner 在香港执行,依赖全命中本地。
五、构建缓存:把“重复编译”干掉
1. Docker BuildKit 层缓存
bash
export BUILDKIT_STEP_LOG_MAX_SIZE=10485760 docker buildx build \ --cache-from type=local,src=/cache/buildkit \ --cache-to type=local,dest=/cache/buildkit,mode=max \ -t hk-harbor.internal/app/svc:ci .
规则:
package.json/requirements.txt变动才重拉依赖层- 源码层每次新,但依赖层命中
- NVMe 挂
/cache,别放系统盘
2. 语言级远程缓存
- Node:
npm ci --prefer-offline - Rust:
sccache远程缓存 - Go:挂载
GOCACHE/GOMODCACHE - Frontend:Vite 依赖预打包 + esbuild 缓存
bash
# 例:Go 缓存挂载 export GOMODCACHE=/cache/gomod export GOCACHE=/cache/gocache
3. 大仓库 git 优化
bash
git config --global core.compression 0 git gc --aggressive # 浅克隆 git clone --depth=1 --filter=blob:none <repo>
六、网络与内核:构建流量也吃吞吐
bash
sysctl -w net.ipv4.tcp_congestion_control=bbr sysctl -w net.core.somaxconn=65535 sysctl -w net.ipv4.tcp_fastopen=3
Docker 侧:
json
{ "mtu": 1450, "max-concurrent-downloads": 10, "registry-mirrors": ["https://hk-harbor.internal"] }
Nginx 反代 Nexus/Harbor:
- 开 HTTP/2
- 开 brotli/gzip
- 大文件走 chunked,不断连
七、安全:CI 中枢最怕凭据泄漏
- Runner 只收 Webhook,不暴露 22/8080 公网
- 管理口走堡垒机/零信任
- 凭据放 Vault / CI Secret,不进 playbook
- 构建镜像扫漏洞(Trivy 嵌入 pipeline):
yaml
scan: stage: test script: - trivy image --exit-code 1 --severity HIGH,CRITICAL $IMAGE
- 制品回传加密(age/sops),密钥不进香港磁盘明文
- 构建日志脱敏:正则擦除 token/密码/内部域名
八、合规边界:香港层“可重建”原则
数据 |
香港节点处理 |
留存 |
源码明文 |
构建期内存/临时卷 |
构建完 rm -rf |
依赖包 |
缓存 |
可重建,可清 |
镜像层 |
缓存 |
可重建 |
构建日志 |
脱敏后短期留 |
加密归档回境内 |
用户 PII |
不进 CI 环境 |
禁止 |
签名密钥 |
不落香港磁盘 |
KMS/境内 Vault |
香港节点崩了能重建:重装 Nexus/Harbor + 拉主仓 + 缓存预热,半小时恢复。
九、监控:盯“缓存命中率”不是 CPU
Prometheus 关键指标:
nexus_cache_hit_ratio(目标 >85%)harbor_pull_cache_hit(目标 >70%)pipeline_wait_seconds(排队时长)build_time_p95分语言拆分egress_cross_border_bytes(跨境出网,越低越省)
告警:
- 命中率掉到 50% 以下 → 上游源切换/预热失效
- 单 Runner 排队 >5min → 扩 Runner
- 跨境出网突增 → 有 Job 在拉全量依赖(查 Dockerfile)
十、最小落地清单
- [ ] 香港节点挂 NVMe,分卷:/data/nexus /data/harbor /cache
- [ ] Nexus 代理 npm/pypi/maven,客户端统一配 group
- [ ] Harbor 开 proxy cache,基础镜像夜间预热
- [ ] GitLab/Runner 自托管,标签路由到香港
- [ ] BuildKit 层缓存持久化,语言级缓存挂载
- [ ] Pipeline 嵌入 Trivy 扫描 + 日志脱敏
- [ ] 管理口零信任,凭据走 Vault
- [ ] 构建完清 workspace,制品加密回传
- [ ] 盯命中率/排队时长/跨境出网
十一、什么别放香港 CI 层
- 生产数据库
- 长期源码归档(归境内代码仓)
- 明文签名密钥
- 用户隐私样本数据
- 把 Runner 当生产服务裸跑公网
十二、总结
香港服务器在研发体系里最被低估的用法,不是“再开一台业务机”,而是:
让构建发生在离依赖最近的地方。
代码主仓在境内/海外,
依赖缓存在香港,
Runner 在香港,
缓存可重建,
跨境只传“增量源码 + 加密制品”。
开发者感知是:
git push后 1 分钟出构建- 不再看
npm sill idealTree buildDeps转圈 - 晚高峰也不卡 clone
工程效率的提升,往往不来自“买更快的机器”,
而来自把等待网络的那一段,从关键路径里拿掉。
香港节点,就是那段等待的终结者。