Kubernetes源码剖析
上QQ阅读APP看本书,新人免费读10天
设备和账号都新为新人

2.4 Bazel环境构建

Kubernetes本地环境构建和容器环境构建实际在内部使用的都是Go语言自带的构建工具go install命令来进行代码构建的。除了使用官方构建工具,Kubernetes还支持Bazel构建,下面介绍一下Bazel构建工具。

Bazel是Google公司开源的一个自动化软件构建和测试工具。Bazel使用分布式缓存和增量构建方法,使构建更加快速。其支持构建任务,包括运行编译器和链接器以生成可执行程序和库。Bazel与Make、Gradle及Maven等构建工具类似,但Bazel在构建速度、可扩展性、灵活性及跨语言和对不同平台的支持上更加出色。Bazel具有如下特性。

支持多语言:Bazel支持Java、Objective-C和C++等主流语言,并可以扩展支持任意的其他编程语言。

高级别的构建语言:项目以BUILD语言进行描述。BUILD是一种简洁的文本格式,可描述多个小而互相关联的库、二进制程序和测试程序组成的项目。

支持多平台:相同的工具和BUILD文件可以为不同架构或平台构建软件。

再现性:在BUILD文件中,必须明确为每个库、测试程序、二进制文件指定其直接依赖。在修改源码文件后,Bazel使用这个依赖信息就可以知道哪些东西必须重新构建,哪些任务可以并行执行。这意味着所有的构建都是以增量的形式构建的并能够每次都生成相同的结果。

可扩展性强:Bazel可以处理大型程序的构建;在Google公司内,一个二进制程序通常有超过100KB的源码文件,在代码文件没有被改动的情况下,构建过程大约需要200ms。

构建速度快:支持增量编译。对依赖关系进行了优化,从而支持并发执行。

但是如此优秀的Bazel为什么在开源软件中流行不起来,只能在Google内部大量使用呢?一方面是因为接入Bazel较为复杂;另一方面在于Google内部的代码库非常庞大(约有数百万行),Bazel支持多语言的构建系统为所有项目构建代码,将源码统一存放,使用统一的持续集成来运行所有的单元测试,因此在构建过程中性能问题是最关键的问题,而大部分公司很少遇到像Google这样进行大规模编译的性能问题。

比较有趣的是,在Go语言社区内有时也会争论Go语言项目是否应该使用go build/install或bazel build。目前Kubernetes已经支持使用Bazel进行构建和测试了,但尚未将Bazel作为默认的构建工具。

2.4.1 使用Bazel构建和测试Kubernetes源码

下面介绍使用Bazel构建和测试Kubernetes源码的内容。

1.Bazel安装

读者可根据自身平台选择不同的安装方式,推荐安装Bazel 0.22.0版本。安装过程较为简单,可直接参考Bazel的官方文档。

2.make bazel常用操作

make bazel-build:构建所有二进制文件。

make bazel-test:运行所有单元测试。

make bazel-test-integration:运行所有集成测试。

make bazel-release:在容器中进行构建。

3.单独构建kubectl

除根据Makefile中定义的make bazel操作外,我们也可以直接使用bazel命令,来对单独组件进行构建,代码示例如下:

上述代码中的//cmd/kubectl/…在Bazel中被称为标记,用于指定需要构建的包名。若执行构建命令后输出如上信息,则表示构建成功,Bazel将构建后的二进制文件输出到根目录下的bazel-bin目录中。kubectl二进制文件的相对路径为bazel-bin/cmd/kubectl/。

注意:Bazel目前不支持CGO的交叉编译。

4.更新BUILD文件

每当开发者对Kubernetes代码进行更新迭代、添加或删除Go语言文件代码,以及更改Go import时,都必须更新各个包下的BUILD和BUILD.bazel文件,更新操作可通过运行hack/update-bazel.sh脚本自动完成:

2.4.2 Bazel的工作原理

Kubernetes源码的根目录下有一个WORKSPACE(工作区)文件,用于指定当前目录是Bazel的一个工作区域,该文件一般存放在项目根目录下。另外,项目中包含一个或多个BUILD文件,用于告诉Bazel如何进行构建。Bazel工作原理如图2-3所示。

图2-3 Bazel工作原理

Bazel工作原理大致分为3部分。

(1)加载与Target相关的BUILD文件。

(2)分析BUILD文件的内容,生成Action Graph。

(3)执行Action Graph,最后产出Outputs。

以ABAC资源的BUILD文件为例,该文件定义在pkg/apis/abac/v1beta1/BUILD中:

ABAC资源的BUILD文件内容如下。

load:需要使用哪个.bzl规则来编译当前Target。

go_library:设置构建规则。

name:当前Target构建后的名称。

src:当前Target下被构建的源码文件。

deps:当前Target构建时依赖的静态库名称。

在Kubernetes项目代码中,BUILD文件可通过执行hack/update-bazel.sh脚本来自动生成。Bazel第一次构建时须生成Bazel Cache,时间较长,再次构建时无须再生成Bazel Cache,Bazel Cache有利于大大提高构建速度。

注意:Bazel目前并非完全支持Kubernetes代码生成器,当前只有openapi-gen和go-bindata是支持的。