Cgroup和Namespace在测试中的使用(下)

 

Cgroup和Namespace在测试中的使用(下)

Namespace介绍

使用Namespace又叫做命名空间,可以让每个进程组具有独立的PID、IPC和网络空间等,也就是说这些系统资源不再是全局性的,而是属于特定的Namespace,每个Namespace里面的资源对其他Namespace都是透明的,从而达到资源的隔离效果。

目前namespace的种类如下

分类 系统调用参数
Mount namespaces CLONE_NEWNS
UTS namespaces CLONE_NEWUTS
IPC namespaces CLONE_NEWIPC
PID namespaces CLONE_NEWPID
Network namespaces CLONE_NEWNET
User namespaces CLONE_NEWUSER

可以查看自己的系统支持哪些namespace

# ls -lai /proc/1/ns
total 0
418834 dr-x--x--x root root Jul 30 22:58 .
1301 dr-xr-xr-x root root Jul 25 22:46 ..
418853 lrwxrwxrwx root root Jul 30 22:58 ipc -> ipc:[4026531839]
418856 lrwxrwxrwx root root Jul 30 22:58 mnt -> mnt:[4026531840]
418851 lrwxrwxrwx root root Jul 30 22:58 net -> net:[4026531957]
418854 lrwxrwxrwx root root Jul 30 22:58 pid -> pid:[4026531836]
418855 lrwxrwxrwx root root Jul 30 22:58 user -> user:[4026531837]
418852 lrwxrwxrwx root root Jul 30 22:58 uts -> uts:[4026531838]

各namespace的功能简述如下:

  • IPC namespaces 
    在一个 IPC 命名空间里面创建的 IPC 对象对该命名空间内的所有进程可见,但是对其他命名空间不可见。这样就使得不同命名空间之间的进程不能直接通信,就像是在不同的系统里一样。

  • MNT namespaces 
    MNT namespace是处理挂载点的,可以使不同容器拥有不同的挂载的文件系统和 root 目录。在一个MNT namespace 挂载的文件系统只能被同一个 namespace 里的进程所见。

  • UTS namespaces 
    UTS namespace提供了主机名和域名的隔离,这样每个容器就可以拥有了独立的主机名和域名,在网络上可以被视作一个独立的节点而非宿主机上的一个进程

  • User namespaces 
    User namespace是最新的子用户空间,它允许你创建独立于其他namespace之外的用户。这是通过GID和UID映射实现的。

  • PID namespaces 
    一个PID Namespace为进程提供了一个独立的PID环境,PID Namespace内的PID将从1开始,在Namespace内调用fork,vfork或clone都将产生一个在该Namespace内独立的PID。新创建的Namespace里的第一个进程在该Namespace内的PID将为1,就像一个独立的系统里的init进程一样

  • Network namespaces 
    主要提供了关于网络资源的隔离,包括网络设备、IPv4和IPv6协议栈、IP路由表、防火墙、/proc/net目录、/sys/class/net目录、端口(socket)等等。一个物理的网络设备最多存在在一个network namespace中,你可以通过创建veth pair(虚拟网络设备对:有两端,类似管道,如果数据从一端传入另一端也能接收到,反之亦然)在不同的network namespace间创建通道,以此达到通信的目的。

一般来说,由于创建namespace需要通过调用系统函数实现,如用clone函数创建一个独立namespace的进程

int clone(int (*child_func)(void *), void *child_stack, int flags, void *arg);

所以使用上并不平易近人,而Network namespaces可以通过命令配置,且使用的场景较多,故下面详细介绍Network namespaces

Network namespaces简单实战

增加一个network namespace的命令如下

ip netns add <network namespace name>

如增加一个名叫mltest的network namespace

# ip netns add mltest

查看一下

# ip netns list
mltest

也可以删除

# ip netns delete mltest

现在在这个namespace中做下ip addr,发现已默认创建一个回环设备(loopback interface:lo),通用的net namespace下的操作命令为ip netns exec [comand]

