本文发表已超过一年。较旧的文章可能包含过时的内容。请检查页面中的信息自发表以来是否仍然正确。

Kubernetes 在 MIPS 上运行

背景

MIPS (无互锁流水级微处理器) 是一种精简指令集计算机 (RISC) 指令集架构 (ISA),出现于 1981 年,由 MIPS Technologies 开发。现在 MIPS 架构广泛应用于许多电子产品中。

Kubernetes 已经正式支持多种 CPU 架构,如 x86、arm/arm64、ppc64le、s390x。然而,遗憾的是 Kubernetes 还不支持 MIPS。随着云原生技术的广泛应用,MIPS 架构下的用户也对在 MIPS 上运行 Kubernetes 有着迫切的需求。

成就

多年来,为了丰富开源社区生态,我们一直致力于调整 MIPS 架构以适应 Kubernetes 的使用场景。随着 MIPS CPU 的不断迭代优化和性能提升,我们在 mips64el 平台上取得了一些突破性进展。

多年来,我们一直积极参与 Kubernetes 社区,在使用和优化 Kubernetes 技术方面拥有丰富的经验。最近,我们尝试将 MIPS 架构平台适配到 Kubernetes,并在这段旅程中达到了一个新的阶段。团队已经完成了 Kubernetes 和相关组件的迁移和适配,不仅构建了一个稳定且高可用的 MIPS 集群,还完成了 Kubernetes v1.16.2 的一致性测试。

Kubernetes on MIPS

图 1 在 MIPS 上运行的 Kubernetes

K8S-MIPS 组件构建

几乎所有与 Kubernetes 相关的原生云组件都没有提供 MIPS 版本的安装包或镜像。在 MIPS 平台上部署 Kubernetes 的前提是在 mips64el 平台上编译和构建所有必需的组件。这些组件包括:

  • golang
  • docker-ce
  • hyperkube
  • pause
  • etcd
  • calico
  • coredns
  • metrics-server

得益于 Golang 出色的设计及其对 MIPS 平台的良好支持,上述云原生组件的编译过程得到了极大简化。首先,我们在 mips64el 平台编译了最新稳定版本的 Golang,然后我们使用源代码编译了上述大部分组件。

在编译过程中,我们不可避免地遇到了许多平台兼容性问题,例如 Golang 系统调用兼容性问题 (syscall),将 syscall. Stat_t 从 uint32 类型转换为 uint64,EpollEvent 补丁等等。

为了构建 K8S-MIPS 组件,我们使用了交叉编译技术。我们的过程包括集成 QEMU 工具来翻译 MIPS CPU 指令,并修改 Kubernetes 的构建脚本以及 Kubernetes、Hyperkube 和 E2E 测试镜像在 MIPS 架构上的 E2E 镜像脚本。

成功构建上述组件后,我们使用 kubespray 和 kubeadm 等工具完成了 Kubernetes 集群构建。

名称版本MIPS 仓库
golang on MIPS1.12.5-
docker-ce on MIPS18.09.8-
metrics-server for CKE on MIPS0.3.2registry.inspurcloud.cn/library/cke/kubernetes/metrics-server-mips64el:v0.3.2
etcd for CKE on MIPS3.2.26registry.inspurcloud.cn/library/cke/etcd/etcd-mips64el:v3.2.26
pause for CKE on MIPS3.1registry.inspurcloud.cn/library/cke/kubernetes/pause-mips64el:3.1
hyperkube for CKE on MIPS1.14.3registry.inspurcloud.cn/library/cke/kubernetes/hyperkube-mips64el:v1.14.3
coredns for CKE on MIPS1.6.5registry.inspurcloud.cn/library/cke/kubernetes/coredns-mips64el:v1.6.5
calico for CKE on MIPS3.8.0registry.inspurcloud.cn/library/cke/calico/cni-mips64el:v3.8.0 registry.inspurcloud.cn/library/cke/calico/ctl-mips64el:v3.8.0 registry.inspurcloud.cn/library/cke/calico/node-mips64el:v3.8.0 registry.inspurcloud.cn/library/cke/calico/kube-controllers-mips64el:v3.8.0

:CKE 是浪潮推出的基于 Kubernetes 的云容器引擎

K8S-MIPS Cluster Components

图 2 K8S-MIPS 集群组件

CPU Architecture

图 3 CPU 架构

Cluster Node Information

图 4 集群节点信息

运行 K8S 一致性测试

验证 K8S-MIPS 集群稳定性和可用性的最直接方法是运行 Kubernetes 一致性测试

一致性测试是一个独立的容器,用于启动 Kubernetes 端到端测试以进行一致性验证。

测试启动后,它会启动多个 Pod 进行各种端到端测试。这些 Pod 使用的镜像源代码主要来自 kubernetes/test/images,构建的镜像位于 gcr.io/kubernetes-e2e-test-images。由于仓库中没有 MIPS 镜像,我们必须首先构建运行测试所需的所有镜像。

构建测试所需镜像

