本文发表于一年多前。旧文章可能包含过时内容。请检查页面中的信息自发布以来是否已变得不正确。

MIPS 上的 Kubernetes

背景

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 仓库
MIPS 上的 golang1.12.5-
MIPS 上的 docker-ce18.09.8-
CKE 在 MIPS 上的 metrics-server0.3.2registry.inspurcloud.cn/library/cke/kubernetes/metrics-server-mips64el:v0.3.2
CKE 在 MIPS 上的 etcd3.2.26registry.inspurcloud.cn/library/cke/etcd/etcd-mips64el:v3.2.26
CKE 在 MIPS 上的 pause3.1registry.inspurcloud.cn/library/cke/kubernetes/pause-mips64el:3.1
CKE 在 MIPS 上的 hyperkube1.14.3registry.inspurcloud.cn/library/cke/kubernetes/hyperkube-mips64el:v1.14.3
CKE 在 MIPS 上的 coredns1.6.5registry.inspurcloud.cn/library/cke/kubernetes/coredns-mips64el:v1.6.5
CKE 在 MIPS 上的 calico3.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

经过漫长的镜像构建过程,我们最终完成了大约四十个镜像,包括测试 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)源代码