# ip netns exec mltest ip addr
1: lo: <LOOPBACK> mtu 65536 qdisc noop state DOWN group default
link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00

这里创建一个网络设备对, 为虚拟设备,用于2个namespace之间的网络通信,可以看到多出了2个设备veth0,veth1

# ip link add veth0 type veth peer name veth1
# ip link list
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN mode DEFAULT group default
link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
2: eth0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UP mode DEFAULT group default qlen 1000
link/ether 00:0c:29:72:bb:19 brd ff:ff:ff:ff:ff:ff
3: veth1: <BROADCAST,MULTICAST> mtu 1500 qdisc noop state DOWN mode DEFAULT group default qlen 1000
link/ether 46:76:1b:6d:c4:b2 brd ff:ff:ff:ff:ff:ff
4: veth0: <BROADCAST,MULTICAST> mtu 1500 qdisc noop state DOWN mode DEFAULT group default qlen 1000
link/ether 7e:da:61:d5:f8:bb brd ff:ff:ff:ff:ff:ff

然后将其中一个分配给刚才的namespace,然后在2个namespache下面各有一个虚拟设备

ip link set veth0 netns mltest
# ip link list
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN mode DEFAULT group default
link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
2: eth0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UP mode DEFAULT group default qlen 1000
link/ether 00:0c:29:72:bb:19 brd ff:ff:ff:ff:ff:ff
3: veth1: <BROADCAST,MULTICAST> mtu 1500 qdisc noop state DOWN mode DEFAULT group default qlen 1000
link/ether 46:76:1b:6d:c4:b2 brd ff:ff:ff:ff:ff:ff

# ip netns exec mltest ip link list
1: lo: <LOOPBACK> mtu 65536 qdisc noop state DOWN mode DEFAULT group default
link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
4: veth0: <BROADCAST,MULTICAST> mtu 1500 qdisc noop state DOWN mode DEFAULT group default qlen 1000
link/ether 7e:da:61:d5:f8:bb brd ff:ff:ff:ff:ff:ff

给这2个网络设备用ipconfig命令分配ip

# ip netns exec mltest ifconfig veth0 10.1.10.1/24 up
# ifconfig veth1 10.1.10.2/24 up

然后namespace mltest的配置基本完成了,在本机已有相同服务的情况下,在namespace里起同样端口的服务也不会有问题 
在每块网卡上都能建相同服务

netstat -lan|grep 50007
tcp 192.168.231.131:50007 0.0.0.0:* LISTEN
tcp 10.1.10.2:50007 0.0.0.0:* LISTEN
# ip netns exec mltest ./tcp_server.py &
[3] 19502

在namespace中也能创建相同服务

# ip netns exec mltest netstat -lan
Active Internet connections (servers and established)
Proto Recv-Q Send-Q Local Address Foreign Address State
tcp 10.1.10.1:50007 0.0.0.0:* LISTEN

本机直接访问毫无压力,显示的是从veth1访问的veth0

# telnet 10.1.10.1 50007
Trying 10.1.10.1...
Connected to 10.1.10.1.
Connected by ('10.1.10.2', 43755)

但是这里只配置了一对网络设备,多个namespace互相访问或者能够对外访问,就需要利用用网桥或NAT了,需要额外配置

通过网络隔离可以解决例如单机模拟多机部署,多实例同一端口不冲突这样的场景; 由于具有隔离性,某一namespace的route和iptables配置并不影响其他namespace里的应用,做异常测试也很适合。玩法很多,有用来做单机自环测试openvpn多处理的, 
国外有人在net namespace基础上做出一个轻量的了网络模拟器CORE

Namespace参考资料

ntroduction to linux namespaces这个系列写的很棒

总结

粗略的介绍了Cgroup和Namespace的基本概念和使用,可使用的场景很多,本文只是抛砖引玉,希望对大家有所启发

posted @ 2015-08-07 21:56  opama  阅读(1365)  评论(0编辑  收藏  举报