对于 kubectl 还有 kubelet 这种比较简单,go build 之后直接把生成的二进制文件替换掉原来 /usr/bin 下面的就可以了,
但是有一些组件是需要启动一个 pod 来执行的,比如 apiserver,这就需要我们把修改后的源码编译成镜像,在编译的时候也是遇到了许多的坑,记录一下整个编译过程。
OS:centos7.6
kubernetes version:1.20.0
就拿 apiserver 组件来举例子
默认你已经有一个可用的k8s集群并且clone下来了k8s的源代码。
方法一
1.首先按照你自己的需要修改源代码
这个根据需要自己改就可以
2.执行镜像编译命令
KUBE_BUILD_PLATFORMS=linux/amd64 make quick-release
# KUBE_BUILD_PLATFORMS=linux/amd64 只编译生成针对linux的镜像,但是这个参数好像没必要,因为quick-release就有这样的效果
# quick-release 只生成linux64 位系统的镜像,不走test,主要是为了节省编译时间
# WHAT=cmd/kube-apiserver 只编译apiserver组件
直接在 kubernetes 代码目录下面执行就行,但是一般来说执行的时候肯定会报错,因为需要依赖的三个基础镜像是需要FQ的,我这边公司内部有对应的镜像资源,所以就直接修改了一下/data/gopath/src/k8s.io/kubernetes/build/common.sh
这个脚本,更换了一下镜像仓库的地址。
(line 46) readonly KUBE_BASE_IMAGE_REGISTRY="${KUBE_BASE_IMAGE_REGISTRY:-k8s.gcr.io/build-image}"
把这个命令里面的 k8s.gcr.io/build-image
换成你能获取镜像的仓库地址就行了。另外还可以去 dockerhub 上面找找有没有能用得上的,拉下来到本地,看看报错提示的是缺少哪个镜像,需要找到相对应的版本才行。
大概需要的就是下面这三个镜像,但是版本有可能有出入
k8s.gcr.io/build-image/go-runner buster-v2.2.2
k8s.gcr.io/build-image/kube-cross v1.15.5-1
k8s.gcr.io/build-image/debian-iptables buster-v1.3.0
总之,可以修改脚本里面的镜像仓库地址,保证 docker pull 可以成功,或者从别的地方 pull 下来对应的镜像,然后修改 tag。
做完这些之后,在执行KUBE_BUILD_PLATFORMS=linux/amd64 make quick-release
应该就不会报错了,如果还有错,需要你自己看看错误信息然后去解决一下了。
编译对硬件要求还是比较高的,我看推荐 需要 8G 内存,然后找了台 8G 的服务器,倒是没什么问题,就是编译的时间有点长。
然后可以在 kubernetes/_output/release-images/amd64/
下面找到编译成功的镜像压缩包了。
3.部署新的镜像
把你需要的镜像压缩包copy到集群的master上面,如果集群使用的是 docker 搭建的,应该直接使用 docker load
命令就可以把 tar 文件家在城 image 了,我这边是用的是 containerd 搭建的集群,需要使用
sudo ctr -n=k8s.io images import xxxxx.tar
去导入镜像,使用
crictl images list
查看镜像是不是导入成功,如果成功了,接着修改
/etc/kubernetes/manifests/kube-apiserver.yaml
文件,把里面的 image 字段修改成你刚刚导入的镜像名字,等一会,k8s 集群会自动重启。
大概等个几十秒就 应该重启完毕了,使用kubectl get pod -A
看看是不是所有 pod 都正常了,有可能会出现以下问题
Q1:Unable to connect to the server: x509: certificate signed by unknown authority (possibly because of "crypto/rsa: verification error" while trying to verify candidate authority certificate "kubernetes")
把 $HOME/.kube 这个删除了再试试
Q2:The connection to the server localhost:8080 was refused - did you specify the right host or port?
执行 export KUBECONFIG=/etc/kubernetes/admin.conf 命令试试
一般来说整个系统应该就可以使用新的镜像来正常工作了。
方法二
上面那种方法缺点是对应的镜像确实比较难找,我当初也是在网上找了半天,没找到我需要的版本,后来从同事口中得知公司内部镜像库都有的,然后就是编译环节,对机器配置要求高,编译时间长,每次都需要把四个组件全部编译一遍,具体能不能只编译单个组件我还没试过。
那么可以使用下面这种方法,就是自己写一个 dockerfile,还是用 apiserver 来举例:
apiserver 需要依赖一个 debian 的基础镜像,也就是我在上面列出的k8s.gcr.io/build-image/debian-iptables:buster-v1.3.0
这个镜像,这就可以随便换了,随便找一个 debian 的基础镜像就可以,我试过其他的 linux 发行版基础镜像也是可以的,把 debain 换成 centos 照样可以编译成功并且能正常工作。
1.首先把 apiserver 的代码 build 一下,生成二进制文件
2.写一个 dockerfile:
(第一行根据你的实际情况换一下基础依赖镜像)
FROM k8s.gcr.io/build-image/debian-iptables:buster-v1.3.0
ADD apiserver /usr/local/bin/kube-apiserver
WORKDIR /usr/local/bin/
3.然后执行docker build . -t xxxxxxx
(随便取个名字,版本号最好和其他的组件保持一致,比如写成 xxxxxxx:v1.20.0)
4.修改/etc/kubernetes/manifests/kube-apiserver.yaml
文件,把里面的 image 字段修改成你刚刚导入的镜像名字,等待集群重启