设计决策与思考 ====================== 原始需求如下(后面的每个设计决策都和需求息息相关) 写一个简单的从代码 (golang) 到 pod 的工具 要求: 1. 在配置文件中填写代码 github 地址 2. 该工具自动编译对应的 docker image 3. 可以使用该工具启动一个 pod ,其中包含该 docker image .. _thinking-requirements: 对需求的重新思考 ------------------- 实现 go2pod 后记 当我一开始接收到这个需求的时候,我觉得需求模形比较简单, 整个过程就类似构建部署。但是当时对部分细节有一些疑问, 其中最烦恼我的两个疑问是:这个工具是在一个怎样的环境中使用? 这个工具是给什么人使用?( **我潜意识觉得这个工具是给开发者使用的** ) 我后来获得这两个疑问的答案: 1. 这个工具由工程师在本地使用,本地有 docker/kubelet 等工具 2. 工程师了解 kubernetes 的相关知识 获得答案之后,我在脑海中为它简单设想了一个使用场景,觉得挺真实的, 于是就动手开始编写代码,它就是 go2pod。然而在代码编写过程中,我又思考了一些问题, 后来得出一个结论: **这不应该是一个在开发者个人电脑上使用的工具, 它应该是一个公用的系统中的一个组成部分。** 它就是一个简单化的构建部署系统。 **为什么?** 由于配置文件是不存在于项目仓库中的, **假设它是由开发者在个人电脑上使用,那么势必会有以下这两个问题:** 1. 对于单个开发者来说,他需要管理这些配置文件,维持配置文件与项目的一对一关系。 2. 对于同一项目的不同开发者来说,每个开发者本地都可能有一个配置文件, 但是内容却不相同。 另外,这个配置文件中,一个关键字段是项目 GitHub 地址。 **这个设定说明使用这个工具的开发者不会自己在本地修改这个项目。** 假设他会修改项目代码,是项目的开发者,那么他对这个工具的期望则应该是: 将自己修改后的代码进行构建部署。 而对于一个公用系统来说,管理项目配置与项目是一个非常轻松并且自然的事情, 一个公用系统对一个项目进行构建部署时,一个重要参数自然也是项目地址。 **那么,假设工具时给开发者个人在本地使用,这个工具该怎样设计?** **配置与项目绑定。** 配置文件应该放入代码仓库,它也需要版本控制, 配置文件不再需要填写 GitHub 地址。 go2pod 和构建的异同 ------------------------ go2pod 的工作主要可以分为两个部分:镜像构建和镜像发布。 在平常的开发中,我们的很多项目也需要通过 Docker 进行构建,它的一般流程是: 1. *checkout* 仓库的某一个版本代码 2. 将仓库根目录设置为构建的工作空间,体现在 *Dockerfile* 中的话, 就是将 *workdir* 设置为仓库根目录 3. 安装依赖、运行构建命令 4. 打包,生成带有 **版本号** 的 *artifact* 。 在 Docker 镜像中,版本号常常体现为镜像的 *tag* go2pod 的镜像构建过程非常相似,基本也是分为四个步骤,第 2,3,4 步基本都是一样, 但第一步会很较大的差别。 **go2pod 的工作环境是没有代码仓库的, go2pod 的工作环境只有一个配置文件。** .. _thinking-version: 版本生成策略 ----------------- 在 go2pod 的场景中,配置文件中 GitHub 地址可能是指向一个特定版本,但也有可能没有版本信息。 当地址的指向一个特定的 commit 时,类似: *http://github.com/NAMESPACE/REPO/tree/COMMIT-SHA* , 我们认为它是指向一个具体的特定版本。而当日志类似 *http://github.com/NAMESPACE/REPO* 时, 它指向项目主分支,而主分支的版本是随着时间的变化而变化。 在 go2pod 目前的实现中,如果遇到第二中情景,go2pod 会使用分支名(也可能是 tag) 和时间戳作为项目的构建版本。 构建版本主要体现在构建产物:Docker 镜像上。举个例子, 对于项目 *http://github.com/NAMESPACE/REPO* ,它的构建产物(Docker 镜像) 名字会类似 *REPO:master-{timestamp}-go2pod* 。对于项目地址为 *http://github.com/NAMESPACE/REPO/tree/COMMIT-SHA* , 它的构建产物名字类似 *REPO:{COMMIT-SHA}-go2pod* 。