Linux namespace 介绍

发布时间: 更新时间: 总字数:1552 阅读时间:4m 作者: IP上海 分享 网址

Linux namespaceLinux 提供的一种内核级别环境隔离的方法。本文结合 unshare、介绍 Linux namespaces,该技术是容器(如Docker等)技术的基础。

namespace 机制

 -------------------------------------------
| Process1 | Process2 | Process1 | Process2 |
 -------------------------------------------
|      Namespace1     |      Namespace2     |
 -------------------------------------------
|              Linux Kernel                 |
 -------------------------------------------
|                Hardware                   |
 -------------------------------------------

Linux namespace 机制提供一种资源隔离和虚拟化技术。如上图中 Namespace1Namespace2 中经常需要有单独的 pid 命名空间,他们分别有自己的 init 进程(PID 为1)。

namespace 分类

Linux 从 Kernel 2.6 版本开始,逐步添加 Namespace 技术支持,Namespace 的 6 大类型如下:

namespace 系统调用参数 Kernel Version 作用
MNT(Mount) Namespaces CLONE_NEWNS Linux 2.4.19 提供磁盘挂载点和文件系统的隔离能力
UTS(Unix Timesharing System) Namespaces CLONE_NEWUTS Linux 2.6.19 提供独立的 hostnamedomainname
IPC(Inter Process Communication) Namespaces CLONE_NEWIPC Linux 2.6.19 提供进程间通信的隔离能力,包括消息队列,共享内存和信号量
PID(Process ID) Namespaces CLONE_NEWPID Linux 2.6.19 提供进程隔离能力
Net(Network) Namespaces CLONE_NEWNET Linux 2.6.24 ~ 2.6.29 网络隔离能力,提供独立的网络栈
User Namespaces CLONE_NEWUSER Linux 2.6.23 ~ 3.8 提供用户和用户组隔离能力

cgroup(control group) 为进程有一个独立的 cgroup 控制组

示例

# 宿主机
$ uname -a
Linux ubuntu 4.4.0-31-generic #50-Ubuntu SMP Wed Jul 13 00:07:12 UTC 2016 x86_64 x86_64 x86_64 GNU/Linux

# 获取当前进程PID
$ echo $$
2363

# 当前进程 namespace 信息
$ ls -lh /proc/$$/ns/
total 0
lrwxrwxrwx 1 root root 0 Jun  3 19:54 cgroup -> 'cgroup:[4026531835]'
lrwxrwxrwx 1 root root 0 Jun  3 19:54 ipc -> 'ipc:[4026531839]'
lrwxrwxrwx 1 root root 0 Jun  3 19:54 mnt -> 'mnt:[4026531840]'  # 不同 ns 的编号不同
lrwxrwxrwx 1 root root 0 Jun  3 19:54 net -> 'net:[4026531992]'
lrwxrwxrwx 1 root root 0 Jun  3 19:54 pid -> 'pid:[4026531836]'
lrwxrwxrwx 1 root root 0 Jun  3 19:54 pid_for_children -> 'pid:[4026531836]'
lrwxrwxrwx 1 root root 0 Jun  3 19:54 user -> 'user:[4026531837]'
lrwxrwxrwx 1 root root 0 Jun  3 19:54 uts -> 'uts:[4026531838]'

使用 lsns 命令查看当前系统有哪些 namespace,下面展示了系统默认的命令空间:

$ lsns
        NS TYPE   NPROCS   PID USER            COMMAND
4026531835 cgroup    330     1 root            /sbin/init splash
4026531836 pid       330     1 root            /sbin/init splash
4026531837 user      329     1 root            /sbin/init splash
4026531838 uts       327     1 root            /sbin/init splash
4026531839 ipc       330     1 root            /sbin/init splash
4026531840 mnt       317     1 root            /sbin/init splash
4026532000 net       329     1 root            /sbin/init splash

MNT Namespace

  • 无隔离时
# create tmp dir
mkdir /tmp/testdir

