Kubeadm: Kubeadm 在 armv6l 上损坏

创建于 2017-04-23  ·  21评论  ·  资料来源: kubernetes/kubeadm

我试图在我的树莓派零 W 上安装 kubeadm,但收到“非法指令”
在 raspberry pi 3 (armv7) 上它工作得很好。

最有用的评论

是否可以讨论重新集成 armv6l 支持。 我发现很多帖子都显示了在 Pi Zero 和其他 armv6l Pi 设备上使用 Kubernetes 的兴趣。 P Zero 适合在 Kubernetes 或 Swarm 集群环境中托管微服务。 Docker Swarm 对我来说效果很好。 所以如果有人可以循环讨论,那就太好了。 Pi clusterhat 是一个不错的演示基础设施。

所有21条评论

我在 Raspberry Pi Model B+ 上的 kubeadm 1.6.1 也面临同样的问题,也是 armv6。

$ kubelet --help
Illegal instruction

$ uname -a
Linux pi1 4.4.50-hypriotos+ #2 PREEMPT Sun Mar 19 14:44:01 UTC 2017 armv6l GNU/Linux

我降级到 kubeadm 1.5.6 并且它有效。 1.6.0 给出与 1.6.1 相同的错误。

@clabu是的,降级到 1.5.6 有效,但无法加入 1.6+ 集群。

首先,感谢您在 ARM 上使用 Kubernetes :smile:!

这是一个已知的问题; 它在https://github.com/kubernetes/kubernetes/issues/38067 中进行了讨论,我们放弃了 armel 支持(RPi 1 的一部分在交叉编译时使用)。

基本上 armhf (GOARM=7) 不能在 Pi 1 上运行,所以我们在 -v1.5 中使用了带有 GOARM=6 的 armel 来支持 RPi 1。但是,我们在 v1.6 中使用了所有 armhf,因此它不起作用圆周率 1。

