一、编译说明

刚接触Kubernetes,便知道集群搭建需要下载一个gcr.io/google_containers/pause-amd64:3.0镜像,然后每次启动一个容器,都会伴随一个pause容器的启动,pause是每个pod需要的根镜像。

遇到这种情况我们都是通过有docker hub或者阿里云下载相关的pause镜像,然后通过tag修改景象名称,这里我们就操作一下如何手动去编译pause二进制和制作pause镜像。

二、编译环境准备

pause源码在kubernetes项目的kubernetes/build/pause/中,我们可以在github上进行下载,

git clone -b v1.10.3 https://github.com/kubernetes/kubernetes.git
​
ll kubernetes/build/pause
<<'COMMENT'
Dockerfile  Makefile  orphan.c  pause.c
COMMENT
​
包含了四个文件:
orphan.c是个测试文件可以不用管;
Makefile用于制作pause镜像,制作镜像的模板便是Dockerfile,非常重要;
pause.c是源码文件。

pause是C语言编写,我们可以看一下源码信息:

#include <signal.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <unistd.h>
​
#define STRINGIFY(x) #x
#define VERSION_STRING(x) STRINGIFY(x)
​
#ifndef VERSION
#define VERSION HEAD
#endif
​
static void sigdown(int signo) {
  psignal(signo, "Shutting down, got signal");
  exit(0);
}
​
static void sigreap(int signo) {
  while (waitpid(-1, NULL, WNOHANG) > 0)
    ;
}
​
int main(int argc, char **argv) {
  int i;
  for (i = 1; i < argc; ++i) {
    if (!strcasecmp(argv[i], "-v")) {
      printf("pause.c %s\n", VERSION_STRING(VERSION));
      return 0;
    }
  }
​
  if (getpid() != 1)
    /* Not an error because pause sees use outside of infra containers. */
    fprintf(stderr, "Warning: pause should be the first process\n");
​
  if (sigaction(SIGINT, &(struct sigaction){.sa_handler = sigdown}, NULL) < 0)
    return 1;
  if (sigaction(SIGTERM, &(struct sigaction){.sa_handler = sigdown}, NULL) < 0)
    return 2;
  if (sigaction(SIGCHLD, &(struct sigaction){.sa_handler = sigreap,
                                             .sa_flags = SA_NOCLDSTOP},
                NULL) < 0)
    return 3;
​
  for (;;)
    pause();
  fprintf(stderr, "Error: infinite loop terminated\n");
  return 42;
}
​

那么需要编译就需要系统上安装了可以编译c语言的gcc工具。

安装gcc工具的教程一大推,大家网上百度一下,这里讲一下如果进行跨平台交叉编译。我们正常使用的linux都是centos系列,使用的amd64(64位)/amd i386(32位)架构,所以安装相关的工具特别顺畅,但是遇到arm甚至更加变态的mips、mipsel架构,在mips上安装gcc装不上去,就无法进行编译,这时候我们就需要通过交叉编译。这里以mips为例。

我们这里使用的mips交叉编译的工具叫mips-linux-gcc。

网上有好多的都是arm-linux-gcc工具的教程,唯独MIPS这一块资料特别少,还有一部分通过buildroot工具进行编译,而且是基于ubuntu的,关于这个工具有时间可以取研究,建议使用这种方式。

下面介绍我本次安装交叉编译工具链的过程。

首先找到了相关的安装包: ftp://ftp.linux-mips.org/pub/linux/mips/people/macro/RPMS 在这个ftp服务器上,我找到了我需要的工具

/pub/linux/mips/people/macro/RPMS/ 的索引
[上级目录]
名称  大小  修改日期
i386/       2013/5/5 上午8:00:00
mips/       2012/9/2 上午8:00:00
mips64/     2013/5/5 上午8:00:00
mips64el/   2012/9/2 上午8:00:00
mipsel/     2012/9/2 上午8:00:00
noarch/     2012/12/26 上午8:00:00
vax/        2013/5/5 上午8:00:00

这里有两点需要注意:

第一:本人的系统是amd64的系统而不是i386,但是本人没有找到相关64位的包,暂且使用i386的包,至于兼容问题,我在下面的着重讲解。

第二:是我们下载文件的版本,必须版本一致,或者向上进行兼容。

首先我们的PC机是i386架构的,所以就进i386的目录下,可以看到很多mips这里有许多mips打头的rpm包,这些就是我们需要的工具链!

