设计决策与思考

原始需求如下(后面的每个设计决策都和需求息息相关)

写一个简单的从代码 (golang) 到 pod 的工具

要求:

  1. 在配置文件中填写代码 github 地址
  2. 该工具自动编译对应的 docker image
  3. 可以使用该工具启动一个 pod ,其中包含该 docker image

对需求的重新思考

实现 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 的工作环境只有一个配置文件。

版本生成策略

在 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