弃用 armel 并使用 armhf 图像,并使用 GOARM=7 而不是 GOARM=6
动机:

  • Go1.8 中唯一支持的 GOARM=6 板是 Raspberry Pi 1,它太慢而无法运行较新的 Kubernetes 版本。
  • 使用 GOARM=7 时的小性能改进
  • armel (http://hub.docker.com/u/armel) 图像不像 armhf (http://hub.docker.com/u/armhf) 图像那样经常更新。

例如, https://hub.docker.com/r/armel/debian/是在 8 个月前更新的,从安全角度来看这真的很糟糕,而https://hub.docker.com/r/armhf/debian/这是 3 天前更新的。

此外,通过 armhf 开关,我们可以使用https://hub.docker.com/r/armhf/alpine ,这很棒。

希望它有所帮助,但很抱歉不能再支持 RPi 1。

如果你想帮助记录它/传播这个词,请做或提出建议

我在 Pi Zero 上遇到了同样的问题

Linux p1 4.9.59+ #1047 Sun Oct 29 11:47:10 GMT 2017 armv6l GNU/Linux

是否可以讨论重新集成 armv6l 支持。 我发现很多帖子都显示了在 Pi Zero 和其他 armv6l Pi 设备上使用 Kubernetes 的兴趣。 P Zero 适合在 Kubernetes 或 Swarm 集群环境中托管微服务。 Docker Swarm 对我来说效果很好。 所以如果有人可以循环讨论,那就太好了。 Pi clusterhat 是一个不错的演示基础设施。

查看当前 docker.io 构建的 pi 零,
Go版本:go1.9.3
和 docker 版本:18.02.0-ce

它似乎确实使用了最新版本的 go。

我同意在独立模式下没有足够的 ram 可以在其上使用 k8s,但是让它成为更大主控上的从属,它应该有足够的资源来做一些有用的事情。

有谁知道是否可以仅从源代码构建以使用我的 pi 零作为 k8s 节点?

例如, https://hub.docker.com/r/armel/debian/是在 8 个月前更新的,从安全角度来看这真的很糟糕,而https://hub.docker.com/r/armhf/debian/这是 3 天前更新的。

今天的情况并非如此,因为不同架构上的官方镜像是同时更新的。 例如https://hub.docker.com/r/arm32v5/debian/https://hub.docker.com/r/arm32v7/debian/https://hub.docker.com/r/amd64/ debian/都在 9 天前更新。

此外,通过 armhf 开关,我们可以使用https://hub.docker.com/r/armhf/alpine ,这很棒。

https://hub.docker.com/r/arm32v6/alpine/在 Pi Zero 上运行良好。

我希望你能重新考虑一下。 阻止 Pi Zero 运行最新的 k8s 太令人失望了。

@luxas

+1。 由于重新安排了集线器并且旧的存储库仍然存在,因此发生了一些混乱。 较新的似乎确实得到了频繁的更新。

@juliancheal

我仍处于在 ClusterHAT 上构建 k8s 的过程中,但我能够为 Pi Zero 编译和构建二进制文件。

基本上,我遵循了以下内容并进行了一些修改:
https://povilasv.me/raspberrypi-kubelet/

我在 wsl 上工作过:
Linux 桌面-6GRDDIN 4.4.0-17134-Microsoft #48-Microsoft 星期五 4 月 27 日 18:06:00 PST 2018 x86_64 x86_64 x86_64 GNU/Linux

1 安装 gcc-arm-linux-gnueabi 而不是 gcc-arm-linux-gnueabihf

sudo apt-get install gcc-arm-linux-gnueabi <- 更改

2 在为 linux/arm 构建之前,对 hack/lib/golang.sh 中的 set_platform_envs() 进行两次修改

* 添加 GOARM出口GOOS=${平台%/ }出口GOARCH=${平台## /}出口 GOARM=5 <- 添加*更改 CC
案例“${platform}”在
“linux/arm”)
出口 CGO_ENABLED=1
出口 CC=arm-linux-gnueabi-gcc <-change
;;

GOARM 必须是 5。如果您指定 6,您将在构建期间收到链接器错误。 (这是我无法解决的。)

@shinichi-hashitani 它适用于我的 Pi Zero! 谢谢!

我也解决了你关于链接器错误的问题。 对于 Pi Zero,设置 GOARM=6 并保留 gcc-arm-linux-gnueabihf。 但是,对于 Pi 1,您必须设置 GOARM=5 并改用 gcc-arm-linux-gnueabi。

@shinichi-hashitani 这太棒了! 我会试试的谢谢!

@shinichi-hashitani 您是否使用make all KUBE_BUILD_PLATFORMS=linux/arm构建它? 如果您使用kubeadm来设置集群,您是如何做到的? 您是否复制了kubelet 、 init 脚本 povilasv 提到的kubeadmkubectl ? 它起作用了吗?

@dbwest是的,我使用 make all 来构建二进制文件。 我使用的确切命令是:

make all WHAT=cmd/kube-proxy KUBE_VERBOSE=5 KUBE_BUILD_PLATFORMS=linux/arm
make all WHAT=cmd/kubelet KUBE_VERBOSE=5 KUBE_BUILD_PLATFORMS=linux/arm
make all WHAT=cmd/kubectl KUBE_VERBOSE=5 KUBE_BUILD_PLATFORMS=linux/arm

我需要节点的二进制文件,所以只需要这三个二进制文件。

我没有使用 kubeadm。 我一直在关注 Kelsey Hightower 的“Kubernetes the Hard Way”。 如上所述这里,你只需要把这些二进制文件中适当的位置。

@shinichi-hashitani 知道您正在构建什么版本的 kubernetes 吗?

我没有运气让这个为 arm v6 构建(希望在 pi 零 w 上运行)。

在版本>= 1.12.0我得到这样的东西......

vendor/github.com/google/cadvisor/accelerators/nvidia.go:30:2: build constraints exclude all Go files in /private/var/folders/hn/gt2l8vq56vx9slvwry43xmz40000gn/T/tmp.A83ZihlF/_output/local/go/src/k8s.io/kubernetes/vendor/github.com/mindprince/gonvml
!!! [0511 07:36:41] Call tree:
!!! [0511 07:36:41]  1: /private/var/folders/hn/gt2l8vq56vx9slvwry43xmz40000gn/T/tmp.A83ZihlF/hack/lib/golang.sh:601 kube::golang::build_some_binaries(...)
!!! [0511 07:36:41]  2: /private/var/folders/hn/gt2l8vq56vx9slvwry43xmz40000gn/T/tmp.A83ZihlF/hack/lib/golang.sh:736 kube::golang::build_binaries_for_platform(...)
!!! [0511 07:36:41]  3: hack/make-rules/build.sh:27 kube::golang::build_binaries(...)
!!! Error in /private/var/folders/hn/gt2l8vq56vx9slvwry43xmz40000gn/T/tmp.A83ZihlF/hack/lib/golang.sh:561
  Error in /private/var/folders/hn/gt2l8vq56vx9slvwry43xmz40000gn/T/tmp.A83ZihlF/hack/lib/golang.sh:561. 'go install "${build_args[@]}" "$@"' exited with status 1

>= 1.10.0 & < 1.12.01.10.0是迄今为止我尝试过的最早的),我得到了这样的东西......

F0511 07:39:30.480641   26683 openapi.go:116] Failed loading boilerplate: open /private/var/folders/hn/gt2l8vq56vx9slvwry43xmz40000gn/T/tmp.A83ZihlF/_output/local/go/src/k8s.io/gengo/boilerplate/boilerplate.go.txt: no such file or directory
!!! Error in ./hack/run-in-gopath.sh:33
  Error in ./hack/run-in-gopath.sh:33. '"${@}"' exited with status 255
Call stack:
  1: ./hack/run-in-gopath.sh:33 main(...)
Exiting with status 1
make[1]: *** [pkg/generated/openapi/zz_generated.openapi.go] Error 1
make: *** [generated_files] Error 2

编辑:没关系...看起来如果我在 linux 机器上构建它可以工作。 我试图从我的 mac 上做到这一点

@ammmze

不完全确定是什么导致了您的问题,但以下是我的详细信息:
Kubernetes - 1.10.2
去 - 19.4
我使用 WSL(可能是 Ubuntu 16.x)来交叉编译这些二进制文件。

同样,我按照以下内容进行了一些修改:
https://povilasv.me/raspberrypi-kubelet/
您可以参考此来确认要执行的步骤。

我已经准备好了我的笔记和我遵循的确切步骤,但很抱歉,这仅提供日语版本:
https://qiita.com/ShinHashitani/items/ea9ffdefce8ca5786da6

是否有任何关于为 pi 零添加回 armel 支持的动向? 我有很多东西,并且很想制作一个低成本/功率集群用于演示目的

是否有任何关于为 pi 零添加回 armel 支持的动向? 我有很多东西,并且很想制作一个低成本/功率集群用于演示目的

嗨,正如你在上面的讨论中看到的,核心 Kubernetes 放弃了对 armv6l 的支持。
所以我不认为有机会重新添加这种支持。

如果您想在 armv6l 上使用 k8s / kubeadm,您必须重新编译所有内容(包括 CNI 图像)。

我只是想说,我已经通过在 golang:1.13-alpine docker 映像中编译成功从源代码编译了 K8s 1.18.3,该映像是一个多架构映像并包含一个 armv6。 (我将 Docker 配置为使用 QEMU 进行仿真,并且可以为其他架构运行容器。)

只需克隆 git repo,并按照自述页面上的 4 步 make 过程(即只制作所有 WHAT=cmd/component),除了 kubelet 之外的所有 k8s 组件都被静态编译并作为独立的可执行文件在我的 pi 零上运行,没有依赖关系。 (如果 golang-alpine 停止工作,我可以从头开始引导 Arch Linux ARM,这应该可以正常编译。)

