nsenter 工具的使用


一、背景

對於運行在后台的docker容器,我們經常需要做的事情是進入到容器中,docker為我們提供了docker exec 、docker attach 命令,並且還提供了nsenter工具,外部工具供我們使用。

docker attach存在的問題是:當多個窗口同時attach到同一個容器時,所有的窗口都會同步的顯示,假如其中的一個窗口發生阻塞時,其它的窗口也會阻塞,docker attach命令可以說是最不方便的進入后台docker容器的方法。

docker exec命令是在docker 1.3之后增加的一個比docker attach命令更加方便的命令。

和docker exec差不多方便的命令是nsenter工具。

nsenter 是一個可以用來進入到目標程序說在 namespace 中運行命令的工具,一般可以用於在容器外 debug 容器中運行的程序。

二、安裝

1、源碼安裝 nsenter

$ cd /tmp;
$ curl https://www.kernel.org/pub/linux/utils/util-linux/v2.24/util-linux-2.24.tar.gz | tar -zxf-; cd util-linux-2.24;
$ ./configure  --without-ncurses
$ make nsenter && sudo cp nsenter /usr/local/bin 

2、yum安裝

util-linux 是一個開放源碼的軟件包,是一個對任何 Linux 系統的基本工具套件。含有一些標准 Unix 工具,如 login。
util-linux 軟件包包含許多工具。其中比較重要的是加載、卸載、格式化、分區和管理硬盤驅動器,打開 tty 端口和得到內核消息。
sudo yum install -y util-linux

三、nsenter使用

1、查看幫助

$ nsenter --help

用法:
 nsenter [options] <program> [<argument>...]
Run a program with namespaces of other processes.

選項:
 -t, --target <pid>     要獲取名字空間的目標進程
 -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
     --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          執行 <程序> 前不 fork
 -Z, --follow-context   set SELinux context according to --target PID

 -h, --help     顯示此幫助並退出
 -V, --version  輸出版本信息並退出

更多信息請參閱 nsenter(1)。
$ nsenter  -V
nsenter,來自 util-linux 2.23.2

在使用nsenter命令之前需要獲取到docker容器的進程,然后再使用nsenter工具進去到docker容器中
每一個容器都有.State.Pid,所以這個命令除了容器的id需要我們根據docker ps -a去查找,其他的全部為固定的格式

$ docker inspect -f {{.State.Pid}} 容器名或者容器id  

如下:
$ docker inspect -f {{.State.Pid}}  7b7af641a02d
20560
$ docker inspect -f {{.State.Pid}}  consul_client
20560 

輸入該命令便進入到容器中

$ nsenter --target 上面查到的進程id --mount --uts --ipc --net --pid  

解釋nsenter指令中進程id之后的參數的含義: 
* –mount參數是進去到mount namespace中  (文件系統)
* –uts參數是進入到uts namespace中  (主機名與域名)
* –ipc參數是進入到System V IPC namaspace中  (信號量、消息隊列和共享內容)
* –net參數是進入到network namespace中   (網絡設備、網絡棧、端口)
* –pid參數是進入到pid namespace中    (進程編號)
* –user參數是進入到user namespace中 (用戶和用戶組)

docker隔離應用應用涉及到的六大名稱空間

1、pid 命名空間(進程ID)

不同用戶的進程就是通過 pid 命名空間隔離開的,且不同命名空間中可以有相同 pid。所有的 LXC 進程在 Docker 中的父進程為 Docker 進程,每個 LXC 進程具有不同的命名空間。同時由於允許嵌套,因此可以很方便的實現嵌套的 Docker 容器。

2、net 命名空間(網絡)

有了 pid 命名空間,每個命名空間中的 pid 能夠相互隔離,但是網絡端口還是共享 host 的端口。網絡隔離是通過 net 命名空間實現的, 每個 net 命名空間有獨立的 網絡設備,IP 地址,路由表,/proc/net 目錄。這樣每個容器的網絡就能隔離開來。Docker 默認采用 veth 的方式,將容器中的虛擬網卡同 host 上的一 個Docker 網橋 docker0 連接在一起。

3、ipc 命名空間(進程間通信)

容器中進程交互還是采用了 Linux 常見的進程間交互方法(interprocess communication - IPC), 包括信號量、消息隊列和共享內存等。然而同 VM 不同的是,容器的進程間交互實際上還是 host 上具有相同 pid 命名空間中的進程間交互,因此需要在 IPC 資源申請時加入命名空間信息,每個 IPC 資源有一個唯一的 32 位 id。

4、mnt 命名空間(掛載文件系統)

