本节我们一起来了解一下容器资源隔离性技术namespace。 namespace即命名空间,主要用来做访问隔离,针对一类资源进行抽象封装给一个容器使用,对于这类资源,每个容器都有自己的抽象,它们之间彼此不可见实现了访问隔离,例如PID namespace用来隔离进程号,User namespace用来隔离用户和用户组。
1.linux namespace的种类
linux共有6种命名空间:
- IPC: IPC(信号量、消息队列、共享内存等)隔离
- Network: 网络设备、网络栈、端口等隔离
- Mount: 文件系统挂载点隔离
- PID: 进程编号隔离
- User: 用户和用户组隔离
- UTS: 主机和域名隔离
另外从linux内核4.6开始提供了第7种namespace: CGroup namespace主要用于cgroup根目录隔离。
2.查看进程所属的namespaces
使用lsns命令可以查看当前系统已经创建的namesapce,第一列可以理解为namespace id:
lsns
NS TYPE NPROCS PID USER COMMAND
4026531836 pid 138 1 root /usr/lib/systemd/systemd --switched-root --system --deserialize 21
4026531837 user 139 1 root /usr/lib/systemd/systemd --switched-root --system --deserialize 21
4026531838 uts 138 1 root /usr/lib/systemd/systemd --switched-root --system --deserialize 21
4026531839 ipc 138 1 root /usr/lib/systemd/systemd --switched-root --system --deserialize 21
4026531840 mnt 128 1 root /usr/lib/systemd/systemd --switched-root --system --deserialize 21
4026531856 mnt 1 27 root kdevtmpfs
4026531956 net 138 1 root /usr/lib/systemd/systemd --switched-root --system --deserialize 21
4026532109 mnt 1 513 root /usr/lib/systemd/systemd-udevd
4026532133 mnt 1 670 root /usr/sbin/NetworkManager --no-daemon要查看一个进程所属的namespace信息,可以到/proc/<pid>/ns目录下查看:
ps -ef | grep mysqld
mysql 5662 ......
ll /proc/5662/ns
ipc -> ipc:[4026531839]
mnt -> mnt:[4026531840]
net -> net:[4026531956]
pid -> pid:[4026531836]
user -> user:[4026531837]
uts -> uts:[4026531838]这些namespace都是链接文件, 格式为namespaceType:[inode number]。inode number则用来标识一个namespace,可以理解为namespace id。 如果两个进程的某个namespace链接文件指向同一个,则其相关资源在同一个namespace中。例如,上面的msyqld进程是直接部署在测试服务器的,现在查看该服务器上sshd进程的namespace:
ps -ef | grep sshd
root 17114 ......
ll /proc/17114/ns
lrwxrwxrwx 1 ipc -> ipc:[4026531839]
lrwxrwxrwx 1 mnt -> mnt:[4026531840]
lrwxrwxrwx 1 net -> net:[4026531956]
lrwxrwxrwx 1 pid -> pid:[4026531836]
lrwxrwxrwx 1 user -> user:[4026531837]
lrwxrwxrwx 1 uts -> uts:[4026531838]可以看到sshd进程和mysqld进程的各种namespace都相同。
下面还是启动一个redis的containerd容器:
nerdctl run -d --name redis redis:alpine3.13查看容器进程的namespace:
lsns | grep redis
4026532170 mnt 1 16117 polkitd redis-server *:637
4026532171 uts 1 16117 polkitd redis-server *:637
4026532172 ipc 1 16117 polkitd redis-server *:637
4026532173 pid 1 16117 polkitd redis-server *:637
4026532175 net 1 16117 polkitd redis-server *:637可以看出,启动容器后,为redis容器进程创建了单独的mtn, uts, ipc, pid, net namespace,说明容器在这些namespace的资源抽象上是隔离的。