唯一的问题是编译 kubelet 仍然动态链接到系统 glibc 库,我还没有想出如何解决这个问题。 我不是 go 程序员,我为 go 或 gcc 添加的编译标志似乎都没有什么不同。 (我猜 Kubelet 有一些 C 代码,因为它需要 gcc 来编译。)我猜最坏的情况我可以为我运行的每种类型的操作系统引导一个 docker 镜像,所以 glibc 动态链接将起作用,但我不想去做。

Debian 仍然官方支持 armel 并且有一个静态链接的 kubelet 版本的包,所以我目前的hacky 解决方案是从 armel deb 包中使用他们的静态二进制文件。

最后,您必须使用包含这些二进制文件(以及其他版本)的映像创建自己的存储库,并配置 kubeadm 以提取它们。 更有趣的是,虽然 Docker 运行在 arm6 上,但它错误地拉取了 arm7 映像(这是一个 3 年多的已知错误),因此您需要更改 arm7 映像以仅运行 armel 版本,或者将 arm6 和 arm7 都设置在相同的图像,只是让入口点是一个 shell 脚本,它在运行时确定是启动 arm6 还是 arm7 程序。 非主节点只需要运行 kubelet 和 kube-proxy,因此这些可能是您需要执行此操作的唯一映像。 (我读过的另一个关于人们使用的 hack 是拉取正确的图像,然后在本地将其重新标记为 kubeadm 想要拉取的任何图像,因此它只会使用本地版本。)

我实际上只是使用 ansible 来“艰难地”设置 k8s,但我打算仍然制作兼容的 Docker 镜像,这些镜像可以直接替换,这样 kubeadm 就可以使用它们。 如果我可以让 kubelet 正确地静态编译,我会将这个过程自动化到 Dockerfile 中,并将图像粘贴在 Docker Hub 上。 这些镜像将拥有尽可能多的架构,因此理想情况下,我们将能够在多架构集群上使用 kubeadm。 例如 amd64、arm64、arm6 和 arm7。 我估计 Pi Zero(作为工作节点)上的完整生产 Docker 和 K8s 仍然至少留下 50mb-100mb ram 来运行小图像。 如果我剥离内核,我可能可以再释放 30 或 40 兆。 但那是遥远的未来。 如果我可以在我的 Pi Zero 上获得由 K8s 管理的 nginx 容器提供的单个静态页面,我暂时称其为胜利。


8 月 7 日编辑:我已经设法让一切正常工作,目前有一个由 arm6、arm7、arm8 和 amd64 组成的 K8s 集群。 我很快就会在这里写下我的过程,但就目前而言,重要的一点是在 arm6 设备上安装 kubeadm 作为工作节点,您需要 kubeadm 和 kubelet 的二进制文件,并且只有两个容器, pause 容器和 kube-proxy 容器。 如果您有 QEMU,您可以使用 buildx 本地构建二进制文件,只需修改我的Dockerfile 。 (现在,那个 Dockerfile 实际上并没有完全工作——kube-controller-manager 构建一直冻结。但是你可以构建 kubelet、kubeadm、pause、kube-proxy 和 CNI 插件。)

或者,您可以从我为kubeadmkubelet制作的 Arch 包中的 /usr/bin 目录中提取静态二进制文件。 我在 Pi Zero 上安装了 Arch Linux ARM,所以 CNI 插件是通过一个包安装在我的系统中的,但是您可以使用我的 Dockerfile 构建它们(或从 Arch Linux ARM包中提取它们),然后将 CNI 二进制文件放入您系统上的目录“/opt/cni/bin/”。 如果您在该文件夹中有这些 CNI 二进制文件,并且安装了 kubelet 并准备好作为服务,那么您可以在设备上运行 kubeadm,它应该可以正常工作。 唯一的要求是您需要正确的 kube-proxy 和 pause 容器,这些容器已经可用于您的容器引擎。

