编译mips64le版k3s

前言

首先说明,本人使用的mips环境,处理器是Loongson-3A3000,系统是NeoKylin7 server。所有包的构建都是在这个环境下进行,由于没有其他mips环境,并不能保证其他mips环境能行。
由于业务需求,本人需要编译mips64le环境下的k3s 1.18.19版本。网上查了查,官方提供了编译方法,但是并不支持mips环境。mips环境下,只找到用go build直接编译的方法。于是尝试了一下,go build直接编译出来的k3s有200MB(官方的k3s只有40-60MB),这大小差了很多。那么这个k3s能不能用呢?能用,但是如果没安装kubernets-cni并将local-host放到PATH中的话,会报错。而且这个k3s别看他有200MB,但是helm, containerd等都没包含进去。如果这些你都无所谓,那么可以不用往下看了。直接用mips的golang go build使用就可以。但是如果你和我一样觉得很不爽,觉得这不是完整的k3s,可以继续往下。

准备

首先是编译mips版本k3s的前期准备工作,你需要一个mips的环境,以及mips的golang。如何从源码编译mips版本的golang,这里不多赘述,网上教程很多。如果你不想自己编译,也可以用我编译好的golang 1.16.5,链接放在文末。
除了golang的环境,还要对应k3s版本的源码,下载至mips环境,并解压。 解压后的k3s源码目录大致如下:

e2e          LICENSE    README.md
build         docker-compose.yml          etc          main.go    scripts
BUILDING.md   Dockerfile.dapper           go.mod       Makefile   tests
channel.yaml  Dockerfile.manifest         go.sum       manifests  Vagrantfile
cmd           Dockerfile.test.dapper      install.sh   package    vendor
contrib       Dockerfile.test.mod.dapper  k3s.service  pkg        vendor.go

按照官方的编译教程,在这个地方直接执行mkdir -p build/data && ./scripts/download && go generate然后再执行make就能编译出完整的k3s,but! mips环境不可以,因为执行make后是在docker容器中进行的编译工作,而Dockerfile.dapper中使用的ubuntu镜像,没有mips版。那么既然这个镜像不行,用mips版的其他镜像不就可以了?于是我去查了查,发现有mips版的Debian镜像和golang镜像,于是我开心的不得了,把Dockerfile进行了修改,并且发现他确实能make, but!! 还是不行。因为Debian镜像中缺少了一些依赖安装不了,并且编译过程会卡住。尝试多次无果后,我放弃了。
既然镜像编译不行,难道就真的没办法了吗? no no no, 我以前编译k8s的时候,是可以在本地进行编译的,所以为啥不直接不使用镜像,在本地编译k3s。所以我打算本地编译,在编译前先执行

mkdir -p build/data && ./scripts/download && go generate

发现这一步就错了。查看scripts/download的内容,主要是要下载一个叫k3s-root的东西,这个是k3s官方自己提供的,但是也没mips版本,所以这个也需要编译。

编译k3s-root

首先从github下载k3s-root源码,并解压到/source这个目录(没有就创建这个目录,这个位置很重要),解压后大概如下

busybox.config  Dockerfile.dapper  LICENSE   package  README.md  Vagrantfile
buildroot       iptables-detect    Makefile  patches  scripts

看上去和k3s差不多。同样的,不能用docker构件,所以查看Makefile和Dockerfile.dapper,发现就是执行了scripts/ci这个脚本。但是我们直接执行是不对的,查看scripts/build这个脚本,发现实际是编译了buildroot,这个感兴趣的可以了解一下。
在编译的时候的配置文件是/source/buildroot/${BUILDARCH}config,但是/source/buildroot/目录下是这样的:

[root@host30 buildroot]# ls
amd64config  arm64config  armconfig  config   ppc64leconfig

没有mips64elconfig,所以我研究了一下buildroot后,自己添加了mips64elconfig
执行vim /source/buildroot/mips64elconfig并添加以下内容

#
# Target options
#
BR2_ARCH_IS_64=y
BR2_ARCH_HAS_MMU_MANDATORY=y
# BR2_arcle is not set
# BR2_arceb is not set
# BR2_arm is not set
# BR2_armeb is not set
# BR2_aarch64 is not set
# BR2_aarch64_be is not set
# BR2_csky is not set
# BR2_i386 is not set
# BR2_m68k is not set
# BR2_microblazeel is not set
# BR2_microblazebe is not set
# BR2_mips is not set
# BR2_mipsel is not set
# BR2_mips64 is not set
BR2_mips64el=y
# BR2_mips64el is not set
# BR2_nds32 is not set
# BR2_nios2 is not set
# BR2_or1k is not set
# BR2_powerpc is not set
# BR2_powerpc64 is not set
#BR2_powerpc64le=y
# BR2_riscv is not set
# BR2_sh is not set
# BR2_sparc is not set
# BR2_sparc64 is not set
# BR2_x86_64 is not set
# BR2_xtensa is not set
BR2_ARCH_HAS_TOOLCHAIN_BUILDROOT=y
BR2_ARCH="mips64el"
BR2_ENDIAN="LITTLE"
BR2_GCC_TARGET_ARCH="mips64r2"
BR2_BINFMT_SUPPORTS_SHARED=y
BR2_READELF_ARCH_NAME="mips64el"
BR2_BINFMT_ELF=y
BR2_GCC_TARGET_ABI="64"
BR2_MIPS_CPU_MIPS64=y
BR2_mips_64=y
BR2_MIPS_NABI64=y
# BR2_MIPS_SOFT_FLOAT is not set
BR2_MIPS_NAN_LEGACY=y

