Linux NameSpace

NameSpace Namespace / Namespace

1. Introduction
1) Linux Namespace: It is a kernel-level environment isolation method provided by Linux.
1) The Linux Namespaces mechanism provides a resource isolation scheme. System resources such as PID, IPC, and Network are no longer global, but belong to a specific Namespace.
The resources in each namespace are transparent to other namespaces. To create a new Namespace, just specify the corresponding flag when calling clone. The Linux
Namespaces mechanism provides a good foundation for implementing container-based virtualization technology.
3) Demo code: test_clon.c

#define _GNU_SOURCE 
#include <sys/types.h>
#include <sys/wait.h>
#include <stdio.h>
#include <sched.h>
#include <signal.h>
#include <unistd.h>

/* 定义一个给 clone 用的栈,栈大小1M */
#define STACK_SIZE (1024 * 1024) 
static char container_stack[STACK_SIZE];

char* const container_args[] = {
    "/bin/bash",
    NULL
};

int container_main(void* arg)
{
    printf("Container - inside the container!\n");
    /* 直接执行一个shell,以便我们观察这个进程空间里的资源是否被隔离了 */
    execv(container_args[0], container_args);
    printf("Something's wrong!\n");
    return 1;
}

int main()
{
    printf("Parent - start a container!\n");
    /* 调用clone函数,其中传出一个函数,还有一个栈空间的(为什么传尾指针,因为栈是反着的) */
    int container_pid = clone(container_main, container_stack+STACK_SIZE, SIGCHLD, NULL);
    /* 等待子进程结束 */
    waitpid(container_pid, NULL, 0);
    printf("Parent - container stopped!\n");
    return 0;
}

/*
1.开辟一个新的命名空间

zhanglu@zhanglu0704:~/zhanglu0704/05_test/20180425$ gcc test_clon.c -o clon
zhanglu@zhanglu0704:~/zhanglu0704/05_test/20180425$ echo $$                  ## 显示进程号
14784

zhanglu@zhanglu0704:~/zhanglu0704/05_test/20180425$ ./clon
Parent - start a container!
Container - inside the container!
zhanglu@zhanglu0704:~/zhanglu0704/05_test/20180425$echo $$
14991                                                                        ## 进入新的命名空间,

zhanglu@zhanglu0704:~/zhanglu0704/05_test/20180425$ exit                     ## 退出这一空间
exit
Parent - container stopped!
zhanglu@zhanglu0704:~/zhanglu0704/05_test/20180425$echo $$
14784                                                                       ## 回到开始时的空间
*/

<1> Classification
Currently , Linux supports 6 different types of namespaces:
1. Mount namespaces: Provides disk mount point and file system isolation capabilities
2. UTS namespaces: Provides hostname isolation capabilities
3. IPC namespaces: Provides inter-process isolation capabilities Communication isolation ability 4.PID namespaces
: Provide process isolation ability
5.Network namespaces: Provide network isolation ability
6.User namespaces: Provide user isolation ability

<2> View the namespace of the current process:

$ echo $$              ##查看当前进程号
$ ls -al /proc/$$/ns/           ##查看命名空间
dr-x--x--x 2 user user 0 四月 25 16:43 ./
dr-xr-xr-x 9 user user 0 四月 25 16:38 ../
lrwxrwxrwx 1 user user 0 四月 25 16:43 cgroup -> cgroup:[4026531835]      
lrwxrwxrwx 1 user user 0 四月 25 16:43 ipc -> ipc:[4026531839]              ##不同的Namespace都有不同的编号 
lrwxrwxrwx 1 user user 0 四月 25 16:43 mnt -> mnt:[4026531840]
lrwxrwxrwx 1 user user 0 四月 25 16:43 net -> net:[4026531957]
lrwxrwxrwx 1 user user 0 四月 25 16:43 pid -> pid:[4026531836]
lrwxrwxrwx 1 user user 0 四月 25 16:43 user -> user:[4026531837]
lrwxrwxrwx 1 user user 0 四月 25 16:43 uts -> uts:[4026531838]