# mount tmpfs
mount -t tmpfs tmpfs /tmp/testdir

# touch file
cd /tmp/testdir
touch 1 2 3
  • 隔离时
$ unshare --mount /bin/bash
$ echo $$
27290  # 新的进程
$ ls -l /proc/$$/ns
total 0
lrwxrwxrwx 1 root root 0 Jun  3 20:00 cgroup -> 'cgroup:[4026531835]'
lrwxrwxrwx 1 root root 0 Jun  3 20:00 ipc -> 'ipc:[4026531839]'
lrwxrwxrwx 1 root root 0 Jun  3 20:00 mnt -> 'mnt:[4026532695]'  # 与没有隔离的 4026531840 不同
lrwxrwxrwx 1 root root 0 Jun  3 20:00 net -> 'net:[4026531992]'
lrwxrwxrwx 1 root root 0 Jun  3 20:00 pid -> 'pid:[4026531836]'
lrwxrwxrwx 1 root root 0 Jun  3 20:00 pid_for_children -> 'pid:[4026531836]'
lrwxrwxrwx 1 root root 0 Jun  3 20:00 user -> 'user:[4026531837]'
lrwxrwxrwx 1 root root 0 Jun  3 20:00 uts -> 'uts:[4026531838]'

# 进程隶属关系 2363 是 27290 的父进程
$ ps -ef |grep 27290 |grep -v grep
root       27290    2363  0 20:00 pts/0    00:00:00 /bin/bash
root       27336   27290  0 20:02 pts/0    00:00:00 ps -ef

$ pstree 2363
bash───bash───pstree
$ pstree 27290
bash───pstree

# mount tmpfs
mount -t tmpfs tmpfs /tmp/testdir

# 查看文件
$ ls -lh
total 0

结论:使用 unshare -m 或者 unshare –mnt 创建了隔离的 namespace。

IPC namespace

  • 无隔离时
$ ipcs

------ Message Queues --------
key        msqid      owner      perms      used-bytes   messages

------ Shared Memory Segments --------
key        shmid      owner      perms      bytes      nattch     status

------ Semaphore Arrays --------
key        semid      owner      perms      nsems
  • 隔离时
# 创建隔离的ipc namespace
unshare --ipc /bin/bash

# 查看
$ ls -l /proc/$$/ns
total 0
lrwxrwxrwx 1 root root 0 Jun  3 20:11 cgroup -> 'cgroup:[4026531835]'
lrwxrwxrwx 1 root root 0 Jun  3 20:11 ipc -> 'ipc:[4026532695]'  # id 变化
lrwxrwxrwx 1 root root 0 Jun  3 20:11 mnt -> 'mnt:[4026531840]'
lrwxrwxrwx 1 root root 0 Jun  3 20:11 net -> 'net:[4026531992]'
lrwxrwxrwx 1 root root 0 Jun  3 20:11 pid -> 'pid:[4026531836]'
lrwxrwxrwx 1 root root 0 Jun  3 20:11 pid_for_children -> 'pid:[4026531836]'
lrwxrwxrwx 1 root root 0 Jun  3 20:11 user -> 'user:[4026531837]'
lrwxrwxrwx 1 root root 0 Jun  3 20:11 uts -> 'uts:[4026531838]'

# 创建消息队列
$ ipcmk --queue

# 查看
$ ipcs

------ Message Queues --------
key        msqid      owner      perms      used-bytes   messages
0x22b527a3 0          root       644        0            0         # 新建

------ Shared Memory Segments --------
key        shmid      owner      perms      bytes      nattch     status

------ Semaphore Arrays --------
key        semid      owner      perms      nsems

退出,在原有中查看不到新建的 queue

$ exit
$ echo $$
2363
$ ipcs

------ Message Queues --------
key        msqid      owner      perms      used-bytes   messages

------ Shared Memory Segments --------
key        shmid      owner      perms      bytes      nattch     status

------ Semaphore Arrays --------
key        semid      owner      perms      nsems

