介绍
通过 k8s 源码运行一个集群的操作在 github 上有对应的文档,我这里主要记录一下过程中遇到的坑。
安装步骤
遇到的问题
运行环境问题
运行环境只能是 linux, 之前我看 Docker Desktop 里面可以在 mac 直接启动 k8s 集群,还以为官方提供的脚本也可以,配置好了环境后以为好了,运行一个 demo:
./cluster/kubectl.sh run my-nginx --image=nginx --port=80
查看 pod 详情
./cluster/kubectl.sh describe pod my-nginx
失败了
报错:no nodes available to schedule pods
查看一下 node
./cluster/kubectl.sh get nodes
No resources found
仔细观察 /hack/local-up-cluster.sh 脚本的输出
kubelet is not currently supported in darwin, kubelet aborted.
kubelet is not currently supported in darwin, kube-proxy aborted.
查了一下,https://github.com/kubernetes/kubernetes/issues/62940 这个脚本确实不能在 mac 上运行 kubelet 和 kube-proxy。
那我只能去 找一个 linux 环境了。
构建源码时报错 execvp: /usr/bin/env: Argument list too long
这个报错是在准备好 debian 的 k8s 开发环境后,运行 make WHAT=cmd/kubectl
构建时遇到的
这个报错是在 debian 系统报错的,报错原因看着是 shell 脚本传递的参数太多了,相同的源码,在 mac 上没报错。运行 git status
显示本地文件没有更改。
运行 getconf ARG_MAX
命令,查看参数长度限制
Mac 是 1048576 ,debian 是 2097152,dibian 比 mac 长,但是mac 构建成功了,debian 却失败了?
我决定查一下是哪个命令报错的,给 make 命令加上 -d 选项,并且设置 DBG_MAKEFILE 变量,打印处理详细的执行信息
make -d DBG_MAKEFILE=1
输出
// 忽略无关内容
Reading makefile '.make/go-pkgdeps.mk' (search path) (no ~ expansion)...
Makefile.generated_files:109: ***** finding all *.go dirs
make[1]: execvp: /usr/bin/env: Argument list too long
发现第一次报错是在 Makefile.generated_files:109 后面,看了一下上下文脚本,这里是把项目里面所所有 go 文件的文件名保存到了.make/all_go_dirs.mk
,然后下面的命令还出现了把文件内容作为参数传入命令行的操作,初步怀疑是这里超长了。
随便看了一下,发现有文件名重复了,有很多文件出现了两次,有一次多了个前缀 kubernetes, 一看根目录,确实有一个 kubernates 目录,里面是另一份源码。删除源码后,再次 make就成功了。
这个问题是多个因素导致的,刚开始,我没有把 k8s 源码放在 $GOPATH/src/k8s.io
里面,操作完回想了一下,老版本的 k8s 源码基于 GOPATH, 位置不对现在的版本代码运行正常,但是切换到老版本就运行不了了。
于是我直接运行 mv kubernetes $GOPATH/src/k8s.io/kubernetes
,把clone 好的文件夹移动过去了,然后到了新文件夹下 git status
后,没有更改,就以为移动成功了。
我运行的 mv 命令,如果 $GOPATH/src/k8s.io 目录下不存在 kubernetes 文件,那么就会把文件夹移动到 $GOPATH/src/k8s.io 下,如果已经有一个 $GOPATH/src/k8s.io/kubernetes 目录了,就会放在这个目录下面。所以我 mv 的代码实际去到了 $GOPATH/src/k8s.io/kubernetes/kubernetes 目录下。
那为什么 git status
看不出来文件夹里面多了一个文件夹呢?看了一下 .gitignore, 里面确实把根目录下的 kubernetes 文件夹加进去了。
cat .gitignore| grep kubernetes
/kubernetes/
# Downloaded kubernetes binary release tar ball
kubernetes.tar.gz
到这里这个问题就清楚了,前几天我已经放了一份源码到这个 debian 电脑了,但是忘记了,重新 clone 一份后 mv , 因为已经有一个 kubernetes 文件夹了,所以新源码被放到了根目录。然后刚好 k8s 的 .gitignore 把 kubernetes 文件夹加进去了,git 命令看着没有任何文件。构建的时候,脚本收集了项目的所有文件名,并且作为参数传给其他 shell 命令,两份项目的文件名超过了系统参数长度限制。
Go 版本
最新版 k8s 要求 18.2 , 我的版本不够,升级一下。
wget https://go.dev/dl/go1.18.4.linux-amd64.tar.gz
tar -zxvf go1.18.4.linux-amd64.tar.gz
# 可能你的go位置和我的不一样,使用 which go 查看
sudo mv /usr/local/lib/go /usr/local/lib/go.bak
sudo mv go /usr/local/lib/
APIServer 启动失败
脚本需要用 root 权限运行
忽略构建
每次启动构建没必要,可以先 make all
,然后启动集群的时候使用 sudo ./hack/local-up-cluster.sh -O
sudo ./hack/local-up-cluster.sh -O
安装了 etcd ,但是运行集群找不到 etcd,etcd must be in your PATH
首先我已经按照文档安装了etcd, https://github.com/kubernetes/community/blob/master/contributors/devel/development.md#etcd
运行命令如下
sudo ./hack/local-up-cluster.sh -O
然后确认 bash zsh 打开新窗口都能找到 etcd 了,但是运行的时候就是报 etcd must be in your PATH
搜索内容,发现是 hack/lib/etcd.sh:31 这个地方报出来的,启动脚本 这个地方调用了验证,hack/local-up-cluster.sh:1137 。
在调用前打印一下环境变量
echo `env`
发现 path 没了,又在脚本开头确认了一下,还是没有 path
检查了一下
sudo visudo
发现内容里面有Defaults env_reset
,这里设置成了 sudo 的时候不继承环境变量了。
可以改成Defaults !env_reset
,或者在暂时在 sudo 后加 env PATH=$PATH
新的运行命令
sudo env PATH=$PATH hack/local-up-cluster.sh -O
这次可以找到了
unknown service runtime.v1alpha2.RuntimeService
集群终于起来了, node 也 ok 了
./cluster/kubectl.sh get nodes
NAME STATUS ROLES AGE VERSION
127.0.0.1 Ready <none> 3h18m v1.25.0-alpha.3.129+12b22ede416177-dirty
运行了一个 pod, ./cluster/kubectl.sh run my-nginx --image=nginx --port=80
查看情况,./cluster/kubectl.sh describe pod my-nginx,发现报错了 unknown service runtime.v1alpha2.RuntimeService
找到了这个 issue https://github.com/containerd/containerd/issues/4581 ,跟着一通配置也不行,后面看https://github.com/kubernetes/kubernetes/issues/73189,需要重新安装一下containerd cri,https://github.com/containerd/containerd,
wget https://github.com/containerd/containerd/releases/download/v1.5.11/containerd-1.5.11-linux-amd64.tar.gz
sudo tar -C / -xzf cri-containerd-cni-1.5.11-linux-amd64.tar.gz
containerd config default > /etc/containerd/config.toml
systemctl enable containerd --now
systemctl restart containerd
我是在这里下载的containerd https://github.com/containerd/containerd/releases/tag/v1.5.11
保险起见,重启 docker
sudo service docker restart
# 发现启动失败了
systemctl status docker.service
# Failed to start docker.service: Unit docker.service is masked.
解决
systemctl unmask docker.service
systemctl unmask docker.socket
systemctl start docker.service
然后再尝试,报错变了
附录
- 前台启动 docker 并且输出 debug 日志:
sudo dockerd --debug
- Docke 在 debian 的日志位置: /var/log/daemon.log ,参考:https://blog.csdn.net/warrior_0319/article/details/79713155
Error response from daemon: Get "https://k8s.gcr.io/v2/": dial tcp 142.250.157.82:443: connect: connection timed out
这个就是镜像被墙了,需要配置代理或者镜像,这里需要注意的是,我给 docker 配置好镜像源后, docker pull k8s.gcr.io/pause:3.5
,没问题了,k8s 启动还是会报错,这里网上的资料基本是给 docker 配置后就可以了,最新版还不行。
后面才知道 还要给 containerd 配置一下,配置后还是报错,failed to do request: Head "https://k8s.gcr.io/v2/pause/manifests/3.5": dial tcp 142.250.157.82:443: connect: connection timed out
直接给 containerd 配置代理,问题解决。
参考:https://segmentfault.com/a/1190000020363043
Error response from daemon: OCI runtime create failed: unable to retrieve OCI runtime error
再次尝试 启动 pod , 发现 报错。
unable to retrieve OCI runtime error xxx/log.json: no such file or directory
看了Shashank V的回答https://stackoverflow.com/questions/59544107/docker-error-response-from-daemon-oci-runtime-create-failed-unable-to-retriev,试了一下 docker run hello-world
,也在报错,那应该是 docker 的问题。
再找了一下找到这个 issue https://github.com/moby/moby/issues/35906
是缺少 libseccomp 库
下载地址: https://packages.debian.org/zh-cn/sid/amd64/libseccomp2/download
wget http://ftp.us.debian.org/debian/pool/main/libs/libseccomp/libseccomp2_2.5.4-1+b1_s390x.deb
sudo dpkg -i libseccomp2_2.5.4-1+b1_s390x.deb
安装后 docker run hello-world
,正常了。
Apt 报错Unsupported proxy configured:
下载某些文件的时候再终端设置了 http 代理,运行 apt 会报错,把代理 unset 掉后不报错了。
运行成功
最终,通过源码构建一个集群并且运行一个 pod 成功
参考资料
https://github.com/kubernetes/community/blob/master/contributors/devel/development.md
https://github.com/kubernetes/community/blob/master/contributors/devel/running-locally.md
https://blog.csdn.net/yj1499945/article/details/80944203
https://mdnice.com/writing/3e3ec25bfa464049ae173c31a6d98cf8
https://blog.csdn.net/u011403655/article/details/50524071
https://blog.csdn.net/warrior_0319/article/details/79713155
https://segmentfault.com/a/1190000020363043
https://github.com/moby/moby/issues/35906
https://github.com/containerd/containerd/issues/4581
https://github.com/kubernetes/kubernetes/issues/73189
- 本文链接: http://hjwblog.com/archives/通过kubernetes源码在本地运行一个集群
- 版权声明: 本博客所有文章除特别声明外,均采用CC BY-NC-SA 3.0 许可协议。转载请注明出处!