namespace 简介
namespace 可以做到对资源的隔离,不同namespace中的进程互不影响。
目前linux内核实现了7种不同的namespace:
名称 宏定义 隔离内容
Cgroup CLONE_NEWCGROUP Cgroup root directory (since Linux 4.6)
IPC CLONE_NEWIPC System V IPC, POSIX message queues (since Linux 2.6.19)
Network CLONE_NEWNET Network devices, stacks, ports, etc. (since Linux 2.6.24)
Mount CLONE_NEWNS Mount points (since Linux 2.4.19)
PID CLONE_NEWPID Process IDs (since Linux 2.6.24)
User CLONE_NEWUSER User and group IDs (started in Linux 2.6.23 and completed in Linux 3.8)
UTS CLONE_NEWUTS Hostname and NIS domain name (since Linux 2.6.19)
简单应用
preflight
准备一台物理机,拥有两张网卡。以nginx为例,在物理机上启动两个nginx,分别使用不同的网卡对外提供服务。
网卡信息如下:
网卡 | 网卡名 | ip |
---|---|---|
nic 1 | ens7f0 | 172.16.30.102 |
nic 2 | ens7f1 | 172.16.18.2 |
主机路由:
Kernel IP routing table
Destination Gateway Genmask Flags Metric Ref Use Iface
0.0.0.0 172.16.30.254 0.0.0.0 UG 0 0 0 ens7f0
169.254.0.0 0.0.0.0 255.255.0.0 U 1008 0 0 ens7f0
172.16.30.0 0.0.0.0 255.255.255.0 U 0 0 0 ens7f0
172.16.18.0 0.0.0.0 255.255.255.0 U 0 0 0 ens7f1
测试机:172.16.17.119
nginx安装在 /usr/local/nginx
目录下。
配置文件如下:
worker_processes 1;
events {
worker_connections 1024;
}
http {
include mime.types;
default_type application/octet-stream;
#log_format main '$remote_addr - $remote_user [$time_local] "$request" '
# '$status $body_bytes_sent "$http_referer" '
# '"$http_user_agent" "$http_x_forwarded_for"';
#access_log logs/access.log main;
sendfile on;
#keepalive_timeout 0;
keepalive_timeout 65;
server {
listen 80;
server_name localhost;
#charset koi8-r;
#access_log logs/host.access.log main;
location / {
root html;
index index.html index.htm;
}
error_page 500 502 503 504 /50x.html;
location = /50x.html {
root html;
}
}
}
启动nginx 并测试
[root@container1 ~]# /usr/local/nginx/sbin/nginx
在测试机上访问:
[root@walker-4 ~]# curl 172.16.30.102
<!DOCTYPE html>
<html>
<head>
<title>Welcome to nginx!</title>
<style>
body {
width: 35em;
margin: 0 auto;
font-family: Tahoma, Verdana, Arial, sans-serif;
}
</style>
</head>
<body>
<h1>Welcome to nginx!</h1>
<p>If you see this page, the nginx web server is successfully installed and
working. Further configuration is required.</p>
<p>For online documentation and support please refer to
<a href="http://nginx.org/">nginx.org</a>.<br/>
Commercial support is available at
<a href="http://nginx.com/">nginx.com</a>.</p>
<p><em>Thank you for using nginx.</em></p>
</body>
</html>
启动新namespace
新起一个终端(终端2)
linux 下提供了unshare
命令来启动新的namespace.
[root@container1 ~]# unshare -m -n /bin/bash
[root@container1 ~]# echo $$
45923
[root@container1 ~]# ip a
1: lo: <LOOPBACK> mtu 65536 qdisc noop state DOWN
link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
unshare -m -n
表示新建mnt和net
namespace.
上述命令可以看到,在新的namespace启动了一个bash进程,pid为45923
. 在新的namespace中,只有一个环回口,且处于down
的状态。
为新建的namespace分配网卡
将nic 2添加到新建的net namespace
中
进程所处的namespace可以通过
ls /proc/<pid>/ns/
看到
[root@container1 ~]# ip netns
[root@container1 ~]# ln -sf /proc/$$/ns/net /var/run/netns/test
[root@container1 ~]# ip netns
test
通过做软链接到/var/run/netns/
可以让 ip netns
命令识别到新建的net namespace
,并对其进行操作。
[root@container1 ~]# ip link set dev ens7f1 netns test
[root@container1 ~]# ip a
1: lo: <LOOPBACK> mtu 65536 qdisc noop state DOWN
link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
4: ens7f1: <BROADCAST,MULTICAST> mtu 1500 qdisc noop state DOWN qlen 1000
link/ether ac:1f:6b:2c:7e:ee brd ff:ff:ff:ff:ff:ff
[root@container1 ~]# ifup ens7f1
1: lo: <LOOPBACK> mtu 65536 qdisc noop state DOWN
link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
4: ens7f1: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc mq state UP qlen 1000
link/ether ac:1f:6b:2c:7e:ee brd ff:ff:ff:ff:ff:ff
inet 172.16.18.2/24 brd 172.16.18.255 scope global ens7f0
valid_lft forever preferred_lft forever
inet6 fe80::ae1f:6bff:fe2c:7eee/64 scope link
valid_lft forever preferred_lft forever
可以看到nic 2已经加入到新的net namespace
中。由于不同net namespace
中的协议栈和路由以及防火墙策略都是独立的,因此为了让外部主机能访问到172.16.18.2
,需要添加默认路由。
[root@container1 ~]# route -n
Kernel IP routing table
Destination Gateway Genmask Flags Metric Ref Use Iface
169.254.0.0 0.0.0.0 255.255.0.0 U 1004 0 0 ens7f0
172.16.18.0 0.0.0.0 255.255.255.0 U 0 0 0 ens7f0
[root@container1 ~]# route add default gw 172.16.18.254
[root@container1 ~]# route -n
Kernel IP routing table
Destination Gateway Genmask Flags Metric Ref Use Iface
0.0.0.0 172.16.18.254 0.0.0.0 UG 0 0 0 ens7f0
169.254.0.0 0.0.0.0 255.255.0.0 U 1004 0 0 ens7f0
172.16.18.0 0.0.0.0 255.255.255.0 U 0 0 0 ens7f0
为第二个nginx挂载新的目录
为了和第一个nginx区分开来,在新的mnt namespace
中挂载不同的 /usr/local/nginx/logs
和/usr/local/nginx/html
目录
[root@container1 ~]# dd if=/dev/zero of=./logs.disk bs=1M count=100
[root@container1 ~]# dd if=/dev/zero of=./html.disk bs=1M count=100
[root@container1 ~]# mkfs.xfs ./logs.disk
[root@container1 ~]# mkfs.xfs ./html.disk
[root@container1 ~]# mount ./logs.disk /usr/local/nginx/logs
[root@container1 ~]# mount ./html.disk /usr/local/nginx/html
[root@container1 ~]# echo "hello nginx" >> /usr/local/nginx/html/index.html
[root@container1 ~]# mount | grep nginx
/tmp/disk/html.disk on /usr/local/nginx/html type xfs (rw,relatime,attr2,inode64,noquota)
/tmp/disk/logs.disk on /usr/local/nginx/logs type xfs (rw,relatime,attr2,inode64,noquota)
在新
mnt namespace
中挂载的文件,对于原来的namespace是不可见的。即在终端1中是看不到新mount的目录
测试
在终端2中启动nginx
[root@container1 ~]# /usr/local/nginx/sbin/nginx
在测试机上,分别访问两个nginx:
nginx1:
[root@walker-4 ~]# curl 172.16.30.102
<!DOCTYPE html>
<html>
<head>
<title>Welcome to nginx!</title>
<style>
body {
width: 35em;
margin: 0 auto;
font-family: Tahoma, Verdana, Arial, sans-serif;
}
</style>
</head>
<body>
<h1>Welcome to nginx!</h1>
<p>If you see this page, the nginx web server is successfully installed and
working. Further configuration is required.</p>
<p>For online documentation and support please refer to
<a href="http://nginx.org/">nginx.org</a>.<br/>
Commercial support is available at
<a href="http://nginx.com/">nginx.com</a>.</p>
<p><em>Thank you for using nginx.</em></p>
</body>
</html>
nginx2 :
[root@walker-4 ~]# curl 172.16.18.2
hello nginx
由此,可以看到我们在一台服务器上启动了两个nginx,并利用net,mnt namespace
隔离了两个nginx进程。