<3> Mount the isolated namespace (CLONE_NEWNS)
1) When calling clone, set CLONE_NEWNS, it will create a new mount Namespace. Each process exists in a mount Namespace
, which provides a file-level view for the process. If this flag is not set, the child process and the parent process will share a mount
Namespace, and subsequent calls to mount or umount by the child process will affect all processes in the Namespace.
2) If the child process is in a separate mount Namespace, it can call mount or umount to create a new file hierarchy view. This flag works with the
pivot_root system call to create an independent directory space for the process.
a. The mount without isolation
uses the memory-based file system tmpfs to simulate

$ echo $$
15541
$ mkdir /tmp/test/
$ sudo mount -t tmpfs tmpfs /tmp/test
$ cd /tmp/test/
$ touch aaa bbb ccc
另起终端查看
$ echo $$
16503
$ ls /tmp/test/
aaa  bbb  ccc
$ sudo umount /tmp/test/
b.隔离的挂载
# echo $$
17391
# unshare --mount /bin/bash
# echo $$
17467                                              ## 已经进入另一进程了
# ps -ef |grep 17391 |grep -v grep
root     17391 17390  0 17:09 pts/28   00:00:00 -su
root     17467 17391  0 17:09 pts/28   00:00:00 /bin/bash         ## 新进程是原进程的子进程
# mount -t tmpfs tmpfs /tmp/test/
# cd /tmp/test/
# touch aaa bbb ccc
# ls
aaa  bbb  ccc
另起终端查看
$ echo $$
16503
$ ls /tmp/test/
$ sudo ls -al /proc/17391/ns/mnt
lrwxrwxrwx 1 root root 0 四月 25 17:17 /proc/17391/ns/mnt -> mnt:[4026531840]          ## mount 命名空间A
$ sudo ls -al /proc/17467/ns/mnt
lrwxrwxrwx 1 root root 0 四月 25 17:17 /proc/17467/ns/mnt -> mnt:[4026532541]          ## mount 命名空间B
$ sudo ls -al /proc/16503/ns/mnt 
lrwxrwxrwx 1 user user 0 四月 25 17:18 /proc/16503/ns/mnt -> mnt:[4026531840]    ## A

3) Demo code test_mount.c

#define _GNU_SOURCE 
#include <sys/types.h>
#include <sys/wait.h>
#include <stdio.h>
#include <sched.h>
#include <signal.h>
#include <unistd.h>

/* 定义一个给 clone 用的栈,栈大小1M */
#define STACK_SIZE (1024 * 1024) 
static char container_stack[STACK_SIZE];

char* const container_args[] = {
    "/bin/bash",
    NULL
};

int container_main(void* arg) 
{ 
    printf("Container [%5d] - inside the container!\n", getpid()); 
    sethostname("container",10); 
    /* 重新mount proc文件系统到 /proc下 */ 
    system("mount -t proc proc /proc"); 
    execv(container_args[0], container_args); 
    printf("Something's wrong!\n"); 
    return 1; 
} 

int main() 
{ 
    printf("Parent [%5d] - start a container!\n", getpid()); 
    /* 启用Mount Namespace - 增加CLONE_NEWNS参数 */ 
    int container_pid = clone(container_main, container_stack+STACK_SIZE,  
            CLONE_NEWUTS | CLONE_NEWIPC | CLONE_NEWPID | CLONE_NEWNS | SIGCHLD, NULL); 
    waitpid(container_pid, NULL, 0); 
    printf("Parent - container stopped!\n"); 
    return 0; 
}