这时我们可以根据你所使用的mips处理器是大端或小端来下载所需的工具,大端的工具都是以mips开头的,而小端都是以mipsel开头,可以通过uname -r指令查看:

[root@master pause]# uname -r
3.10.0-862.ns7_4.016.mips64el
​
注意点:
mips:大端32位
mips64:大端64位
mipsel:小端32位
mips64el:小端64位
​
本人的就属于小端64位。

 

最后我们需要下载的是这几个包:

mips64el-linux-binutils-x.xx.x-x.i386.rpm

mips64el-linux-gcc-x.xx.x-x.i386.rpm

mips64el-linux-gcc-c-x.xx.x-x.i386.rpm

mips64el-linux-gcc-cpp-x.xx.x-x.i386.rpm

mips64el-linux-sim-x.xx.x-x.i386.rpm

各个rpm包的版本尽量保持一致,由于mips64el-linux-gcc-c-x.xx.x-x.i386.rpm是主要的安装包,其他包的版本信息尽量小于等于它。本人安装时使用的版本如下:

mips64el-linux-binutils-2.16.1-1.i386.rpm
mips64el-linux-gcc-4.0.1-1.i386.rpm
mips64el-linux-gcc-c-4.0.1-1.i386.rpm
mips64el-linux-gcc-cpp-4.0.1-1.i386.rpm
mips64el-linux-sim-6.8-2.i386.rpm

安装rpm包,rpm -ivh mips64el-linux*.rpm,会发现以下问题:

ld-linux.so.2 被 mips64el-linux-binutils-2.16.1-1.i386 需要
libc.so.6 被 mips64el-linux-binutils-2.16.1-1.i386 需要
libc.so.6(GLIBC_2.0) 被 mips64el-linux-binutils-2.16.1-1.i386 需要
libc.so.6(GLIBC_2.1) 被 mips64el-linux-binutils-2.16.1-1.i386 需要
libc.so.6(GLIBC_2.1.3) 被 mips64el-linux-binutils-2.16.1-1.i386 需要
libc.so.6(GLIBC_2.2) 被 mips64el-linux-binutils-2.16.1-1.i386 需要
libc.so.6(GLIBC_2.2.3) 被 mips64el-linux-binutils-2.16.1-1.i386 需要
......
等等一大推,这个问题就是我上面说到的第一个注意点,由于本人使用amd64位的,但是使用的包是amdi386的,所以需要安装兼容包。
安装指令:yum install glibc.i686
安装完成重复上面操作即可完成安装。

验证安装是否成功:

[root@master mips]# mips64el-linux-gcc -v
​
使用内建 specs。
目标:mips64el-linux
配置为:../configure --prefix=/usr --mandir=/man --with-local-prefix=/mips64el-linux/local --enable-libc --disable-multilib --enable-shared --enable-static --with-system-zlib --enable-threads --cache-file=config.cache --build=i386-linux --host=i386-linux --target=mips64el-linux
线程模型:posix
gcc version 4.0.1
​
​
看到最后的版本信息代表安装成功。

这几个工具装好之后,我们就可以写个helloworld测试一下了:

#include <stdio.h>
void main()
{
    printf("Hello World!\n");  
}

然后执行:

mips64el-linux-gcc hello.c -o hello

编译失败了。提示说找不到stdio.h,这是因为我们PC上并没有对应mips的动态链接库,所以我们编译的时候还需要加上静态选型

mips64el-linux-gcc -g hello.c -o hello -static

但是执行还是报错。

解决办法:我们还需下载一个静态库文件的包,有了这个包,我们的静态编译才能通过。

还是在ftp://ftp.linux-mips.org/pub/linux/mips/people/macro/RPMS/noarch/下面找到

mips-linux-glibc-devel-x.x.xx.noarch.rpm

mips-linux-glibc-static-x.x.xx.noarch.rpm

本人使用版本:

mips64el-linux-glibc-devel-2.4-13.noarch.rpm
mips64el-linux-glibc-static-2.4-13.noarch.rpm

最后我们就可以编译pause.c的源码了。

在源码包下面使用指令:
mips64el-linux-gcc -o pause pause.c
​
可得到pause文件
然后执行file pause,如果得到下面信息:
pause: ELF 64-bit LSB executable, MIPS, MIPS-III version 1 (SYSV), dynamically linked (uses shared libs), for GNU/Linux 2.4.0, not stripped
​
没有其他多余信息,比如with unknown capability 0x756e670000000f41 = 0x104000000070100,等等,代表编译成功。

编译就完成!!!!

Logo

开源、云原生的融合云平台

更多推荐