方式 1:容器构建时就将代码导入好,并安装好依赖,部署时可以做到开箱即用。 方式 2:仅构建一个空白容器,并写好启动脚本。由 CI 负责打包并上传代码,部署时根据启动脚本拉取代码并安装依赖,然后再启动。
方式 1 在 CI 要花费更长时间。方式 2 在 CD 要花费更长时间,而且部署时存在不确定性(代码拉不下来,安装依赖失败等)。目前我司用的是方式 2 来完成 k8s 部署,但我觉得这并没有真正利用到容器的所有优势( CI/CD 架构并不是我设计的,我只是负责将部分项目接入)。我个人认为方式 1 才是正确的。是这样的吗?
1
pomelo11 2020-07-10 11:00:09 +08:00
目前公司的 ci/cd 采用的是方式 1,项目的 ci/cd 根据项目本身的大小决定的,方式 2 没有试过
|
2
wangking 2020-07-10 11:02:19 +08:00
一般是 1,
|
3
fivesmallq 2020-07-10 11:07:00 +08:00 1
当然是 1,可重用的镜像不应该再有太多的外部过程,应该是直接可用的
|
4
suom 2020-07-10 11:08:38 +08:00
用方式一。方式一保证了环境和代码的一致性。
而且最好:构建成功的镜像用当前时间或者流水 ID 打上 tag 。线上万一出问题要回滚,直接按照 tag 回滚。 |
5
MOETAN0 2020-07-10 11:10:36 +08:00
1 才真正符合容器设计目的之一:环境一致性。
以及,对 1 的过程做好分层优化,比如充分利用 layer cache,那么也可以大幅度提高 CD 阶段的效率。 |
6
lenqu 2020-07-10 11:24:25 +08:00
二其实也可以,看自己所用的生态环境是否完备,不完备自己是否有能力实现一个完备的生态环境?
|
7
Kilerd 2020-07-10 11:27:03 +08:00
当然是 1 。
|
8
idblife 2020-07-10 11:29:18 +08:00
我们用的是 2,想换成 1
|
9
vinsec 2020-07-10 11:52:50 +08:00
Golang 项目其实 1 和 2 差不太多. 目前用的是 1 CI 过程 Jenkins+Dockerfile,根据当前 Build ID 打 tag 并 push 到内网 hrabor 上, 构建完毕同时触发 CD 通过 Jenkins API 获取最新一次构建成功的 Build ID,作为 tag 从 harbor 拉镜像 停止旧容器 启动新容器. 目前是一个小规模的项目这么做的
|
10
wangritian 2020-07-10 11:53:32 +08:00
公司 php web 项目,我创建了 2 个镜像仓库,base (仅包含项目依赖,构建时使用方式 2 远程拉取)和 service ( FROM base,仅包含业务代码,构建时复制到指定目录),项目的新功能需要添加依赖时,更新 base 镜像,service
镜像业务代码更新频率很高,但体积小,打包快,又有一个可控的 base 依赖镜像 |
11
optional 2020-07-10 11:56:01 +08:00
当然实 1,ship 是 docker 的最大优点。
2 其实是把容器当成虚拟机在用了。 |
12
optional 2020-07-10 11:57:07 +08:00
而且 1 并没有在 CI 的时候多花费多少,Dockerfile 写得好,用上 multi stage builder,可以缓存大部分步骤的。
|
13
koolob 2020-07-10 12:20:37 +08:00
1 是对的。Dockerfile 最后的部分去导入代码。这样之前的层都是缓存了,不会花费更长时间。每一个代码版本就出一个镜像版本。然后部署时,可以根据版本号爱部署哪个镜像就部署哪个镜像。
|
14
maemual 2020-07-10 12:27:36 +08:00
正常人都是用 1 吧,用 2 的优点是什么?
|
15
hantsy 2020-07-10 12:36:04 +08:00
一套流程都可以在 CI 服务器上,比如 Github Actions,CircleCI,SemaphoreCI,Codefresh 等:
1. PR Build: Clone, Compile, 运行测试所有的测试代码(单元测试,集成测试),确定全部通过。(此过程反复 Refactor,Code Review ) 2. PR Merge 到 Master, 开始(或者指定特定 Event,或者 Tag ) Build Docker Image, (有些场景,会加入一个容器环境运行的纯 Client 端的功能测试),然后上传到 docker hub, 或者私有 Register 。 3. 比如 Github Tag 等特定事件(有的 CI 可以人工决定,手动触发),生产环境( K8s )容器更新。(有一些 CI 云服务本身就是集成了 CD 部署(多个 K8s ),一键部署) 项目自动化很好,但前提一定要做是自动化测试,国内测试都没有的,谈自动化只能用呵呵两字。 |
16
hantsy 2020-07-10 12:42:45 +08:00
@optional 我用 Mutil Stage Builder 主要应对一些没办法的事,很多环境在本地机测试有困难,直接把整个编译过程放到容器内。
|
17
swulling 2020-07-10 12:43:59 +08:00 via iPhone
没听说过用 2 的
|
18
hantsy 2020-07-10 13:01:02 +08:00
如果 2,你指的容器是 Docker,那我真的无语了。Docker 部署一个基本的原则就使用 Immutable Image 。
|
19
ETiV 2020-07-10 13:34:36 +08:00 via iPhone
3: 额外打一个 runtime 镜像
CI 时 Dockerfile FROM busybox CD 时,用 initContainer 把代码 copy 进与 runtime 共享的 volume |
20
594duck 2020-07-10 13:38:07 +08:00
2 的好处是私有配置可以在 CI/CD 上上传,与测试配置解耦。
|
21
Aquariuslt 2020-07-10 13:40:19 +08:00
1
|
22
wiken 2020-07-10 14:23:17 +08:00
1 吧
|
23
tikazyq 2020-07-10 14:33:17 +08:00
一般是 1
如果是 2,可能是针对那种一个容器里跑多个轻量级应用的情况吧 |
24
whileFalse 2020-07-10 15:29:50 +08:00
@ETiV 哥们你的想法很正确,但看来你不知道 docker multi stage build 。
|