# UAT 流水线:构建镜像并推送到 Harbor(方案 A) 在现有 **UAT Maven + jar 部署** 流水线上增加可选阶段,把业务镜像推到: ```text 39.105.153.68/alien_cloud/<服务名>:uat-latest # 当前预生产最新 39.105.153.68/alien_cloud/<服务名>:uat-build- # 被本次构建顶替的旧 uat-latest(归档) ``` 生产侧 **Gateway-K8s / Alien-Cloud-K8s-Whole** 推荐使用 **`SOURCE_TAG=uat-latest`** 做晋升;需要固定某一版快照时用 `uat-build-`。 脚本:`docs/jenkins/Jenkinsfile-uat-build-deploy.groovy` --- ## 一、整体流程 ```text UAT Jenkins Job(88:30003) 1. Checkout(拉 alien_cloud 预生产分支) 2. Maven Build(mvn clean package) 3. Push images to Harbor(PUSH_TO_HARBOR=true 时) 若已有 uat-latest:pull → 再打 tag uat-build-<本次构建号> → push docker build → push ...:uat-latest 4. Deploy Services(拷 jar 到 /app_deploy_uat + docker restart,与现网一致) Harbor Web(153.68)gateway 等仓库有 uat-latest + 若干 uat-build-* 生产 Jenkins(同机,另一文件夹) Gateway-K8s / Whole:SOURCE_TAG=uat-latest → produ-xxx → ACK ``` **标签规则(以构建 #49 为例)** | 步骤 | 说明 | |------|------| | 推送前 | 若存在 `uat-latest`,将其归档为 `uat-build-49`(与本次 Jenkins 构建号一致) | | 推送后 | 新镜像仅打 `uat-latest` | | 生产晋升 | `SOURCE_TAG=uat-latest` 即「当前 UAT 最新」 | --- ## 二、一次性准备(运维 / Jenkins 管理员) ### 2.1 Harbor(153.68) - [x] 项目 `alien_cloud` 已存在 - [x] 基础镜像 `alien_cloud/base/openjdk8-ffmpeg:v1` 已 push - [ ] 机器人 `robot$alien_cloud+jenkins-k8s` 具备 **推送** 权限 ### 2.2 Jenkins 凭据(全局,UAT / 生产 Job 共用) | ID | 类型 | 内容 | |----|------|------| | `harbor-robot-alien` | Username with password | 用户 `robot$alien_cloud+jenkins-k8s`,密码=Token | | `zhanghaomimapingzheng` | Git | UAT Job SCM 已在使用 | ### 2.3 Jenkins 执行机 Docker(通常在 88 本机或 Jenkins 容器内) ```bash # 探测 Registry curl -sI http://39.105.153.68/v2/ # 登录(与凭据一致) echo '' | docker login 39.105.153.68 -u 'robot$alien_cloud+jenkins-k8s' --password-stdin ``` 若 HTTP + IP 访问,需在 **运行 docker 的宿主机** `/etc/docker/daemon.json` 增加: ```json { "insecure-registries": ["39.105.153.68"] } ``` 然后 `systemctl restart docker`(注意:若在 153.68 上误执行会影响 Harbor,**应在 88 Jenkins 节点** 配置)。 ### 2.4 将脚本提交到 Gitea 本地修改 `docs/jenkins/Jenkinsfile-uat-build-deploy.groovy` 后,push 到 UAT Job 使用的分支(如 `uat-20260202`)。 --- ## 三、配置 UAT Jenkins Job | 项 | 值 | |----|-----| | 定义 | Pipeline script from SCM | | 仓库 | `http://8.152.195.41:3000/alien/alien_cloud` | | 分支 | `*/uat-20260202`(与你们一致) | | Script Path | **`docs/jenkins/Jenkinsfile-uat-build-deploy.groovy`** | | SCM 凭据 | Git(**不要**选 Harbor 机器人) | 保存后先 **立即构建一次**,加载新参数。 --- ## 四、Build with Parameters(推荐首次 gateway) ### 配置页 vs 构建页(易混) | 页面 | `HARBOR_PUSH_SCOPE` 长什么样 | |------|-------------------------------| | **Job → 配置(Configure)** | 多行**文本框**,每行一个选项——这是在**编辑**下拉列表,不是让你手打 tag | | **Build with Parameters(立即构建旁)** | **下拉框**,可点选 `all-java-services`、`gateway-only` 等 | 若在「配置」里看到文本框,属正常;请去 **Build with Parameters** 里选。 ### 必须勾选 PUSH_TO_HARBOR | 参数 | 说明 | |------|------| | **`PUSH_TO_HARBOR`** | **必须勾选**,否则整个「Push images to Harbor」阶段**跳过**,Harbor 不会出现 gateway(与 `HARBOR_PUSH_SCOPE` 选什么无关) | | `HARBOR_PUSH_SCOPE` | 仅当 `PUSH_TO_HARBOR=true` 时生效 | 配置里「Set by Default」未勾时,每次构建都要在 **Build with Parameters** 手动勾选 **PUSH_TO_HARBOR**。 | 参数 | 首次试跑建议 | |------|----------------| | `GIT_BRANCH` | `uat-20260202` | | `FORCE_UPDATE` | 按需 | | **`PUSH_TO_HARBOR`** | **勾选 true** | | **`HARBOR_PUSH_SCOPE`** | 下拉选 **`all-java-services`** 或 **`gateway-only`** | | `HARBOR_REGISTRY` | `39.105.153.68` | | `HARBOR_PROJECT` | `alien_cloud` | 构建成功后日志末尾应有: ```text >>> archive previous uat-latest -> uat-build- # 非首次构建才有 >>> pushed 39.105.153.68/alien_cloud/gateway:uat-latest >>> Prod promote: SOURCE_TAG=uat-latest ``` --- ## 五、验证 Harbor 浏览器打开:`http://39.105.153.68/harbor/` → 项目 **alien_cloud** → 镜像仓库应出现 **`gateway`**,标签 **`uat-latest`**,以及若干 **`uat-build-*`**。 或命令行: ```bash curl -s -u 'robot$alien_cloud+jenkins-k8s:' \ 'http://39.105.153.68/v2/alien_cloud/gateway/tags/list' ``` --- ## 六、接生产晋升流水线 在 **Gateway-K8s** 或 **Alien-Cloud-K8s-Whole**: | 参数 | 值 | |------|-----| | `SOURCE_TAG` | **`uat-latest`**(推荐);或指定历史 `uat-build-` | | `DEPLOY_STRATEGY` | 先 `skip`(只晋升 Harbor),再 `rolling` | | `DEPLOY_MODE` | 单服务用 `single` + `gateway` | --- ## 七、参数说明 | 参数 | 说明 | |------|------| | `PUSH_TO_HARBOR` | 默认 **`true`**(推 Harbor);仅 jar 部署 UAT 时 **取消勾选** | | `HARBOR_PUSH_SCOPE` | 默认 **`all-java-services`**(七个);**`gateway-only`** 等只推一个;Maven 须对所选模块打出 jar | | `HARBOR_PRUNE_OLD_TAGS` | 默认 **true**:每个仓库只保留最近 **10** 个 `uat-build-*` tag,删更旧的(**不删 `uat-latest`**) | | `HARBOR_KEEP_TAG_COUNT` | 保留 `uat-build-*` 个数,默认 `10` | ### 旧镜像清理说明 - 每次 push 更新 **`uat-latest`**;被顶替的旧 `uat-latest` 会归档为 **`uat-build-<本次 Jenkins 构建号>`**。 - 脚本在 push 后调 Harbor API 删除最老的 `uat-build-*`,**保留最近 N 个**;**永不删除 `uat-latest`**。 - 机器人需有 **删除制品** 权限;若删除失败,日志会有 `WARN: delete failed`。 - **不会**删除 `base/openjdk8-ffmpeg` 等基础镜像。 - Jenkins 本机 `docker images` 可用 `docker image prune` 另行清理,与 Harbor 无关。 | 环境变量 | 说明 | |----------|------| | `UAT_HARBOR_LATEST_TAG` | 固定 `uat-latest` | | `UAT_HARBOR_BUILD_TAG` | 本次归档名 `uat-build-${BUILD_NUMBER}`(仅在有旧 `uat-latest` 时 push) | --- ## 八、常见问题 | 现象 | 处理 | |------|------| | `not found` pull 基础镜像 | 确认 Harbor 有 `base/openjdk8-ffmpeg:v1` | | `Login Succeeded` 后 push 失败 | 机器人是否有项目 push 权限 | | `x509` / 证书错误 | 88 上 `insecure-registries` 或 HTTPS + ca.crt | | Harbor 仍无 gateway | 是否勾选了 `PUSH_TO_HARBOR`;Maven 是否打出 `alien-gateway/target/*.jar` | | 生产 Whole `uat-latest: not found` | 先跑一轮 UAT 推 Harbor;`SOURCE_TAG` 填 **`uat-latest`** | | 需要回滚到上一版 UAT | 在 Harbor 查 `uat-build-`,生产 Job 填该 tag 作 `SOURCE_TAG` | | `no space left on device`(docker build) | Jenkins 节点磁盘满;见下文 **磁盘不足** | ### 磁盘不足(`no space left on device`) Harbor 阶段会在本机 **docker build**,store/lawyer 等带 `lib/` 时单次上下文可达数百 MB,七个服务连续构建易占满 `/var/lib/docker`。 **在 Jenkins 节点(日志里多为 `/var/jenkins_home` 所在盘)执行:** ```bash df -h docker system df docker system prune -af # 清理未使用镜像/构建缓存(会删未引用镜像,慎用前先确认) docker builder prune -af # 仅清构建缓存(相对安全) ``` 脚本已做优化:`withLib=false` 的服务(如 **gateway**)构建上下文**不再拷贝** `target/lib`,仅保留空 `lib/.keep`;每个服务 push 后删除本地镜像并清理 `.jenkins_docker_ctx`。仍建议在节点定期 `docker system prune`。 --- ## 九、与现网 jar 部署的关系 - **Deploy Services** 阶段仍会拷 jar 并 `docker restart` UAT 容器,**不影响**现有 UAT 访问方式。 - Harbor 镜像供 **ACK / 生产晋升** 使用,两套路径可并行。 - 日常若只更新 UAT 机 jar、暂不发 ACK,可 `PUSH_TO_HARBOR=false`。