需要

失常状况下这种操作比拟反设计,须要审慎应用
有些时候咱们应用docker的时候会须要用到宿主机命令操作,比方

  • 执行 netplan apply失效机器网络配置
  • 查看宿主机网络信息应用ifconfig或者 ip addr
  • 从容器收回命令重启宿主机

具体实现

最简略的实现
应用docker运行一个ubuntu容器
进入容器之后执行nsenter命令查看宿主机网络配置信息

$ sudo docker run -it --pid=host --privileged=true ubuntu /bin/bash# 进入容器外部之后执行/# nsenter -a -t 1 sh -c "ip addr"

实现原理

docker run 参数

--pid=host

  • 应用宿主机命名空间,不便容器获取到宿主机所有过程信息
  • 把宿主机的/proc文件夹挂载进入容器的/proc门路,其中/proc/1作为nsentertarget,作为容器向宿主机发送命令的要害局部

--privileged=true

  • 使得docker容器有root权限执行宿主机命令,确保从容器执行命令的时候不会产生权限有余谬误

nsenter命令

nsenter命令是一个能够在指定过程的命令空间下运行指定程序的命令

$ nsenter --help用法: nsenter [选项] [<程序> [<参数>...]]以其余程序的名字空间运行某个程序。选项: -a, --all              enter all namespaces -t, --target <pid>     要获取名字空间的指标过程 -m, --mount[=<文件>]   进入 mount 名字空间 -u, --uts[=<文件>]     进入 UTS 名字空间(主机名等) -i, --ipc[=<文件>]     进入 System V IPC 名字空间 -n, --net[=<文件>]     进入网络名字空间 -p, --pid[=<文件>]     进入 pid 名字空间 -C, --cgroup[=<文件>]  进入 cgroup 名字空间 -U, --user[=<文件>]    进入用户名字空间 -S, --setuid <uid>     设置进入空间中的 uid -G, --setgid <gid>     设置进入名字空间中的 gid     --preserve-credentials 不干预 uid 或 gid -r, --root[=<目录>]     设置根目录 -w, --wd[=<dir>]       设置工作目录 -F, --no-fork          执行 <程序> 前不 fork -Z, --follow-context  依据 --target PID 设置 SELinux 环境 -h, --help             display this help -V, --version          display version更多信息请参阅 nsenter(1)。

具体执行

$ nsenter -a -t 1 sh -c "ip addr"
  • -a示意进入宿主机的所有命名空间
  • -t 1示意获取/proc/1过程,就是pid=1的过程,这个过程是docker应用--pid=host参数挂载进入容器外部的宿主机过程
  • sh -c "ip addr"就示意发送给宿主机的命令是ip addr

理论应用过程中如果呈现宿主机和容器命名空间不统一问题,次要产生起因是宿主机内核版本和容器
所默认的加载内核版本不统一

比方cgroup是在Linux4.6版本退出的,如果应用Ubuntu20或者其余python3.10等比拟新的镜像启动容器的时候,当nsenter应用参数-a,容器会加载所有命名空间,然而cgroup命名空间在旧版本的零碎外面因为内核版本比拟旧,所以该命名空间是没有的,最终nsenter命令就会报错

须要依照宿主机有的命名空间来调整nsenter参数,能够调整如下

$ nsenter -m -u -i -n -p  -t 1 sh -c "ip addr"

比方能够把-a参数替换成-m -u -i -n -p,明确指定进入mount, UTS,System V IPC,网络,pid命名空间
这几个命名空间蕴含了绝大多数的空间环境,linux的大部分命令都能够失常执行

命名空间阐明

namespaceLinux中一些过程的属性的作用域,应用命名空间,能够隔离不同的过程

Linux在一直的增加命名空间,目前有

  • mount:挂载命名空间,使过程有一个独立的挂载文件系统,始于Linux 2.4.19
  • ipcipc命名空间,使过程有一个独立的ipc,包含音讯队列,共享内存和信号量,始于Linux 2.6.19
  • utsuts命名空间,使过程有一个独立的hostnamedomainname,始于Linux 2.6.19
  • netnetwork命令空间,使过程有一个独立的网络栈,始于Linux 2.6.24
  • pidpid命名空间,使过程有一个独立的pid空间,始于Linux 2.6.24
  • useruser命名空间,是过程有一个独立的user空间,始于Linux 2.6.23,完结于Linux 3.8
  • cgroupcgroup命名空间,使过程有一个独立的cgroup控制组,始于Linux 4.6

参考浏览

  • nsenter命令简介
  • Linux manual page
  • docker官网文档