docker背景知识1 命名空间Namespace(nsenter命令)

文章目录

  • 1. 什么是Linux namespace
  • 2. 探索namespaces
    • 2.1 查询本机所有namespaces
      • 2.1.1 通过lsns命令查看ns
      • 2.1.2 通过查看proc文件系统查看ns
    • 2.2 查看某个docker 容器的namespaces
    • 2.3 进入命名空间命令nsenter

如下操作都是在centos7上执行,通过cat /proc/version查看系统信息。

1. 什么是Linux namespace

linux namespaces是Linux提供的一种内核级别环境隔离的方法,也是Container环境隔离的底层技术,Linux Namespaces共有如下种类

分类 系统调用参数 相关内核版本
Mount namespaces CLONE_NEWNS Linux 2.4.19
UTS namespaces CLONE_NEWUTS Linux 2.6.19
IPC namespaces CLONE_NEWIPC Linux 2.6.19
PID namespaces CLONE_NEWPID Linux 2.6.24
Network namespaces CLONE_NEWNET Linux 2.6.29
User namespaces CLONE_NEWUSER Linux 3.8
  • Mount: mount表空间隔离,配合chroot系统调用,使程序有自己的文件系统
  • UTS: hostname(本地主机名)和doaminname隔离,使应用有自己独立的主机名
    假设分配UTS1、UTS2给2个进程P1、P2,那么P1看到的本地主机名H1,P2看到的本地主机名H2。放佛P1、P2是运行在2个不同的机器上一样。
  • IPC: 隔离进程间通讯
  • PID: 使程序包括子程序构造一个独立的程序集,最先创建的程序为1号pid
  • Network: 网络空间隔离,支行在此空间的程序拥有独立的网络栈。
    一个进程属于什么Network命名空间,决定了运行在进程里的应用程序能看见什么网络端口。每个网络接口属于一个命名空间,但是可以从一个命名空间转移到另一个。每个容器都使用属于它自己的网络命名空间,因此每个容器技能看到它自己的一组网络接口。
  • User: 此空间下有独立的uid/gid系统

因此,一个容器拥有一组命名空间,即Mount1、UTS1、IPC1、PID1、Network1、User1组合。

Namespaces操作的可以通过三个系统调用完成clone(),unshare(),setns(),默认情况下子进程继承新父进程的namespaces

2. 探索namespaces

2.1 查询本机所有namespaces

2.1.1 通过lsns命令查看ns

❯ sudo lsns
        NS TYPE  NPROCS   PID USER   COMMAND
4026531836 pid      317     1 root   /usr/lib/systemd/systemd --switched-root --system --deserialize 22
4026531837 user     318     1 root   /usr/lib/systemd/systemd --switched-root --system --deserialize 22
4026531838 uts      317     1 root   /usr/lib/systemd/systemd --switched-root --system --deserialize 22
4026531839 ipc      317     1 root   /usr/lib/systemd/systemd --switched-root --system --deserialize 22
4026531840 mnt      312     1 root   /usr/lib/systemd/systemd --switched-root --system --deserialize 22
4026531856 mnt        1    91 root   kdevtmpfs
4026531956 net      317     1 root   /usr/lib/systemd/systemd --switched-root --system --deserialize 22
4026532215 mnt        1  5127 chrony /usr/sbin/chronyd
4026532216 mnt        2  5120 root   /usr/sbin/NetworkManager --no-daemon
4026532219 mnt        1  6264 root   /usr/bin/simple
4026532220 uts        1  6264 root   /usr/bin/simple
4026532221 ipc        1  6264 root   /usr/bin/simple
4026532222 pid        1  6264 root   /usr/bin/simple
4026532224 net        1  6264 root   /usr/bin/simple
4026532281 mnt        1  5438 root   /usr/sbin/cupsd -f

2.1.2 通过查看proc文件系统查看ns

