关于容器构建方式优劣的疑惑

2020-07-10 10:49:09 +08:00
 wxsm

方式 1:容器构建时就将代码导入好,并安装好依赖,部署时可以做到开箱即用。 方式 2:仅构建一个空白容器,并写好启动脚本。由 CI 负责打包并上传代码,部署时根据启动脚本拉取代码并安装依赖,然后再启动。

方式 1 在 CI 要花费更长时间。方式 2 在 CD 要花费更长时间,而且部署时存在不确定性(代码拉不下来,安装依赖失败等)。目前我司用的是方式 2 来完成 k8s 部署,但我觉得这并没有真正利用到容器的所有优势( CI/CD 架构并不是我设计的,我只是负责将部分项目接入)。我个人认为方式 1 才是正确的。是这样的吗?

3119 次点击
所在节点    程序员
24 条回复
pomelo11
2020-07-10 11:00:09 +08:00
目前公司的 ci/cd 采用的是方式 1,项目的 ci/cd 根据项目本身的大小决定的,方式 2 没有试过
wangking
2020-07-10 11:02:19 +08:00
一般是 1,
fivesmallq
2020-07-10 11:07:00 +08:00
当然是 1,可重用的镜像不应该再有太多的外部过程,应该是直接可用的
suom
2020-07-10 11:08:38 +08:00
用方式一。方式一保证了环境和代码的一致性。


而且最好:构建成功的镜像用当前时间或者流水 ID 打上 tag 。线上万一出问题要回滚,直接按照 tag 回滚。
MOETAN0
2020-07-10 11:10:36 +08:00
1 才真正符合容器设计目的之一:环境一致性。
以及,对 1 的过程做好分层优化,比如充分利用 layer cache,那么也可以大幅度提高 CD 阶段的效率。
lenqu
2020-07-10 11:24:25 +08:00
二其实也可以,看自己所用的生态环境是否完备,不完备自己是否有能力实现一个完备的生态环境?
Kilerd
2020-07-10 11:27:03 +08:00
当然是 1 。
idblife
2020-07-10 11:29:18 +08:00
我们用的是 2,想换成 1
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 拉镜像 停止旧容器 启动新容器. 目前是一个小规模的项目这么做的
wangritian
2020-07-10 11:53:32 +08:00
公司 php web 项目,我创建了 2 个镜像仓库,base (仅包含项目依赖,构建时使用方式 2 远程拉取)和 service ( FROM base,仅包含业务代码,构建时复制到指定目录),项目的新功能需要添加依赖时,更新 base 镜像,service
镜像业务代码更新频率很高,但体积小,打包快,又有一个可控的 base 依赖镜像
optional
2020-07-10 11:56:01 +08:00
当然实 1,ship 是 docker 的最大优点。
2 其实是把容器当成虚拟机在用了。
optional
2020-07-10 11:57:07 +08:00
而且 1 并没有在 CI 的时候多花费多少,Dockerfile 写得好,用上 multi stage builder,可以缓存大部分步骤的。
koolob
2020-07-10 12:20:37 +08:00
1 是对的。Dockerfile 最后的部分去导入代码。这样之前的层都是缓存了,不会花费更长时间。每一个代码版本就出一个镜像版本。然后部署时,可以根据版本号爱部署哪个镜像就部署哪个镜像。
maemual
2020-07-10 12:27:36 +08:00
正常人都是用 1 吧,用 2 的优点是什么?
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 ),一键部署)

项目自动化很好,但前提一定要做是自动化测试,国内测试都没有的,谈自动化只能用呵呵两字。
hantsy
2020-07-10 12:42:45 +08:00
@optional 我用 Mutil Stage Builder 主要应对一些没办法的事,很多环境在本地机测试有困难,直接把整个编译过程放到容器内。
swulling
2020-07-10 12:43:59 +08:00
没听说过用 2 的
hantsy
2020-07-10 13:01:02 +08:00
如果 2,你指的容器是 Docker,那我真的无语了。Docker 部署一个基本的原则就使用 Immutable Image 。
ETiV
2020-07-10 13:34:36 +08:00
3: 额外打一个 runtime 镜像
CI 时 Dockerfile FROM busybox

CD 时,用 initContainer 把代码 copy 进与 runtime 共享的 volume
594duck
2020-07-10 13:38:07 +08:00
2 的好处是私有配置可以在 CI/CD 上上传,与测试配置解耦。

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://www.v2ex.com/t/688791

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX