Overview Link to heading

虽然可以使用本地 golang 安装来构建 Kubernetes,但在 Docker 容器中运行的构建过程简化了初始设置,并提供了非常一致的构建和测试环境。尽管如此,本文还是会介绍本地 golang 和 Docker 容器两种构建方式,以供读者自由选择。

本地 golang 构建 Link to heading

本地 golang 构建的方式可以快速构建和调试所需的组件,而不需要一次构建所有的组件,同时也不需要容器运行时。该方案适用于对 Kubernetes 有二次开发/源码阅读需求的用户。

安装依赖 Link to heading

如何快速构建一个 Go 语言开发环境

下载 Kubernetes 源码 Link to heading

项目默认分支为 master 可以使用以下命令下载指定分支 / tag :

# 创建并进入 Kubernetes 专用的 workdir ,如:
mkdir -p /home/atompi/workdir/GolandProjects/Kubernetes
cd /home/atompi/workdir/GolandProjects/Kubernetes
export GOPATH=`pwd`
mkdir -p $GOPATH/src/k8s.io
cd $GOPATH/src/k8s.io
git clone https://github.com/kubernetes/kubernetes -b <branch/tag name>

编译 Link to heading

KUBE_BUILD_PLATFORMS 指定目标平台, WHAT 指定编译的组件,通过 GOFLAGSGOGCFLAGS 传入编译时参数,如此处编译 kubelet 组件。

KUBE_BUILD_PLATFORMS=linux/amd64 make all WHAT=cmd/kubelet GOFLAGS=-v GOGCFLAGS="-N -l"

make 参数说明:

  • WHAT :指定需要编译的包如 WHAT=cmd/kubelet ,如果不指定则编译全部
  • all :在本地环境中进行编译,相对于 releasequick-release 是在容器中完成编译并打包成 Docker 镜像,默认为 all
  • clean :清理编译结果以便重新编译

快速编译 Link to heading

编译过程较长,编译后的文件在 _output 里。可以在 cmd/xxx 目录下执行 go build -v 构建当前平台下当前的二进制包,构建结果直接输出在当前文件夹。如快速构建 kubelet :

cd cmd/kubelet
go build -v

容器化构建 Link to heading

如果利用容器化的构建环境,构建 Kubernetes 将变得非常简单。本文档将帮助您理解这一构建过程。