保存后回到/source,执行BUILDARCH=mips64el scripts/ci。中间可能会跳出来一些选项如

choice[1]: 1
Target Architecture Variant
> 1. Generic MIPS64 (BR2_mips_64)
  2. Generic MIPS64R2 (BR2_mips_64r2) (NEW)
  3. Generic MIPS64R3 (BR2_mips_64r3) (NEW)
  4. Generic MIPS64R5 (BR2_mips_64r5) (NEW)
  5. Generic MIPS64R6 (BR2_mips_64r6) (NEW)
  6. I6400 (BR2_mips_i6400) (NEW)
  7. Octeon II (BR2_mips_octeon2) (NEW)
  8. Octeon III (BR2_mips_octeon3) (NEW)
  9. P6600 (BR2_mips_p6600) (NEW)
choice[1-9?]:
Target ABI
  1. n32 (BR2_MIPS_NABI32) (NEW)
> 2. n64 (BR2_MIPS_NABI64)

根据自己实际情况选。因为我是龙芯3A3000所以选的BR2_mips_64r2和n64
然后就是漫长的等待…
等编译结束后会在/source文件夹下多出artifactsdist两个文件夹。建议先执行下/source/artifacts/mips64el/bin/ip a如果报错如无法执行的二进制文件,那么说明编译错了,把artifactsdist/usr/src/buildroot删除,重新编译。如果执行没问题,那么dist文件夹下有我们编译出来的k3s-root的tar文件。
我编译出的k3s-root-mips64le.tar会放在文末,可以直接使用

k3s 编译

回到k3s源码的根目录,执行mkdir -p build/data && go generate
先执行vim scripts/package,把里面的

./package-image
./package-airgap

这两行注释掉,因为我们只编译k3s。
再执行vim scripts/download,将其中k3s-root部分注释并改为解压自己编译的k3s-root

#curl --compressed -sfL https://github.com/rancher/k3s-root/releases/download/${ROOT_VERSION}/k3s-root-${ARCH}.tar | tar xf -
cp /source/dist/k3s-root-${ARCH}.tar .
tar xf k3s-root-${ARCH}.tar 

最后执行SKIP_VALIDATE=true scripts/ci

可能遇到的问题

在编译k3s的过程中遇到了很多坑

  1. No package 'libseccomp' found error during runc build
    这个错是因为要安装libseccomp-devel或者libseccomp-dev,但是我的环境的源里没有,需要自己编译。
    runc releases下载libseccomp-2.5.1.tar.gz
    解压后,目录如下
aclocal.m4  config.status  configure.h.in   include           LICENSE      Makefile.in  stamp-h1
build-aux   configure      CONTRIBUTING.md  libseccomp.pc     m4           README.md    tests
CHANGELOG   configure.ac   CREDITS          libseccomp.pc.in  Makefile     SECURITY.md  tools
config.log  configure.h    doc              libtool           Makefile.am  src

执行

./configure
make
make install

如果过程中遇到

AUDIT_ARCH_MIPSEL64" undeclared here

这样的报错。参考issue,修改include/seccomp.h,tools/bpf.h和tools/util.h,都在合适的位置添加上

#ifndef AUDIT_ARCH_MIPSEL64
#define AUDIT_ARCH_MIPSEL64 (EM_MIPS|__AUDIT_ARCH_64BIT|__AUDIT_ARCH_LE)
#endif
  1. 缺少gperf
    下载源码
    解压后执行
./configure
make
make install
  1. use s.Rdev (type uint32) as type uint64
    这个是在mips编译k8s也会遇到的问题。根据报错把指定文件中的(buf.Dev)(buf.Rdev)分别改为(uint64(buf.Dev))(uint64(buf.Rdev))就可以了。

  2. 整个过程中还遇到了两个其它问题,但是由于发生时没有记录,现在忘记了。很惭愧。。

End

总之在排除了一系列的问题后,成功编译出了mips版本的k3s,大小为41MB。执行k3s server也能运行。

网盘链接

网盘中包括mips版的golang 1.16.5, k3s 1.18.19, k3s-root 0.8.1
链接:https://pan.baidu.com/s/1lH3RbBW9tiSmOd15xhOU_A
提取码:31bh


版权声明:本文为Timerzz原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接和本声明。