pipework下载地址
解压之后,有一个pipework文件,其实就是shell脚本。
1.创建启动一个容器
docker run -it -d --name test_pipework --net=none centos bash
2.给docker设置ip
sh -x /usr/bin/pipework br0 test_pipework 192.168.0.12/24@192.168.0.254
这里给-x是为了看shell脚本的执行过程都打印出来,br0这个网桥不需要你提前创建,pipework在你执行这个语句的时候进行创建绑定,执行之后报错Object “netns” is unknown, try “ip help”.可以看到我们打印的执行过程最后一行是ip netns exec 6979 ip link set veth1pg6979 name eth1,恰恰说明了ip命令不支持netns选项
3.下载ip源码进行安装编译,为什么下载源码进行安装编译,后面会说,千万不要直接下载二进制ip命令文件。iproute2下载地址
4.解压之后编译源码,make,make install。再次执行,结果还是报错seting the network namespace failed: Function not implemented
5.我们可以去源码里面看这段报错是执行的哪一段代码,打开iproute2-3.1.0/ip/ipnetns.c文件,在static int netns_exec(int argc, char **argv)函数中

if (setns(netns, CLONE_NEWNET) < 0) 
{
	fprintf(stderr, "seting the network namespace failed: %s\n",
		strerror(errno));
	return -1;
}

我们再看setns函数

#ifndef HAVE_SETNS
static int setns(int fd, int nstype)
{
#ifdef __NR_setns
	return syscall(__NR_setns, fd, nstype);
#else
	errno = ENOSYS;
	return -1;
#endif
}
#endif /* HAVE_SETNS */

很明显,由于宏__NR_setns造成了没有调用syscall,我们可以修改代码

#ifndef __NR_setns
#if defined(__x86_64__)
#define __NR_setns 308
#elif defined(__i386__)
#define __NR_setns 346
#elif defined(__arm__)
#define __NR_setns 375
#elif defined(__aarch64__)
#define __NR_setns 375
#elif defined(__powerpc__)
#define __NR_setns 350
#elif defined(__s390__)
#define __NR_setns 339
#endif
#endif

#ifndef HAVE_SETNS
#if defined(__NR_setns)
#include <sys/syscall.h>
static int setns(int fd, int nstype)
{
	return syscall(__NR_setns, fd, nstype);
}
#else /* !__NR_setns */
#error Please determine the syscall number for setns on your architecture
#endif
#endif

再次编译,执行,成功!所以说不要下载ip命令二进制文件,我们要下载源码来编译,因为__NR_setns这个宏的值和系统相关。
6.再执行pipework br0 test_pipework 192.168.0.12/24@192.168.0.254没报错,查看一下是否成功
docker exec test_pipework ifconfig
这里写图片描述
7.但是你会发现在宿主主机和其它主机上ping这个docker还是ping不通,因为pipework仅仅只是给我们简单创建了一个br0网桥,但是还没有配置它,还需要我们自己配置
brctl show
这里写图片描述
brctl addbr br0
ip link set br0 up
ip addr add 192.168.0.99/24 dev br0
ip addr del 192.168.0.99/24 dev eth0
brctl addif br0 eth0
ip route del default
ip route add default via 192.168.0.254 dev br0
我们再看一下网桥brctl show
这里写图片描述
这里先是给br0设置了原本eth0的ip地址,然后把eth0删除这个ip地址,再把eth0作为br0的网口,最后删除默认路由,增加一个新路由
给docker设置ip成功之后,如果重启docker,设置会失效,需要再次调用pipework重新设置ip。
现在这个test_pipework已经可以在宿主主机和同一网段其它机器都可以ping通
8.代码修改部分是参考这里https://www.redhat.com/archives/libvir-list/2015-August/msg00910.html
9.docker0和br0的网络配置区别http://www.linuxidc.com/Linux/2016-08/134035.htm

Logo

权威|前沿|技术|干货|国内首个API全生命周期开发者社区

更多推荐