/*
同理,加入了挂载点隔离,程序执行后,两个空间的挂载点互相隔离,
A、B空间同时对同一目标文件进行mount、umount互不影响。 

$ sudo ./mnt 
Parent [26424] - start a container!
Container [    1] - inside the container!
# ls /proc/
1       buddyinfo  consoles  diskstats    fb           iomem    kallsyms   kmsg         loadavg  misc     net           schedstat  softirqs  sysrq-trigger  timer_stats  version_signature
15      bus        cpuinfo   dma          filesystems  ioports  kcore      kpagecgroup  locks    modules  pagetypeinfo  scsi       stat      sysvipc        tty          vmallocinfo
acpi    cgroups    crypto    driver       fs           ipmi     keys       kpagecount   mdstat   mounts   partitions    self       swaps     thread-self    uptime       vmstat
asound  cmdline    devices   execdomains  interrupts   irq      key-users  kpageflags   meminfo  mtrr     sched_debug   slabinfo   sys       timer_list     version      zoneinfo
# ps -aux
USER       PID %CPU %MEM    VSZ   RSS TTY      STAT START   TIME COMMAND
root         1  0.0  0.0  24588  5692 pts/1    S    20:42   0:00 /bin/bash
root        16  0.0  0.0  39104  3360 pts/1    R+   20:43   0:00 ps -aux
# top
top - 20:44:23 up 2 days,  4:25,  1 user,  load average: 0.98, 1.01, 0.72


Tasks:   2 total,   1 running,   1 sleeping,   0 stopped,   0 zombie
%Cpu(s):  0.8 us,  0.3 sy,  0.0 ni, 95.6 id,  3.3 wa,  0.0 hi,  0.0 si,  0.0 st
KiB Mem :  8091908 total,   211772 free,  3824828 used,  4055308 buff/cache
KiB Swap:  8303612 total,  8146764 free,   156848 used.  3380948 avail Mem 

PID USER      PR  NI    VIRT    RES    SHR S  %CPU %MEM     TIME+ COMMAND 
1 root      20   0   24588   5692   3648 S   0.0  0.1   0:00.01 bash                                                                                                                                    
17 root      20   0   43424   3740   3232 R   0.0  0.0   0:00.00 top                                                                                                                                     
 */

<4> Space for host name isolation (system call CLONE_NEWUTS)
1) It is used to isolate host names and network information services in different namespaces (for example, inside and outside the container).
2) Demo code: test_utc.c

#define _GNU_SOURCE 
#include <sys/types.h>
#include <sys/wait.h>
#include <stdio.h>
#include <sched.h>
#include <signal.h>
#include <unistd.h>

/* 定义一个给 clone 用的栈,栈大小1M */
#define STACK_SIZE (1024 * 1024) 
static char container_stack[STACK_SIZE];

char* const container_args[] = {
    "/bin/bash",
    NULL
};


/* 与uts有关的代码:此处只演示主机名的隔离 */
int container_main(void* arg) 
{ 
    printf("Container - inside the container!\n"); 
    sethostname("container",10); /* 设置hostname */ 
    execv(container_args[0], container_args); 
    printf("Something's wrong!\n"); 
    return 1; 
} 

int main() 
{ 
    printf("Parent - start a container!\n"); 
    int container_pid = clone(container_main, container_stack+STACK_SIZE,  
            CLONE_NEWUTS | SIGCHLD, NULL); /*启用CLONE_NEWUTS Namespace隔离 */ 
    waitpid(container_pid, NULL, 0); 
    printf("Parent - container stopped!\n"); 
    return 0; 
}
/*
 $ gcc test_utc.c -o utc 
 $ echo $$
 21132
 $ hostname
 ubuntu-ssh01
 $ ./utc 
 Parent - start a container!
 Parent - container stopped!
 $ echo $$
 21132
 $ hostname
 ubuntu-ssh01
 $ 
 */

<5>IPC namespace (system call CLONE_NEWIPC)
1) Inter-Process Communication (inter-process communication) methods mainly include pipes, shared memory, semaphores, message queues, and networks.
IPC has a global ID, and the Namespace needs to isolate this ID, and cannot be obtained by the processes of other Namespaces.
2) In principle:
When calling clone and setting CLONE_NEWIPC, a new IPC Namespace will be created, and the cloned process will become
the first process in the Namespace. An IPC Namespace consists of a set of System V IPC objects
identifiers . The IPC object created in an IPC Namespace is visible to all processes in the Namespace, but invisible to other Namespaces
, so that processes between different Namespaces cannot communicate directly, just like in different systems. When an IPC Namespace
is destroyed, all IPC objects in the Namespace will be automatically destroyed by the kernel.
3) Demo code: test_ipc.c

#define _GNU_SOURCE 
#include <sys/types.h>
#include <sys/wait.h>
#include <stdio.h>
#include <sched.h>
#include <signal.h>
#include <unistd.h>

/* 定义一个给 clone 用的栈,栈大小1M */
#define STACK_SIZE (1024 * 1024) 
static char container_stack[STACK_SIZE];

char* const container_args[] = {
    "/bin/bash",
    NULL
};


/* 与uts有关的代码:此处只演示主机名的隔离 */
int container_main(void* arg) 
{ 
    printf("Container - inside the container!\n"); 
    sethostname("container",10); /* 设置hostname */ 
    execv(container_args[0], container_args); 
    printf("Something's wrong!\n"); 
    return 1; 
} 

int main() 
{ 
    printf("Parent - start a container!\n"); 
    int container_pid = clone(container_main, container_stack+STACK_SIZE,  
            CLONE_NEWUTS | CLONE_NEWIPC | SIGCHLD, NULL); /*新增CLONE_NEWIPC就可以了 */ 
    waitpid(container_pid, NULL, 0); 
    printf("Parent - container stopped!\n"); 
    return 0; 
}
/*
 $ echo $$                                                                 NameSpace A
 24399
 $ ipcs -q                                                                 查看消息队列-->没有
 --------- 消息队列 -----------
 键        msqid      拥有者  权限     已用字节数 消息      

 $ ipcmk -Q                                                                创建一个消息队列,
 消息队列 id:65536                                                          id是65536
 $ ipcs -q
 --------- 消息队列 -----------
 键        msqid      拥有者  权限     已用字节数 消息      
 0xf1fde496 65536      user    644        0            0           
=========================================================================
 $ sudo ./utc                                                              先执行UTC(隔离主机名)的命名空间代码
 [sudo] user 的密码: 
 Parent - start a container!
 Container - inside the container!
 # echo $$                                                                 NameSpace B
 24487
 # ipcs -q                                                                 消息队列65536仍然可见

 --------- 消息队列 -----------
 键        msqid      拥有者  权限     已用字节数 消息      
 0xf1fde496 65536      user    644        0            0           
 # exit                                                                    退出NameSpace B
 ===================================================================
 $ gcc test_ipc.c -o ipc
 $ sudo ./ipc 
 Parent - start a container!
 Container - inside the container!
 root@container # echo $$
 24835                                                                     NameSpace B
 # ipcs -q
 --------- 消息队列 -----------
 键        msqid      拥有者  权限     已用字节数 消息                         查不到消息队列65536,同样在该命名空间如果创建消息队列,对NameSpace A也不可见
 # exit
 exit
 Parent - container stopped!
 $ ipcrm -q 65536                                                          删除队列
 */

<6> PID namespace (system call CLONE_NEWPID)
1) The PID in the space is allocated independently, the virtual PID in the namespace may conflict with the PID outside the namespace, so the PID in the namespace is mapped to
the outside of the namespace will use another PID. For example, the first PID of the init process in the container is 1, and outside the namespace is that the PID has been used by the
init process of the system, then another PID will be used to identify it in the system.
2) In principle:
1. When calling clone and setting CLONE_NEWPID, a new PID Namespace will be created, and the new process from clone will become
the first process in the Namespace. A PID Namespace provides an independent PID environment for the process. The PID in the PID Namespace will start from 1.
Calling fork, vfork or clone in the Namespace will generate an independent PID in the Namespace. The
first namespace will have a PID of 1 in that namespace, just like the init process in a separate system. All orphan processes in the Namespace will take
this process as the parent process. When the process is terminated, all processes in the Namespace will be terminated. The PID Namespace is hierarchical, and the newly created
Namespace will be a child Namespace of the Namespace that the process that created it belongs to.
2. The processes in the child Namespace are visible to the parent Namespace. A process will have more than one PID, but will have a PID in the Namespace where it is located and all
immediate ancestor Namespaces.
3. When the system starts, the kernel will create a default PID Namespace, which is the ancestor of all the Namespaces created later, so
all are visible in this Namespace.
3) Demo code: test_pid.c

#define _GNU_SOURCE 
#include <sys/types.h>
#include <sys/wait.h>
#include <stdio.h>
#include <sched.h>
#include <signal.h>
#include <unistd.h>

/* 定义一个给 clone 用的栈,栈大小1M */
#define STACK_SIZE (1024 * 1024) 
static char container_stack[STACK_SIZE];

char* const container_args[] = {
    "/bin/bash",
    NULL
};


int container_main(void* arg) 
{ 
    printf("Container PID: [%5d] - inside the container!\n",getpid()); /* 此处的getpid()是为了获取容器的初始进程(init)的pid */
    sethostname("container",10); /* 设置hostname */ 
    execv(container_args[0], container_args); 
    printf("Something's wrong!\n"); 
    return 1; 
} 

int main() 
{ 
    printf("Parent PID:[%5d] - start a container!\n",getpid()); /* 此处的getpid()则是为了获取父进程的pid */ 
    int container_pid = clone(container_main, container_stack+STACK_SIZE,  
            CLONE_NEWUTS | CLONE_NEWIPC | CLONE_NEWPID | SIGCHLD, NULL); 
    /*新增CLONE_NEWPID即可,此处代表在UTS和IPC隔离的基础之上再进行PID的隔离,其实我们完全可以只加CLONE_NEWPID自己:这样的话就只代表隔离PID了 */ 
    waitpid(container_pid, NULL, 0); 
    printf("Parent - container stopped!\n"); 
    return 0; 
}

/*
 $ gcc test_pid.c -o pid
 $ echo $$                                                ## namespace A
 25638
 $ sudo ./pid 
 Parent PID:[25732] - start a container!                  ## 父进程 PID 是namespace A中的进程号
 Container PID: [    1] - inside the container!           ## PID隔离后 namespace B的 第一个进程PID id=1
 # echo $$
 1
 # exit
 exit
 Parent - container stopped!
 $ echo $$
 25638
 $  
 */

<7> Network namespace (CLONE_NEWNET)
1) Used to isolate network resources (/proc/net, IP address, network card, routing, etc.). Background processes can run on the same port in different namespaces, and
users can also virtualize a network card. Each network namespace has its own routing table with its own iptables settings providing nat and filtering. Linux
network namespaces also provide the ability to run processes within network namespaces.
2) In principle:
1. When calling clone and setting CLONE_NEWNET, a new Network Namespace will be created. A Network Namespace provides a process with
a completely independent view of the network protocol stack. Including network device interfaces, IPv4 and IPv6 protocol stacks, IP routing tables, firewall rules, sockets, and more.
A Network Namespace provides an independent network environment, just like an independent system.
2. A physical device can only exist in one Network Namespace, and can be moved from one Namespace to another.
3. A virtual network device (virtual network device) provides a pipe-like abstraction that can establish tunnels between different Namespaces. Using virtualized
network devices, bridges can be established to physical devices in other namespaces. When a Network Namespace is destroyed, the physical device will be automatically moved back to the
init NetworNamespace, which is the first Namespace of the system
3) Kernel source code implementation:https://blog.csdn.net/hejin_some/article/details/71480862
4) The method of connecting the network namespace:
https://www.cnblogs.com/hustcat/p/3928261.html
https://blog.csdn .net/lineuman/article/details/52108191
a. Use a pair of veth pair: The
Use a pair of virtual ip pair communication model
picture comes from the Internet

$ su -                        ## 需要root权限
/* 创建网络命名空间  */
# ip netns add ns1
# ip netns add ns2
# ip netns list
ns2
ns1
# ls /var/run/netns/
ns1 ns2
/* 
   创建veth pair(虚拟网卡对,只能成对创建)
   Virtual Ethernet Pair简称veth pair,是一个成对的端口。
   所有从这对端口一 端进入的数据包都将从另一端出来 
*/
# ip link add tap1 type veth peer name tap2
# ip link list
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN mode DEFAULT group default qlen 1
    link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
2: enp2s0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UP mode DEFAULT group default qlen 1000
    link/ether 64:00:6a:19:6a:20 brd ff:ff:ff:ff:ff:ff
7: tap2@tap1: <BROADCAST,MULTICAST,M-DOWN> mtu 1500 qdisc noop state DOWN mode DEFAULT group default qlen 1000
    link/ether 12:8b:1a:ca:a6:cd brd ff:ff:ff:ff:ff:ff
8: tap1@tap2: <BROADCAST,MULTICAST,M-DOWN> mtu 1500 qdisc noop state DOWN mode DEFAULT group default qlen 1000
    link/ether 46:c5:09:8b:03:c8 brd ff:ff:ff:ff:ff:ff
/*将两个虚拟网卡分别添加到两个网络命名空间*/
# ip link set tap1 netns ns1
# ip link set tap2 netns ns2
# ip link list
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN mode DEFAULT group default qlen 1
    link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
2: enp2s0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UP mode DEFAULT group default qlen 1000
    link/ether 64:00:6a:19:6a:20 brd ff:ff:ff:ff:ff:ff
/*在当前的网络命名空间中就没有这两个虚拟网卡了,两个虚拟网卡备份配到网络命名空间ns1,ns2中*/
# ip netns exec ns1 ip link list
7: lo: <LOOPBACK> mtu 65536 qdisc noop state DOWN mode DEFAULT group default qlen 1
    link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
8: tap1@if5: <BROADCAST,MULTICAST> mtu 1500 qdisc noop state DOWN mode DEFAULT group default qlen 1000
    link/ether 46:c5:09:8b:03:c8 brd ff:ff:ff:ff:ff:ff link-netnsid 1
/*通过ip netns exec可以配置namespace的网口*/
# ip netns exec ns2 ip link set dev lo up
# ip netns exec ns1 ifconfig tap1 172.4.101.101/24 up
# ip netns exec ns1 ifconfig
lo        Link encap:本地环回  
          inet 地址:127.0.0.1  掩码:255.0.0.0
          inet6 地址: ::1/128 Scope:Host
          UP LOOPBACK RUNNING  MTU:65536  跃点数:1
          接收数据包:8 错误:0 丢弃:0 过载:0 帧数:0
          发送数据包:8 错误:0 丢弃:0 过载:0 载波:0
          碰撞:0 发送队列长度:1 
          接收字节:672 (672.0 B)  发送字节:672 (672.0 B)

tap1      Link encap:以太网  硬件地址 8a:65:a9:53:3d:9f  
          inet 地址:172.4.101.101  广播:172.4.101.255  掩码:255.255.255.0
          UP BROADCAST MULTICAST  MTU:1500  跃点数:1
          接收数据包:0 错误:0 丢弃:0 过载:0 帧数:0
          发送数据包:0 错误:0 丢弃:0 过载:0 载波:0
          碰撞:0 发送队列长度:1000 
          接收字节:0 (0.0 B)  发送字节:0 (0.0 B)

/*按相同方式配置ns2的tap2为172.4.101.102*/
/* 然后可以试一下,ns1和ns2的通讯 */
# ip netns exec ns2 ping 172.4.101.101
# ip netns exec ns1 ping 172.4.101.102
而这两个ip对于其他NetWork NameSpace是不能访问的。

b. Use (bridge or openvswitch) and multiple pairs of veth pair
two_veth_pair_brd.png
pictures from the network

1. The above method a uses a pair of virtual IPs to implement network access between two namespaces, but the communication between more than two (excluding two) NetWork NameSpaces
can not be implemented so simply. (Figure one_veth_pair.png)
2. At this time, you can use a bridge and multiple pairs of virtual network cards: each network namespace and the init network space have a virtual network card pair for communication, and
use a bridge or openvswitch between each namespace. The switch communicates (Figure: two_veth_pair_brd.png/two_veth_pair_switch.png).

/*删掉刚才创建的虚拟网卡对*/
ip netns exec ns1 ip link set dev tap1 down
ip netns exec ns2 ip link set dev tap2 down
ip netns exec ns1 ip link del tap1 type veth peer name tap2
/* 创建ns3 */
# ip netns list
/*创建网桥*/
# apt install bridge-utils
BRIDGE=br-test
brctl addbr $BRIDGE
brctl stp   $BRIDGE off
ip link set dev $BRIDGE up
# ifconfig 
br-test   Link encap:以太网  硬件地址 7e:d1:0b:14:0e:e0  
          inet6 地址: fe80::7cd1:bff:fe14:ee0/64 Scope:Link
          UP BROADCAST RUNNING MULTICAST  MTU:1500  跃点数:1
          接收数据包:0 错误:0 丢弃:0 过载:0 帧数:0
          发送数据包:30 错误:0 丢弃:0 过载:0 载波:0
          碰撞:0 发送队列长度:1000 
          接收字节:0 (0.0 B)  发送字节:4350 (4.3 KB)
# ip link list
15: br-test: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UNKNOWN mode DEFAULT group default qlen 1000
    link/ether 7e:d1:0b:14:0e:e0 brd ff:ff:ff:ff:ff:ff
/*
创建3对虚拟网卡,分别命名为tap1a,tap1b,tap2a,tap2b,tap3a,tap3b
并将 以a结尾的分别添加到对应的NameSpace,将以b结尾的添加到刚才创建的linux网桥br-test
*/
# ip link add tap1a type veth peer name tap1b
# ip link add tap2a type veth peer name tap2b
# ip link add tap3a type veth peer name tap3b
# ip link set tap1a netns ns1
# ip link set tap2a netns ns2
# ip link set tap3a netns ns3
# brctl addif br-test tap1b
# brctl addif br-test tap2b
# brctl addif br-test tap3b
/*配置3个namespace的网络*/
# ip netns exec ns1 ifconfig tap1a 172.4.101.101/24 up
# ip netns exec ns2 ifconfig tap2a 172.4.101.102/24 up
# ip netns exec ns3 ifconfig tap3a 172.4.101.103/24 up
/*set up 网桥中的虚拟网卡*/
# ip link set dev tap1b up
# ip link set dev tap2b up
# ip link set dev tap3b up
/*
  这时三个NameSpace之间可以互相通讯
  只要给网桥设置ip和子网掩码,即可在init网络命名空间访问ns1,ns2的ip。
*/

3. The principle of using openvswitch is the same as that of the bridge, and you can refer to the specific information.
two_veth_pair_switch.png

openvswitch_port.png
The picture comes from the Internet

<8>User namespace,
like process ID, user ID and group ID are different inside and outside the namespace, and the same ID can exist in different namespaces.

Second, the specific implementation of NameSpace:
https://blog.csdn.net/wangjianno2/article/details/50415835
https://blog.csdn.net/zhangyifei216/article/details/49788629
Third, the use of NameSpace
https:// blog.csdn.net/shichaog/article/details/41378145

Reference:
https://www.cnblogs.com/linhaifeng/p/6657119.html
https://www.cnblogs.com/ilinuxer/p/6188450.html
https://lwn.net/Articles/531114/
NameSpace Specific implementation:
https://blog.csdn.net/wangjianno2/article/details/50415835

Guess you like

Origin http://43.154.161.224:23101/article/api/json?id=325867990&siteId=291194637