UTS namespace

  • 隔离前
$ hostname
vm
  • 隔离后
$ echo $$
27458
$ ls -lh /proc/$$/ns
total 0
lrwxrwxrwx 1 root root 0 Jun  3 20:15 cgroup -> 'cgroup:[4026531835]'
lrwxrwxrwx 1 root root 0 Jun  3 20:15 ipc -> 'ipc:[4026531839]'
lrwxrwxrwx 1 root root 0 Jun  3 20:15 mnt -> 'mnt:[4026531840]'
lrwxrwxrwx 1 root root 0 Jun  3 20:15 net -> 'net:[4026531992]'
lrwxrwxrwx 1 root root 0 Jun  3 20:15 pid -> 'pid:[4026531836]'
lrwxrwxrwx 1 root root 0 Jun  3 20:15 pid_for_children -> 'pid:[4026531836]'
lrwxrwxrwx 1 root root 0 Jun  3 20:15 user -> 'user:[4026531837]'
lrwxrwxrwx 1 root root 0 Jun  3 20:15 uts -> 'uts:[4026532695]'  # 与之前 id 不同

# 修改 hostname
$ hostname
vm
$ hostname abc
$ hostname
abc

退出,在原有中查看不到新建的 queue

$ exit
$ echo $$
2363
$ hostname

PID namespace

  • 隔离后
# 隔离
$ unshare --fork --pid /bin/bash

# 进程信息为 1,证明时新的 pid
$ echo $$
1
$ ls -l /proc/$$/ns
total 0
lrwxrwxrwx 1 root root 0 Jun  3 20:03 cgroup -> 'cgroup:[4026531835]'
lrwxrwxrwx 1 root root 0 Jun  3 20:03 ipc -> 'ipc:[4026531839]'
lrwxrwxrwx 1 root root 0 Jun  3 20:03 mnt -> 'mnt:[4026531840]'
lrwxrwxrwx 1 root root 0 Jun  3 20:03 net -> 'net:[4026531992]'
lrwxrwxrwx 1 root root 0 Jun  3 20:03 pid -> 'pid:[4026531836]'
lrwxrwxrwx 1 root root 0 Jun  3 20:24 pid_for_children -> 'pid:[4026531836]'
lrwxrwxrwx 1 root root 0 Jun  3 20:03 user -> 'user:[4026531837]'
lrwxrwxrwx 1 root root 0 Jun  3 20:03 uts -> 'uts:[4026531838]'

USER namespace

  • 隔离前
$ id
uid=0(root) gid=0(root) groups=0(root)
  • 隔离后
$ unshare --user /bin/bash

$ echo $$
27684
$ ls -l /proc/$$/ns
total 0
lrwxrwxrwx 1 nobody nogroup 0 Jun  3 20:21 cgroup -> 'cgroup:[4026531835]'
lrwxrwxrwx 1 nobody nogroup 0 Jun  3 20:21 ipc -> 'ipc:[4026531839]'
lrwxrwxrwx 1 nobody nogroup 0 Jun  3 20:21 mnt -> 'mnt:[4026531840]'
lrwxrwxrwx 1 nobody nogroup 0 Jun  3 20:21 net -> 'net:[4026531992]'
lrwxrwxrwx 1 nobody nogroup 0 Jun  3 20:21 pid -> 'pid:[4026531836]'
lrwxrwxrwx 1 nobody nogroup 0 Jun  3 20:21 pid_for_children -> 'pid:[4026531836]'
lrwxrwxrwx 1 nobody nogroup 0 Jun  3 20:21 user -> 'user:[4026532695]'  # 与之前 id 不同
lrwxrwxrwx 1 nobody nogroup 0 Jun  3 20:21 uts -> 'uts:[4026531838]'

# 通过 id 证明在不同的 user ns 中
$ id
uid=65534(nobody) gid=65534(nogroup) groups=65534(nogroup)
Home Archives Categories Tags Statistics
本文总阅读量 次 本站总访问量 次 本站总访客数