類似 chroot,將一個進程放到一個特定的目錄執行。mnt 命名空間允許不同命名空間的進程看到的文件結構不同,這樣每個命名空間 中的進程所看到的文件目錄就被隔離開了。同 chroot 不同,每個命名空間中的容器在 /proc/mounts 的信息只包含所在命名空間的 mount point。

5、UTS 命名空間(主機名/域名)

UTS("UNIX Time-sharing System") 命名空間允許每個容器擁有獨立的 hostname 和 domain name, 使其在網絡上可以被視作一個獨立的節點而非 主機上的一個進程。

6、user 命名空間(用戶)

每個容器可以有不同的用戶和組 id, 也就是說可以在容器內用容器內部的用戶執行程序而非主機上的用戶。

查看docker的連接

由於使用DOCKER的時候,ESTABLISHED連接不會出現在netstat中,在運行中的docker容器中列出打開的套接字的方法 ,查找docker的進程號 :

$ docker inspect -f '{{.State.Pid}}' <containerid>   
$ docker inspect -f '{{.State.Pid}}' 1746bf8c10aa  
1829 

查看連接: 

$ sudo nsenter -t <pid> -n netstat | grep ESTABLISHED  

示例:
$ nsenter -t 1829 -n netstat |grep ESTABLISHED  
tcp        0      0 localhost:60353         localhost:epmd          ESTABLISHED
tcp        0      0 localhost:epmd          localhost:60353         ESTABLISHED
tcp        0      0 localhost.localdo:15672 192.168.56.1:59679      ESTABLISHED
tcp6       0      0 172.17.0.2:amqp         192.168.56.1:59898      ESTABLISHED
tcp6      21      0 172.17.0.2:amqp         192.168.56.1:59571      ESTABLISHED

結合 docker 使用用於在某個容器的 namespace 中運行指定程序的常用命令是:

PID=$(docker inspect --format {{.State.Pid}} <container_name_or_ID>)

nsenter -m -u -i -n -p -t $PID <command>

例子:

$ docker run --rm --name test -d busybox  sleep 10000
8115009baccc53a2a5f6dfff642e0d8ab1dfb95dde473d14fb9a06ce4e89364c

$ docker ps |grep busybox
8115009baccc        busybox             "sleep 10000"            9 seconds ago       Up 8 seconds                            test

$ PID=$(docker inspect --format {{.State.Pid}} 8115009baccc)

$ nsenter -m -u -i -n -p -t $PID ps aux
PID   USER     TIME  COMMAND
    1 root      0:00 sleep 10000
    7 root      0:00 ps aux

$ nsenter -m -u -i -n -p -t $PID hostname
8115009bacc

創建docker-enter並置於$PATH下(將shell腳本放到環境變量中,任意路徑可執行)

腳本放置:

cd ~
#創建bin文件夾,也可以按自己喜好在指定位置下創建目錄(目錄名也可以自定義)
mkdir bin

vim ~/.bashrc
#移到最后一行,添加以下命令,其中:表示路徑分隔符,~/bin就是我們剛才創建的文件路徑
export PATH=$PATH:~/bin

source ~/.bashrc

在~/bin 目錄下創建自己的腳本

chmod +x  xxx.sh

腳本:vim docker-enter

#!/bin/bash

if [ -e $(dirname "$0")/nsenter ]; then
  # with boot2docker, nsenter is not in the PATH but it is in the same folder
  NSENTER=$(dirname "$0")/nsenter
else
  NSENTER=nsenter
fi

if [ -z "$1" ]; then
  echo "Usage: `basename "$0"` CONTAINER [COMMAND [ARG]...]"
  echo ""
  echo "Enters the Docker CONTAINER and executes the specified COMMAND."
  echo "If COMMAND is not specified, runs an interactive shell in CONTAINER."
else
  PID=$(docker inspect --format "{{.State.Pid}}" "$1")
  if [ -z "$PID" ]; then
    exit 1
  fi
  shift

  OPTS="--target $PID --mount --uts --ipc --net --pid /bin/bash"

  if [ -z "$1" ]; then
    # No command given.
    # Use su to clear all host environment variables except for TERM,
    # initialize the environment variables HOME, SHELL, USER, LOGNAME, PATH,
    # and start a login shell.
#"$NSENTER" $OPTS su - root
"$NSENTER" $OPTS
  else
    # Use env to clear all host environment variables.
    "$NSENTER" $OPTS env --ignore-environment -- "$@"
  fi
fi

常見問題

$ sudo nsenter -t 31340 -n netstat | grep ESTABLISHED
nsenter: failed to execute netstat: 沒有那個文件或目錄

 

 

https://www.cnblogs.com/rwxwsblog/p/5430902.html    不錯的文章

 

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM