1、kubernete 源码编译介绍
我们知道,kubernetes 源码编译,分为本地二进制可执行文件编译和 docker 镜像编译两种。之前演示的 minikube 方式或 kubeadm 方式安装,都是基于第二种 docker 镜像方式运行,当然也可以基于二进制文件方式安装,不管哪种方式,都是直接使用并不需要修改任何 k8s 代码。不过当我们有特殊需求时,比如需要修改 kube-proxy 对 service 的代理逻辑,kube-scheduler 对 pod 的调度逻辑等,这个时候就需要修改 k8s 源码了,为了让修改的代码生效,就需要对 k8s 代码执行编译了。当然 k8s 也为我们提供了 CRD 等可扩展插件,在不修改 k8s 源码的基础上实现自定义功能,但是对于一些底层逻辑策略需要修改的话,还是办不到的。
注意:因为 kubernetes 源码是由 go 语言编写的,所以要编译其源码,需要安装 go 环境,若我们想基于 docker 镜像编译 kubernetes 的话,那么还需要安装 docker 环境。
2、环境
Linux: CentOS Linux release 7.3.1611 (Core)
Docker: 18.06.1-ce
Golang: go1.11.5
Kubernetes: v1.13.4
2、安装依赖 golang、docker
2.1、安装 golang
注意:kubernetes 1.13 版本需要依赖的 go 版本 >= 1.11.1,所以安装时需选择该版本以上,否则下边编译时会报错终止,提示需要升级 go 版本,这里提供两种方式安装 golang 环境。
一、直接下载源码安装
$ cd opt && wget -c https://dl.google.com/go/go1.11.5.linux-amd64.tar.gz$ tar -C usr/local -xzf go1.11.4.linux-amd64.tar.gz$ echo "export PATH=$PATH:/usr/local/go/bin" >> etc/profile$ source /etc/profile
二、yum安装
$ cd /opt && wget http://download-ib01.fedoraproject.org/pub/epel/7/x86_64/Packages/g/golang-1.11.5-1.el7.x86_64.rpm$ yum -y install golang-1.11.5-1.el7.x86_64.rpm$ echo "GOPATH=/root/go" >> /etc/profile$ source etc/profile
3.2、安装 docker
docker 安装非常方便,针对自己系统参照 Docker 官网文档 安装即可,这里简单操作一下吧!
一键式安装方式:
$ curl -fsSL https://get.docker.com -o get-docker.sh$ sudo sh get-docker.sh
rpm 包 yum 安装方式:
$ wget https://download.docker.com/linux/centos/7/x86_64/stable/Packages/docker-ce-18.06.1.ce-3.el7.x86_64.rpm$ yum -y install docker-ce-18.06.1.ce-3.el7.x86_64.rpm$ systemctl enable docker$ systemctl start docker
yum 源安装方式:
$ yum install -y yum-utils device-mapper-persistent-data lvm2$ yum-config-manager --add-repo https://download.docker.com/linux/centos/docker-ce.repo$ yum install docker-ce docker-ce-cli containerd.io$ systemctl enable docker$ systemctl start docker
安装完毕后,执行 docker -v 命令能输出对应版本号,说明安装没问题。
4、二进制可执行文件编译 kubernetes
开始执行编译前,我们需要将 kubernetes 源码 拉取到本地 GOPATH
工作路径,并指定好 release-1.13
稳定分支。
$ mkdir -p $GOPATH/src/k8s.io && cd $GOPATH/src/k8s.io$ git clone https://github.com/kubernetes/kubernetes -b release-1.13$ cd kubernetes
我们从 kubernetes/hack/lib/golang.sh 代码中可以看到,该脚本会检测当前系统环境来安装对应的必要的服务,默认不指定 KUBE_BUILD_PLATFORMS(当前构建平台环境类型)的话,它会分别编译多种环境,编译时间很长,而且没有必要。这里我们可以直接修改文件中 KUBE_SERVER_PLATFORMS KUBE_NODE_PLATFORMS KUBE_CLIENT_PLATFORMS KUBE_TEST_PLATFORMS 配置,只保留当前系统对应环境,例如我们的系统环境为 linux/amd64。另一种方式就是在编译时,直接指定 KUBE_BUILD_PLATFORMS 参数即可。编译命令如下:
$ KUBE_BUILD_PLATFORMS=linux/amd64 make all GOFLAGS=-v GOGCFLAGS="-N -l"
对参数简单说明一下:
KUBE_BUILD_PLATFORMS=linux/amd64 指定当前编译平台环境类型为 linux/amd64。
make all 表示在本地环境中编译所有组件。
GOFLAGS=-v 编译参数,开启 verbose 日志。
GOGCFLAGS="-N -l" 编译参数,禁止编译优化和内联,减小可执行程序大小。
注意:执行以上命令时,需要机器可用内存在 4G 左右,否则编译时会报内存不够错误。若我们只想编译某个组件,例如,只想编译 kube-apiserver ,那么可以执行 make WHAT=cmd/kube-apiserver 命令。这里可选组件有很多,详细可参考 kubernetes/cmd/ 目录下所有组件。
稍等片刻,全部组件编译耗时较长,执行完毕后,二进制可执行文件默认生成到 kubernetes/_output/bin 目录下。
上边讲到单独对某个组件执行编译,除了上述办法之外,还可以进入到 kubernetes/cmd/
目录下对应组件下执行,例如我们编译 kube-apiserver
组件。
$ cd kubernetes/cmd/kube-apiserver$ go build -v$ lsapiserver.go app kube-apiserver BUILD OWNERS
5、docker 镜像编译 kubernetes
docker 镜像编译 kubernetes,可以编译出各核心组件二进制文件以及对应的镜像文件,这里得提一下,由于国内网络的问题,想顺利的安装 kubernetes,依赖镜像拉取问题比较麻烦,之前文章也提到过,可以通过 Github 配合 DockerHub 的 Auto build 功能,将镜像推送到 DockerHub,然后本地拉取后修改 tag 名称,操作有点麻烦,不过好歹解决了我们镜像拉取不到的问题。现在我们可以本地编译出 kubernetes 依赖的镜像了,那就很方便了,有木有。
具体涉及到的代码目录为 kubernetes/build,这里主要包含几个核心基础镜像的制作,包括 kube-cross、pause-amd64、debian-iptables-amd64、debian-base-amd64、debian-hyperkube-base-amd64。这里我偷个懒,先不挨个构建了,当然依旧可以通过上边提到的途径解决,直接拿别人构建好的镜像,拉取后修改 tag 即可。
docker pull xiaoxu780/pause-amd64:3.1docker pull xiaoxu780/kube-cross:v1.11.2-1docker pull xiaoxu780/debian-base-amd64:0.4.0docker pull xiaoxu780/debian-iptables-amd64:v11.0docker pull xiaoxu780/debian-hyperkube-base-amd64:0.12.0docker tag xiaoxu780/pause-amd64:3.1 k8s.gcr.io/pause-amd64:3.1docker tag xiaoxu780/kube-cross:v1.11.2-1 k8s.gcr.io/kube-cross:v1.11.5-1docker tag xiaoxu780/debian-base-amd64:0.4.0 k8s.gcr.io/debian-base-amd64:v1.0.0docker tag xiaoxu780/debian-iptables-amd64:v11.0 k8s.gcr.io/debian-iptables-amd64:v11.0.2docker tag xiaoxu780/debian-hyperkube-base-amd64:0.12.0 k8s.gcr.io/debian-hyperkube-base-amd64:0.12.0
注意:这里通过 kube-cross 组件有指定的版本,可以从 kubernetes/build/build-image/cross/VERSION 文件得到,我这里显示是 v1.11.5-1,跟上边提供的版本不一致,不过没关系,直接修改为该版本 tag 亲测没有问题的。
依赖的基础镜像本地已经有了,接下来需要修改构建策略,忽略 --pull 参数,不然每次构建还是会去外网拉取基础镜像,要让它直接读取本地镜像。修改 kubernetes/build/lib/release.sh 文件如下:
"${DOCKER[@]}" build --pull -q -t "${docker_image_tag}" "${docker_build_path}" >/dev/null修改为"${DOCKER[@]}" build -q -t "${docker_image_tag}" "${docker_build_path}" >/dev/null
其次修改 kubernetes/hack/lib/version.sh 文件,将变量 KUBE_GIT_TREE_STATE="dirty" 改为 KUBE_GIT_TREE_STATE="clean",dirty 表示 Git 提交 ID 之后的源代码有更改,clean 表示 Git 提交 ID 之后没有更改,为了确保版本号干净,都修改为 clean。
$ KUBE_BUILD_PLATFORMS=linux/amd64 KUBE_BUILD_CONFORMANCE=n KUBE_BUILD_HYPERKUBE=n make release-images GOFLAGS=-v GOGCFLAGS="-N -l"
说明一下:
UBE_BUILD_CONFORMANCE=n 和 KUBE_BUILD_HYPERKUBE=n 参数配置是否构建 hyperkube-amd64 和 conformance-amd64 镜像,默认是 y 构建,这里设置为 n 暂时不需要构建了。
make release-images 表示执行编译并生成镜像 tar 包。
稍等片刻,编译的 kubernetes 组件 docker 镜像以 tar 包的形式发布在 kubernetes/_output/release-tars/amd64
目录中。
ggg
生成的核心组件二进制可执行文件以及镜像,在 kubernetes/_output/release-stage/server/linux-amd64/kubernetes/server/bin/
目录可以找到。
稍等
这些镜像 tar 包是可以直接用的,这下再也不用担心镜像拉不下来了。
6、如何使用编译产物
之前我们使用 minikube 或 kubeadm 方式安装 kubernetes,都是基于 docker 镜像方式运行的,现在本地已经有镜像 tar 包了,只需要导入即可。
docker load -i kube-apiserver.tar
本地加载完镜像之后,可以修改/etc/kubernetes/manifests 的对应的yaml文件里的镜像地址images:xxxx ,保存之后k8s自动加载镜像并生效。