在我的 Pi Zeroes 上,我安装了股票 Docker,我使用我从 Docker 文件构建的二进制文件,结合对官方 K8s 容器的分析,为kube-proxypause构建了一个兼容的 arm6 容器。 在 kubeadm 上将 Kubernetes 版本指定为 v1.18.6,需要将这些容器分别重新标记为“k8s.gcr.io/kube-proxy:v1.18.6”和“k8s.gcr.io/pause:3.2”,但如果这些如果容器已经存在并正确标记在您的系统上,那么 kubeadm 就会成功而不会抱怨。

唯一的另一个问题是有效的覆盖网络。 我不想经历更多的编译地狱,所以我使用了 Flannel,它的“arm”变体适用于 arm6 和 arm7。 您可以使用他们的默认 yaml 文件安装它。 但是,您应该为所有名为 FLANNEL_MTU 的部分添加一个 env var 并将其设置为 1430 或更低。 默认值 1500 会导致 metrics-server 出现一些问题。 此外,如果您想使用它,我将 Flannel 的所有图像组合成一个多架构图像。 这将允许您执行我所做的并将默认的 yaml 安装文件剥离为一个部分。

通过使用 kubeadm 和 Docker CE 的“完整”K8s 安装,我的 Pi Zeroes 在大约 55% 的 CPU 使用率下空闲,并且有大约 160MB 可用内存。 如果我们假设我想为突发容量留出至少 25%,那仍然留有大约 20%,相当于 200 毫秒。 (Pi Zero 有一个单核 1GHz CPU。)为了给一些额外的回旋余地,我四舍五入并将我的容器请求和限制设置为 120m,将 RAM 设置为 100MB。 到目前为止,一切正常。 唯一的问题是热量,因为我的零都挤在一个可爱的可堆叠箱子里,没有太多空气空间。

(当然,管理器节点不是 Pi Zero,而是 Pi 4。)


2020 年 12 月 1 日起编辑:这将是我的最后一次更新。 事实上,没有太多要补充的。 Kubeadm 有一个 yaml 配置文件,所有其他 k8s 组件也是如此,这些组件都没有很好的文档记录……但是如果您尝试一下,您可以一头雾水。

kubeadm 选项之一是为您的映像使用自定义注册表,因此您可以制作多架构映像并将其推送到私有注册表,然后将其用于您的设置,而不是简单地在 docker 中重新标记映像。 这就是我为了摆脱 docker 而直接使用 containerd 所做的事情。

我还没有弄清楚如何为 arm6 编译控制平面组件。 QEMU 和本机设备都不允许超过 1gb 的内存,这不足以让 Go 编译大部分控制平面。 我知道 Go 理论上可以为其他架构编译,所以我应该能够在我的 amd64 机器上编译 arm6,使用它的所有 ram。 但是对于我的生活,我无法让它工作,所以我只能在 QEMU 或设备本身上进行本地编译。 这意味着没有 arm6 控制平面组件。

但这是唯一的小问题。 Kubelet 和 kubeadm 编译,pause 容器和 kube-proxy 容器同样可以使用 buildx 构建。 因此,让工作节点组件为 arm6 工作仍然很容易。 但是,如果您正在使用 pi 零创建集群,请务必阅读 kubelet 配置文件,以便针对资源使用情况进行调整。 (或者,您知道,使用 k3s 或其他轻量级发行版,而不是完整的 k8s。)

我在这里发布了旧树莓模型的二进制文件https://github.com/aojea/kubernetes-raspi-binaries
它们是使用 github 操作作业创建的,因此可以随意重用它

此页面是否有帮助?
0 / 5 - 0 等级

相关问题

ep4eg picture ep4eg  ·  3评论

helphi picture helphi  ·  3评论

chuckha picture chuckha  ·  3评论

tmjd picture tmjd  ·  4评论

jbrandes picture jbrandes  ·  4评论