第一步是找到测试所需的所有镜像。我们可以运行 sonobuoy images-p e2e 命令列出所有镜像,或者在 /test/utils/image/manifest.go 中找到这些镜像。尽管 Kubernetes 官方有一个完整的 Makefile 和 shell 脚本,提供了构建测试镜像的命令,但仍然存在许多与架构相关的问题尚未解决,例如基础镜像和依赖项的不兼容性。因此,我们无法通过直接执行这些命令来构建 mips64el 架构的镜像。

大多数测试镜像使用 golang 编写,然后编译成二进制文件,并基于相应的 Dockerfile 构建为 Docker 镜像。这些镜像很容易构建。但请注意,大多数镜像使用 alpine 作为基础镜像,而 alpine 目前官方尚不支持 mips64el 架构。目前我们无法制作 mips64el 版本的 alpine,所以我们必须将 alpine 替换为现有的 MIPS 镜像,例如 Debian-stretch、fedora、ubuntu。替换基础镜像还需要替换安装依赖项的命令,甚至这些依赖项的版本。

有些镜像不在 kubernetes/test/images 中,例如 gcr.io/google-samples/gb-frontend:v6。没有明确的文档说明这些镜像的位置,尽管我们在仓库 github.com/GoogleCloudPlatform/kubernetes-engine-samples 中找到了源代码。我们很快遇到了新问题:要构建这些 Google 示例镜像,我们必须构建它使用的基础镜像,甚至基础镜像的基础镜像,例如 php:5-apacheredisperl

经过漫长的镜像构建过程,我们最终构建了大约四打(约 48 个)镜像,包括测试 Pod 使用的镜像和基础镜像。运行测试前的最后一步是将所有这些镜像放入集群中的每个节点,并确保 Pod 的镜像拉取策略为 imagePullPolicy: ifNotPresent

以下是我们构建的一些镜像:

  • docker.io/library/busybox:1.29
  • docker.io/library/nginx:1.14-alpine
  • docker.io/library/nginx:1.15-alpine
  • docker.io/library/perl:5.26
  • docker.io/library/httpd:2.4.38-alpine
  • docker.io/library/redis:5.0.5-alpine
  • gcr.io/google-containers/conformance:v1.16.2
  • gcr.io/google-containers/hyperkube:v1.16.2
  • gcr.io/google-samples/gb-frontend:v6
  • gcr.io/kubernetes-e2e-test-images/agnhost:2.6
  • gcr.io/kubernetes-e2e-test-images/apparmor-loader:1.0
  • gcr.io/kubernetes-e2e-test-images/dnsutils:1.1
  • gcr.io/kubernetes-e2e-test-images/echoserver:2.2
  • gcr.io/kubernetes-e2e-test-images/ipc-utils:1.0
  • gcr.io/kubernetes-e2e-test-images/jessie-dnsutils:1.0
  • gcr.io/kubernetes-e2e-test-images/kitten:1.0
  • gcr.io/kubernetes-e2e-test-images/metadata-concealment:1.2
  • gcr.io/kubernetes-e2e-test-images/mounttest-user:1.0
  • gcr.io/kubernetes-e2e-test-images/mounttest:1.0
  • gcr.io/kubernetes-e2e-test-images/nautilus:1.0
  • gcr.io/kubernetes-e2e-test-images/nonewprivs:1.0
  • gcr.io/kubernetes-e2e-test-images/nonroot:1.0
  • gcr.io/kubernetes-e2e-test-images/resource-consumer-controller:1.0
  • gcr.io/kubernetes-e2e-test-images/resource-consumer:1.5
  • gcr.io/kubernetes-e2e-test-images/sample-apiserver:1.10
  • gcr.io/kubernetes-e2e-test-images/test-webserver:1.0
  • gcr.io/kubernetes-e2e-test-images/volume/gluster:1.0
  • gcr.io/kubernetes-e2e-test-images/volume/iscsi:2.0
  • gcr.io/kubernetes-e2e-test-images/volume/nfs:1.0
  • gcr.io/kubernetes-e2e-test-images/volume/rbd:1.0.1
  • registry.k8s.io/etcd:3.3.15(镜像自发布以来已更改 - 之前使用仓库 "k8s.gcr.io")
  • registry.k8s.io/pause:3.1(镜像自发布以来已更改 - 之前使用仓库 "k8s.gcr.io")

最后,我们运行了测试并获得了测试结果,包括 e2e.log 文件,其中显示所有测试用例均已通过。此外,我们还将测试结果提交到了 k8s-conformance,作为一项拉取请求

Pull request for conformance test results

图 5 一致性测试结果的拉取请求

后续计划

我们手动构建了 kubernetes-MIPS 组件并完成了兼容性测试,这验证了 Kubernetes 在 MIPS 平台上的可行性,极大地增强了我们推动 Kubernetes 支持 MIPS 架构的信心。

未来,我们计划积极向社区贡献我们的经验和成果,提交 PR,并为 MIPS 提交补丁。我们希望社区中有更多的开发者和公司加入我们,共同推动 Kubernetes 在 MIPS 平台上的发展。

贡献计划:

  • 贡献适用于 MIPS 的 e2e 测试镜像源代码
  • 贡献适用于 MIPS 的 hyperkube 源代码
  • 贡献适用于 MIPS 的 kubeadm 等部署工具源代码