定制kubernetes源码的前提是需要知道如何编译kubernetes,我们需要掌握编译整个工程以及编译脚本具体做了哪些事以及如何编译单个组件等
笔者更推荐的还是在docker中进行编译,这样一致性比较好且比较容易复用
安装依赖
编译kubernetes有两种方式,如果有golang环境可以这样进行编译:
mkdir -p $GOPATH/src/k8s.io
cd $GOPATH/src/k8s.io
git clone https://github.com/kubernetes/kubernetes
cd kubernetes
make
快速开始
编译指定的某个组件
make WHAT=cmd/{$package_you_want}
# 如编译kubelet
make WHAT=cmd/kubelet
编译结束会输出到_output/bin
目录
跨平台编译:
make cross
安装etcd
cd $working_dir/kubernetes
# Installs in ./third_party/etcd
hack/install-etcd.sh
# Add to PATH
echo export PATH="\$PATH:$working_dir/kubernetes/third_party/etcd" >> ~/.profile
测试
cd $working_dir/kubernetes
执行一些校验操作如
hack/update-gofmt.sh 确定所有文件都被格式化 hack/update-bazel.sh 更新bazel编译依赖的文件
make verify
或者去执行所有的更新脚本
make update
执行单元测试用例
make test
执行特定的测试用例
make test WHAT=./pkg/api/helper GOFLAGS=-v
集成测试,需要依赖etcd
make test-integration
端到端测试,会创建集群,跑测试用例,删除集群,全部跑完很耗时间,运行指定的测试用例访问此链接./e2e-tests.md#building-kubernetes-and-running-the-tests
make test-e2e
或者在docker中进行编译,前提是已经安装了docker,在docker环境中编译非常简单,不用考虑安装一些依赖环境
快速开始
git clone https://github.com/kubernetes/kubernetes
cd kubernetes
make quick-release
前提条件
编译脚本介绍
在 build/ 目录有如下几个比较重要的脚本
build/run.sh make
仅编译linux二进制程序build/run.sh make cross
编译跨平台二进制程序build/run.sh make kubectl KUBE_BUILD_PLATFORMS=darwin/amd64
指定组件与平台编译build/run.sh make test
运行所有单元测试用例build/run.sh make test-integration
运行集成测试用例build/run.sh make test-cmd
运行命令行测试_output/dockerized/bin
拷贝到本地的 _output/dockerized/bin
, 编译完的二进制同样在该目录,build/run.sh会自动调用这个脚本进行拷贝编译环境介绍
要了解k8s的编译环境最重要的就是解读编译环境的Dockerfile, 有两个Dockerfile,一个用于构建基本镜像,我们来选取其中一些重要的东西分析一下,为了便于阅读分成几段去看
FROM golang:1.13.4
ENV GOARM 7
ENV KUBE_DYNAMIC_CROSSPLATFORMS \
armhf \
arm64 \
s390x \
ppc64el
ENV KUBE_CROSSPLATFORMS \
linux/386 \
linux/arm linux/arm64 \
linux/ppc64le \
linux/s390x \
darwin/amd64 darwin/386 \
windows/amd64 windows/386
选取一个golang的基础镜像,设置一些跨平台信息的环境变量
RUN for platform in ${KUBE_CROSSPLATFORMS}; do GOOS=${platform%/*} GOARCH=${platform##*/} go install std; done \
&& go clean -cache
预编译go标准库,跨平台编译时需要依赖这块
RUN apt-get update \
&& apt-get install -y rsync jq apt-utils file patch unzip \
&& apt-get clean && rm -rf /var/lib/apt/lists/*
安装依赖工具,这里注意依赖了rsync用于拷贝编译产物
RUN echo "deb http://archive.ubuntu.com/ubuntu xenial main universe" > /etc/apt/sources.list.d/cgocrosscompiling.list \
&& apt-key adv --no-tty --keyserver keyserver.ubuntu.com --recv-keys 40976EAF437D05B5 3B4FE6ACC0B21F32 \
&& apt-get update \
&& apt-get install -y build-essential \
&& for platform in ${KUBE_DYNAMIC_CROSSPLATFORMS}; do apt-get install -y crossbuild-essential-${platform}; done \
&& apt-get clean && rm -rf /var/lib/apt/lists/*
安装各个平台的build-essential
RUN PROTOBUF_VERSION=3.0.2; ZIPNAME="protoc-${PROTOBUF_VERSION}-linux-x86_64.zip"; \
mkdir /tmp/protoc && cd /tmp/protoc \
&& wget "https://github.com/protocolbuffers/protobuf/releases/download/v${PROTOBUF_VERSION}/${ZIPNAME}" \
&& unzip "${ZIPNAME}" \
&& chmod -R +rX /tmp/protoc \
&& cp -pr bin /usr/local \
&& cp -pr include /usr/local \
&& rm -rf /tmp/protoc \
&& protoc --version
安装protobuf,核心组件之间几乎都是通过proto进行通信
RUN go get golang.org/x/tools/cmd/cover \
golang.org/x/tools/cmd/goimports \
&& go clean -cache
cover是测试覆盖度工具,goimports是包导入工具
RUN export ETCD_VERSION=v3.2.24; \
mkdir -p /usr/local/src/etcd \
&& cd /usr/local/src/etcd \
&& curl -fsSL https://github.com/coreos/etcd/releases/download/${ETCD_VERSION}/etcd-${ETCD_VERSION}-linux-amd64.tar.gz | tar -xz \
&& ln -s ../src/etcd/etcd-${ETCD_VERSION}-linux-amd64/etcd /usr/local/bin/
最后跑测试时需要用到etcd
以上是基础镜像的核心内容, 上层镜像是一些比较简单的内容这里就不进行分析了,读者可自行到源码的 build/build-image 目录找到
发布
build/release.sh
脚本用于发布包, 编译二进制程序,跑测试用例和build运行时的Docker镜像
会输出kubernetes.tar.gz文件包含:
还会创建一些额外的压缩包
会先输出到 _output/release-stage 目录然后打包到 _output/release-tars 目录
接下来以在linux环境下Docker中编译为例子来讲解下如何编译kubeadm
安装git docker
yum install -y docker git
clone 代码
git clone https://github.com/kubernetes/kubernetes
build编译环境docker镜像
官方镜像非常大,build传输都非常麻烦,这里精简了一个Dockerfile:
mkdir build && cd build
cat <<EOF > FROM golang:1.13.4
RUN apt-get update \
&& apt-get install -y rsync jq apt-utils file patch unzip \
&& apt-get clean && rm -rf /var/lib/apt/lists/*
RUN PROTOBUF_VERSION=3.0.2; ZIPNAME="protoc-${PROTOBUF_VERSION}-linux-x86_64.zip"; \
mkdir /tmp/protoc && cd /tmp/protoc \
&& wget "https://github.com/protocolbuffers/protobuf/releases/download/v${PROTOBUF_VERSION}/${ZIPNAME}" \
&& unzip "${ZIPNAME}" \
&& chmod -R +rX /tmp/protoc \
&& cp -pr bin /usr/local \
&& cp -pr include /usr/local \
&& rm -rf /tmp/protoc \
&& protoc --version
RUN go get golang.org/x/tools/cmd/cover \
golang.org/x/tools/cmd/goimports \
&& go clean -cache
EOF
docker build -t kube-build:alpine .
编译源代码
这里把源代码挂载到容器中,方便在修改代码和编译
docker run -v /root/kubernetes:/go/src/k8s.io/kubernetes -w /go/src/k8s.io/kubernetes \
kube-build:alpine KUBE_GIT_TREE_STATE="clean" KUBE_GIT_VERSION=v1.17.0 KUBE_BUILD_PLATFORMS=linux/amd64 \
make all WHAT=cmd/kubeadm GOFLAGS=-v
KUBE_GIT_VERSION 环境变量是需要的,否则编译出来的二进制文件没有版本信息,会无法正常工作 KUBE_BUILD_PLATFORMS 指定平台
编译结束后ouput目录就能看到编译出来的bin文件了
ls _output/bin/
本期推荐几本杜军老师的书:
对于容器网络讲解是非常的全面透彻了,网络稀里糊涂的同学看看会有巨大的收获,觉得自己网络还可以的同学看看肯定也会查缺补漏有收获。
etcd是集群中最为重要的组件存储了集群的命脉,本书对原理讲的非常之深入,看不懂也要拿来拜拜