系列专栏声明:比较流水,主要是写一些踩坑的点,和实践中与文档差距较大的地方的思考。这个专栏的典型特征可能是 次佳实践,争取能在大量的最佳实践中生存。

一、利用 云效 Flow 拉取代码

关于怎么开通 云效 以及 CodeUpFlow官方文档 吧。

Flow 对标的是 Jenkins / Pipeline / CICD,看文档 旧版是有配置文件 所以可以 IaC 的,新版没有找到这个功能。新版的 ClickOps 够用了,而且我的场景几乎是一次性配置的,不会经常变更,所以够用了。

第一个坑点是,代码源是支持 GitHub 的,但实际并不支持。首先在墙外拉不动代码,对比镜像仓库 ACR 自带的构建功能就可以勾选用海外服务器构建,Flow 没有这个选项。其次就算连上了,速度也会很慢,而流水线是按耗时而不是次数收费的,所以代码源,包括三方库的源实际上都必须在阿里云上面。以及构建镜像时的 FROM,官方文档也建议把基础镜像提前上传到自己的 ACR 私有仓库里,以提高拉取时的效率。跨生态是不存在的,vender lockin 了。

因此就自然引出了第二个坑点,云效的自建三方库只有 Maven 和 NPM,所以这个生态里只能用 Java 和 JavaScript。虽然理论上可以使用自建的 Nexus,但我上云效的目的不就是不想自建么。关于怎么本地开发怎么配置 .m2/settings.xml 才能使用云效提供的 Maven,以及上传一些私有包,参考 需要登录云效才能看的文档,能搜到的常规文档里是旧版的,还没更新。Flow 里的 settings.xml 都是配置好的,使用系统推荐不要修改就可以了。

第三个需要注意的点是 工作目录 的概念。代码是可以有多个来源的,理论上可以将来自不同上游的代码分别拉取,然后混在一起,微信小程序的分包似乎就是这个逻辑?从体验上说 monorepo 会更直觉一点,但对多源的支持也许落地时 对企业内部混乱的组织架构支持更好,更容易帮助甲方转型一点。可以将源 A 的工作目录指定为 /path/to/app-a,源 B 的工作目录指定为 /oath/to/app-b,然后使用一些诸如 cd app-b 的命令来操作。

以上,虽然云效是 ClickOps 但刻意没有附云效的截图和代码片段,一是因为没有 IaC 不想贴脚本,等找到了再来更新这个部分;二是交互做得意外的不错吧,按提示到处点点上手很快的。

二、使用自定义镜像构建

流水线有很多步骤,Flow 默认建议的是代码扫描、构建、部署等等,这里主要讨论构建过程。

Flow 有很多准备好的构建环境,如 Java 构建,Go 构建等等,其中 Java 构建又分为 JDK 1.8,OPENJDK 11,Maven 2.x,3.x 等等。这些看似会带来易上手的开箱体验,但实际用起来就发现非常不可控。比如只能从支持的 JDK major 版本里选择,如果特殊情况下要指定到 minor 版本就更不可能了。

实践上我们需要的是 Drone Runner 那种方案,用户自行准备镜像,每个步骤用镜像挂工作目录去执行构建,在 Flow 里这个叫做 自定义环境构建

目前美中不足的是 只支持公开仓库 的镜像(支持自建的私有仓库但这里的服务链接方式我没搞定),不知道它为什么不支持 ACR 私有仓库。那么问题就来了,如果使用开箱的 Java 构建,平台会把 settings.xml 都配置好了,使用自定义的镜像显然没有这个。同时,由于自定义镜像必须放在公网,所以也不可能将 带用户名密码的 settings.xml 打进镜像里。

目前我采用的方案是另开了一个 CodeUp 仓库 secrets,将明文的 settings.xml 放在仓库里,并将它指定成为代码源的 /root/workspace/secrets 工作目录。上面提到过,第一步拉取代码源支持多源多工作目录,所以到构建这一步的脚本就形如:

cd /root/workspace/app
mvn -s /root/workspace/secrets/settings.xml clean package

翻了一下文档,发现 secrets/settings.xml 应该还可以支持其它下载方式,比如从 OSS 下载,或者 CodeUp 加密仓库等等,这里就不深究了。以上主要提供的思路点是利用不同的 工作目录,将不敏感和敏感的内容,分别存储,再混合使用。

三、发布到 镜像仓库 ACR

这一步很简单,使用平台提供的 镜像构建并推送至阿里云镜像仓库个人版 即可。由于实际的复杂构建工作是在前续步骤完成的,这里只要将 /root/workspace/app 挂载上去,Dockerfile 里也只需要简单写几行 COPY fromxx toxx 就好。

会有一个向导帮你建立到 ACR 的服务链接,实际上执行的应该是 docker run build & push,记得在 tag 上标记版本,我使用的是 release-${BUILD_NUMBER},因此推送进仓库的镜像形如 registry.cn-hangzhou.aliyun/lisitede/app:release-8。最终用来启动容器的就是这个镜像。

03-05 14:41