要求 Link to heading

  1. Docker,使用以下配置之一:

    • macOS 安装 Docker for Mac。安装说明请参见此处
      注意:您需要将 Docker 虚拟机的初始内存设置为至少 8GB,否则构建可能会失败。(参见:#11852)。
    • Linux 系统本地 Docker 根据您的操作系统说明安装 Docker。
    • Windows 使用 Docker Desktop WSL2 后端 根据说明安装 Docker。确保将源代码存储在本地 Linux 文件系统中,而不是 Windows 远程挂载点 /mnt/c 中。

    注意:您需要检查 Docker CLI 插件 buildx 是否正确安装(docker-buildx 文件应存在于 ~/.docker/cli-plugins 中)。您可以根据说明安装 buildx。

  2. 可选 Google Cloud SDK

如果您希望将发布版本上传到 Google Cloud Storage,则必须安装并配置 Google Cloud SDK,否则可以安全地忽略此步骤。

概述 Link to heading

您可以在两种环境中构建 Kubernetes:

  1. 本地 Go 环境
  2. Docker 容器 环境

在 Docker 容器中构建 Kubernetes 简化了初始设置,并提供了非常一致的构建和测试环境。

克隆仓库 Link to heading

在开始构建 Kubernetes 之前,请确保使用以下命令克隆仓库:

git clone https://github.com/kubernetes/kubernetes.git

在执行脚本文件之前,请导航至 Kubernetes 目录:

cd kubernetes

关键脚本 Link to heading

注意:确保从 Kubernetes 根目录运行所有脚本。

以下脚本位于 build/ 目录中:

  • build/run.sh: 在构建 Docker 容器中运行命令。常见调用方式包括:
    • build/run.sh make: 仅在容器中构建 Linux 二进制文件。根据需要传递选项和包。
    • build/run.sh make cross: 为所有平台构建所有二进制文件。若要仅构建特定平台,请添加 KUBE_BUILD_PLATFORMS=<os>/<arch>
    • build/run.sh make kubectl KUBE_BUILD_PLATFORMS=darwin/amd64: 为特定平台构建特定二进制文件(在此示例中分别为 kubectldarwin/amd64)。
    • build/run.sh make test: 运行所有单元测试。
    • build/run.sh make test-integration: 运行集成测试。
    • build/run.sh make test-cmd: 运行 CLI 测试。
  • build/copy-output.sh: 此脚本会将 _output/dockerized/bin 的内容从 Docker 容器复制到本地 _output/dockerized/bin。它还会复制生成过程中生成的特定文件模式。这是作为 build/run.sh 的一部分自动运行的。
  • build/make-clean.sh: 清理 _output 的内容,删除任何本地构建的容器镜像并删除数据容器。
  • build/shell.sh: 在构建容器中进入一个带有当前仓库代码快照的 bash shell。

基本流程 Link to heading

直接位于 build/ 下的脚本用于构建和测试。它们将确保 kube-build Docker 镜像已构建(基于 build/build-image/Dockerfile,并且在 Dockerfile 中的 KUBE_BUILD_IMAGE_CROSS_TAG 被替换为基本镜像的实际标签之一,例如 v1.13.9-2),然后在该容器中执行适当命令。这些脚本将确保从一次运行到下一次运行之间的正确数据被缓存以支持增量构建,并将结果复制回容器外部。您可以通过设置 KUBE_CROSS_IMAGEKUBE_CROSS_VERSION 来指定不同的注册表/名称和版本,更多详细信息请参见 common.sh

kube-build 容器镜像是通过首先在 _output/images/build-image 中创建一个“上下文”目录来构建的。这样做是为了减少在构建镜像时需要打包的数据量,而不是在 Kubernetes 仓库的根目录进行操作。

有 3 个不同的容器实例是从这个镜像运行的。第一个是“数据”容器,用于存储所有需要跨构建持久化的数据以支持增量构建。接下来是一个“rsync”容器,用于将数据传输到数据容器或从中传输数据。最后一个是“构建”容器,用于实际执行构建操作。数据容器会在多次运行之间持久存在,而 rsync 和构建容器在每次使用后都会被删除。

rsync 在幕后透明地用于高效地将数据移入和移出容器。这将使用 Docker 选择的临时端口。您可以通过设置 KUBE_RSYNC_PORT 环境变量来修改此行为。

所有 Docker 名称都带有基于文件路径派生的哈希值后缀(以允许在 CI 机器等上并发使用)和版本号。当版本号更改时,所有状态都会被清除并重新开始干净的构建。这使得构建基础架构可以更改,并向 CI 系统发出信号表明旧工件需要删除。

构建产物 Link to heading

构建系统将其所有输出到源代码仓库中的顶级目录 _output
这些包括编译后的二进制包(例如 kubectl、kube-scheduler 等)和归档的 Docker 镜像。
如果您打算使用 docker 镜像运行组件,则需要使用适当的命令从该目录加载它,例如:

docker load --input _output/release-images/amd64/kube-controller-manager.tar

发布 Link to heading

build/release.sh 脚本将构建一个发布版本。它将构建二进制文件、运行测试、(可选)构建运行时 Docker 镜像。

主要输出是一个 tar 文件:kubernetes.tar.gz。它包含:

  • 跨平台编译的客户端工具。
  • 用于根据平台选择并运行正确客户端二进制文件的脚本(kubectl)。
  • 示例
  • 各种云的集群部署脚本
  • 包含所有服务器二进制文件的 tar 文件

此外,还会创建一些其他 tar 文件:

  • kubernetes-client-*.tar.gz 特定平台的客户端二进制文件。
  • kubernetes-server-*.tar.gz 特定平台的服务器二进制文件。

在构建最终发布的 tar 文件时,它们首先会被暂存到 _output/release-stage,然后再被打包成 tar 并放入 _output/release-tars

可重复性 Link to heading

make release 及其变体 make quick-release 提供了一个封闭的构建环境,应该能为构建提供一定程度的可重复性。make 本身不是封闭的。

Kubernetes 构建环境支持由 Reproducible Builds 项目指定的 SOURCE_DATE_EPOCH 环境变量,它可以设置为 UNIX 时间戳。
这将用于嵌入到编译后的 Go 二进制文件中的构建时间戳,也许有一天也会用于 Docker 镜像。

对此变量的一个合理设置是使用正在构建的树的顶端提交时间戳;这是 Kubernetes CI 系统使用的。例如,您可以使用以下单行命令:

SOURCE_DATE_EPOCH=$(git show -s --format=format:%ct HEAD)