❯ sudo ls -l /proc/*/ns/ |awk '{print $11}' |sort -u
ipc:[4026531839]
ipc:[4026532221]
mnt:[4026531840]
mnt:[4026531856]
mnt:[4026532215]
mnt:[4026532216]
mnt:[4026532219]
mnt:[4026532281]
net:[4026531956]
net:[4026532224]
pid:[4026531836]
pid:[4026532222]
user:[4026531837]
uts:[4026531838]
uts:[4026532220]

2.2 查看某个docker 容器的namespaces

>sudo docker inspect  -f "{{.State.Pid}}" 34b48c1d3093  //34b48c1d3093是容器id
>10427    //查询容器对应在主机上的pid
> sudo ls -l /proc/10427/ns
lrwxrwxrwx 1 root root 0 Dec 11 16:21 ipc -> ipc:[4026533018]
lrwxrwxrwx 1 root root 0 Dec 11 16:21 mnt -> mnt:[4026533016]
lrwxrwxrwx 1 root root 0 Dec 11 16:21 net -> net:[4026531956]
lrwxrwxrwx 1 root root 0 Dec 11 16:21 pid -> pid:[4026533019]
lrwxrwxrwx 1 root root 0 Dec 11 16:21 user -> user:[4026531837]
lrwxrwxrwx 1 root root 0 Dec 11 16:21 uts -> uts:[4026533017]

  • 首先查找到容器id
  • 根据容器id查找容器对应的pid
  • 根据pid,查找 /proc/{pid}/ns路径下的命名空间

从结果看,一个容器对应6个命名空间,类型不重复,正好验证了我们之前的结论 “一个容器拥有一组命名空间,即Mount1、UTS1、IPC1、PID1、Network1、User1组合”。

2.3 进入命名空间命令nsenter

nsenter作用是查看某个命令空间内的信息。

nsenter的使用帮忙如下:

 Usage:
 nsenter [options] <program> [<argument>...]

Run a program with namespaces of other processes.

Options:
 -t, --target <pid>     target process to get namespaces from
 -m, --mount[=<file>]   enter mount namespace
 -u, --uts[=<file>]     enter UTS namespace (hostname etc)
 -i, --ipc[=<file>]     enter System V IPC namespace
 -n, --net[=<file>]     enter network namespace
 -p, --pid[=<file>]     enter pid namespace
 -U, --user[=<file>]    enter user namespace
 -S, --setuid <uid>     set uid in entered namespace
 -G, --setgid <gid>     set gid in entered namespace
      <span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span>--preserve-credentials do not touch uids or gids
 -r, --root[=<*dir*>]     set the root directory
 -w, --wd[=<*dir*>]       set the working directory
 -F, --no-fork          do not fork before exec'ing <program>
 -Z, --follow-context   set SELinux context according to --target PID

 -h, --help     display this help and exit
 -V, --version  output version information and exit

For more details see nsenter(1).

操作特定进程命名空间中的信息,容器就是一个命名空间

查看容器内的网卡信息:

❯ sudo nsenter -t 10427 -n ip addr
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1000
    link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
    inet 127.0.0.1/8 scope host lo
       valid_lft forever preferred_lft forever
66: eth0@if67: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP group default
    link/ether 02:42:ac:11:00:02 brd ff:ff:ff:ff:ff:ff link-netnsid 0
    inet 172.17.0.2/16 brd 172.17.255.255 scope global eth0
       valid_lft forever preferred_lft forever

也可以通过 nsenter -t 10427 -n bash 进入命名空间,单独执行ip addr命令


查看容器的Host信息(主机名)

❯ sudo nsenter -t 10427 -u hostname
d911aa5d1a1c   //hostname

等价于进入容器后,执行hostname命令

>docker exec -it 34b48c1d3093 sh    //进入容器
>/home/zenap # hostname
  d911aa5d1a1c   //hostname

你可能感兴趣的:(docker,k8s,paas,linux,namespace,docker,命名空间,nsenter)