unshareコマンドの詳細な説明と事例

unshareコマンドの詳細な説明

1.名前

unshare - run program with some namespaces unshared from parent(使用与父程序不共享的名称空间运行程序)

2.まとめ

unshare [options] program [arguments]

3.説明

示された名前空間を親プロセスから共有解除してから、指定されたプログラムを実行します。共有されない名前空間はオプションで示されます。共有できない名前空間は(指定された名前空間を親プロセスから共有解除してから、指定されたプログラムを実行します。スペースはオプションで示されます。共有できない名前空間には次のものがあります)

合計6つの非共有ネームスペースを非共有に設定できます。これは次のとおりです。

mount namespace

UTS namespace

IPC namespace

network namespace

pid namespace

user namespace

4.オプション

次のオプションの合計があります。

(1)-i, --ipc

 unshare the IPC namespace.

(2)-m, --mount

 Unshare the mount namespace.

(3)-n, --net

 Unshare the network namespace.

(4) -p, --pid

Unshare the pid namespace.  See also the --fork and --mount-proc options.

(5)-u, --uts

 Unshare the UTS namespace.

(6) -U, --user

Unshare the user namespace.

(7)-f, --fork

Fork the specified program as a child process of unshare rather than running it directly.  This is useful when creating a new pid namespace.

(8)--mount-proc[=mountpoint]

Just  before running the program, mount the proc filesystem at mountpoint (default is /proc).  This is useful when creating a new pid namespace.  It also implies creating a new mount names‐pace since the /proc mount would otherwise mess up existing programs on the system.  The new proc filesystem is explicitly mounted as private (by MS_PRIVATE|MS_REC).

(9)-r, --map-root-user

Run the program only after the current effective user and group IDs have been mapped to the superuser UID and GID in the newly created user namespace.  This  makes  it  possible  to  conve‐niently  gain  capabilities  needed  to  manage various aspects of the newly created namespaces (such as configuring interfaces in the network namespace or mounting filesystems in the mount namespace) even when run unprivileged. As a mere convenience feature, it does not support more sophisticated use cases, such as mapping multiple ranges  of  UIDs  and  GIDs.  This  option  implies --setgroups=deny.

(10) --propagation private|shared|slave|unchanged

Recursively  sets mount propagation flag in the new mount namespace. The default is to set the propagation to private, this feature is possible to disable by unchanged argument. The options        is silently ignored when mount namespace (--mount) is not requested.

(11)--setgroups allow|deny

Allow or deny setgroups(2) syscall in user namespaces.

setgroups(2) is only callable with CAP_SETGID and CAP_SETGID in a user namespace (since Linux 3.19) does not give you permission to call setgroups(2) until after GID map has been  set.  The GID map is writable by root when setgroups(2) is enabled and GID map becomes writable by unprivileged processes when setgroups(2) is permanently disabled.

(12) -V, --version

Display version information and exit.

(13)-h, --help

Display help text and exit.

5.例

# unshare --fork --pid --mount-proc readlink /proc/self

1

Establish a PID namespace, ensure we're PID 1 in it against newly mounted procfs instance.

(建立一个PID命名空间,确保我们在新安装的procfs实例中是PID 1。)

 

$ unshare --map-root-user --user sh -c whoami

root

Establish a user namespace as an unprivileged user with a root user within it.

(将用户命名空间建立为非特权用户,其中包含根用户。)

6.さまざまな名前空間の役割は何ですか?

(1)マウント名前空間

Mount Namespaceは、Linuxカーネルによって実装された最初の名前空間であり、カーネルのバージョン2.4.19以降に追加されました。さまざまなプロセスまたはプロセスグループから見たマウントポイントを分離するために使用できます。素人の言葉で言えば、さまざまなプロセスでさまざまなマウントディレクトリを確認することができます。マウント名前空間を使用すると、コンテナー内に表示できるのは独自のマウント情報のみであり、コンテナー内のマウント操作はホストのマウントディレクトリに影響を与えないことがわかります。

例を使用して、マウント名前空間を示しましょう。コマンドラインツールunshareを使用します。unshareはutil-linuxツールキットのツールです。CentOS7はデフォルトでこのツールを統合しています。unshareコマンドを使用して、さまざまなタイプの名前空間を作成してアクセスできます。

まず、次のコマンドを使用してbashプロセスを作成し、新しいマウント名前空間を作成します。

unshare --mount --fork /bin/bash

上記のコマンドを実行した後、ホスト上に新しいマウント名前空間を作成し、新しく作成したマウント名前空間を現在のコマンドラインウィンドウに追加しました。例を使用して、独立したマウント名前空間にマウントディレクトリを作成しても、ホストのマウントディレクトリに影響がないことを確認します。

上記のコマンドを実行した後、ホスト上に新しいマウント名前空間を作成し、新しく作成したマウント名前空間を現在のコマンドラインウィンドウに追加しました。例を使用して、独立したマウント名前空間にマウントディレクトリを作成しても、ホストのマウントディレクトリに影響がないことを確認します。

まず、/ tmpディレクトリの下にディレクトリを作成します。

[root@centos7 centos]# mkdir /tmp/tmpfs

ディレクトリを作成したら、mountコマンドを使用してtmpfsタイプのディレクトリをマウントします。コマンドは次のとおりです。

[root@centos7 centos]# mount -t tmpfs -o size=20m tmpfs /tmp/tmpfs

次に、dfコマンドを使用して、マウントされたディレクトリ情報を表示します。

[root@centos7 centos]# df -h

Filesystem   Size Used Avail Use% Mounted on

/dev/vda1    500G 1.4G 499G  1% /

devtmpfs     16G   0  16G  0% /dev

tmpfs      16G   0  16G  0% /dev/shm

tmpfs      16G   0  16G  0% /sys/fs/cgroup

tmpfs      16G  57M  16G  1% /run

tmpfs      3.2G   0 3.2G  0% /run/user/1000

tmpfs      20M   0  20M  0% /tmp/tmpfs

/ tmp / tmpfsディレクトリが正しくマウントされていることがわかります。このディレクトリがホストにマウントされていないことを確認するために、新しいコマンドラインウィンドウを開き、dfコマンドを実行してホストのマウント情報を表示します。

[centos@centos7 ~]$ df -h

Filesystem   Size Used Avail Use% Mounted on

devtmpfs     16G   0  16G  0% /dev

tmpfs      16G   0  16G  0% /dev/shm

tmpfs      16G  57M  16G  1% /run

tmpfs      16G   0  16G  0% /sys/fs/cgroup

/dev/vda1    500G 1.4G 499G  1% /

tmpfs      3.2G   0 3.2G  0% /run/user/1000

上記の出力から、/ tmp / tmpfsがホストにマウントされていないことがわかります。独立したマウント名前空間でのマウント操作は、ホストに影響を与えないことがわかります。

アイデアをさらに検証するために、現在のコマンドラインウィンドウで現在のプロセスの名前空間情報を引き続き確認します。コマンドは次のとおりです。

[root@centos7 centos]# ls -l /proc/self/ns/

total 0

lrwxrwxrwx. 1 root root 0 Sep 4 08:20 ipc -> ipc:[4026531839]

lrwxrwxrwx. 1 root root 0 Sep 4 08:20 mnt -> mnt:[4026532239]

lrwxrwxrwx. 1 root root 0 Sep 4 08:20 net -> net:[4026531956]

lrwxrwxrwx. 1 root root 0 Sep 4 08:20 pid -> pid:[4026531836]

lrwxrwxrwx. 1 root root 0 Sep 4 08:20 user -> user:[4026531837]

lrwxrwxrwx. 1 root root 0 Sep 4 08:20 uts -> uts:[4026531838]

次に、新しいコマンドラインウィンドウを開き、同じコマンドを使用してホストの名前空間情報を確認します。

[centos@centos7 ~]$ ls -l /proc/self/ns/

total 0

lrwxrwxrwx. 1 centos centos 0 Sep 4 08:20 ipc -> ipc:[4026531839]

lrwxrwxrwx. 1 centos centos 0 Sep 4 08:20 mnt -> mnt:[4026531840]

lrwxrwxrwx. 1 centos centos 0 Sep 4 08:20 net -> net:[4026531956]

lrwxrwxrwx. 1 centos centos 0 Sep 4 08:20 pid -> pid:[4026531836]

lrwxrwxrwx. 1 centos centos 0 Sep 4 08:20 user -> user:[4026531837]

lrwxrwxrwx. 1 centos centos 0 Sep 4 08:20 uts -> uts:[4026531838]

2つのコマンドの出力結果を比較すると、マウント名前空間のID値を除いて、他の名前空間のID値が同じであることがわかります。

上記の結果から、unshareコマンドを使用すると、新しいマウント名前空間を作成でき、新しく作成されたマウント名前空間のマウントは外部から完全に分離されていると結論付けることができます。

(2)PID名前空間

PID名前空間の機能は、プロセスを分離することです。異なるPID名前空間では、プロセスは同じPID番号を持つことができます。PID名前空間を使用すると、各コンテナのメインプロセスがプロセス番号1であるのに対し、コンテナ内のプロセスはホスト上で異なるPIDを持っていることがわかります。たとえば、ホスト上のプロセスのPIDは122であり、PID名前空間を使用して、プロセスがコンテナー内の1のPIDを認識していることを認識できます。

以下では、例を使用してPID名前空間の役割を示します。まず、次のコマンドを使用してbashプロセスを作成し、新しいPID名前空間を作成します。

unshare --fork --pid --mount-proc /bin/bash

上記のコマンドを実行した後、ホスト上に新しいPID名前空間を作成し、新しく作成したPID名前空間を現在のコマンドラインウィンドウに追加しました。現在のコマンドラインウィンドウでpsauxコマンドを使用して、プロセス情報を表示します。

[root@centos7 centos]# ps aux

USER    PID %CPU %MEM  VSZ  RSS TTY   STAT START  TIME COMMAND

root     1 0.0 0.0 115544 2004 pts/0  S  10:57  0:00 bash

root    10 0.0 0.0 155444 1764 pts/0  R+  10:59  0:00 ps aux

上記のコマンドの出力から、bashが現在の名前空間でNo. 1のプロセスであり、ホスト上の他のプロセス情報を確認できないことがわかります。

(3)UTS名前空間

UTS名前空間は、主にホスト名を分離するために使用され、各UTS名前空間が独立したホスト名を持つことを可能にします。たとえば、ホスト名はdockerです。UTS名前空間を使用すると、コンテナ内のホスト名をladoudockerまたはその他のカスタムホスト名として実現できます。

同様に、例を使用してUTS名前空間の役割を確認します。最初に、unshareコマンドを使用してUTS名前空間を作成します。

unshare --fork --uts /bin/bash

UTS名前空間が作成された後、現在のコマンドラインウィンドウはすでに独立したUTS名前空間にあります。次に、hostnameコマンド(ホスト名を使用してホスト名を表示できます)を使用して、ホスト名を設定します。

 hostname -b lagoudocker

次に、ホスト名をもう一度確認します。

[root@centos7 centos]# hostname

lagoudocker

上記のコマンドの出力から、現在のUTS名前空間のホスト名がlagudockerに変更されていることがわかります。次に、新しいコマンドラインウィンドウを開き、同じコマンドを使用してホストのホスト名を確認します。

[centos@centos7 ~]$ hostname

centos7

ホストの名前はまだcentos7であり、変更されていないことがわかります。このことから、UTS名前空間を使用してホスト名を分離できることを確認できます。

(4)IPC名前空間

IPC名前空間は、主にプロセス間通信を分離するために使用されます。たとえば、PID名前空間とIPC名前空間を一緒に使用して、同じIPC名前空間内のプロセスは相互に通信できますが、IPC名前空間が異なるプロセスは通信できないことを認識できます。

同様に、例を使用してIPC名前空間の役割を確認します。最初に、unshareコマンドを使用してIPC名前空間を作成します。

unshare --fork --ipc /bin/bash

次に、2つのコマンドを使用してIPC名前空間を確認する必要があります。

ipcs -qコマンド:システム間の通信キューのリストを表示するために使用されます。

ipcmk -Qコマンド:システム間の通信キューを作成するために使用されます。

まず、ipcs -qコマンドを使用して、現在のIPC名前空間の下にあるシステム通信キューのリストを表示します。

[centos@centos7 ~]$ ipcs -q

------ Message Queues --------

key    msqid   owner   perms   used-bytes  messages

上記から、現在システム通信キューがないことがわかります。次に、ipcmk-Qコマンドを使用してシステム通信キューを作成します。

[root@centos7 centos]# ipcmk -Q

Message queue id: 0

ipcs -qコマンドを再度使用して、現在のIPC名前空間の下にあるシステム通信キューのリストを表示します。

[root@centos7 centos]# ipcs -q

------ Message Queues --------

key    msqid   owner   perms   used-bytes  messages

0x73682a32 0     root    644    0      0

システム通信キューが正常に作成されたことがわかります。次に、新しいコマンドラインウィンドウを開き、ipcs -qコマンドを使用して、ホストのシステム通信キューを確認します。

[centos@centos7 ~]$ ipcs -q

------ Message Queues --------

key    msqid   owner   perms   used-bytes  messages

上記の実験を通じて、別のIPC名前空間で作成されたシステム通信キューがホスト上に表示されないことがわかります。つまり、IPC名前空間は、システム通信キューの分離を実現します。

(5)ユーザー名前空間

ユーザー名前空間は、主にユーザーとユーザーグループを分離するために使用されます。典型的なアプリケーションシナリオは、ホスト上で非rootユーザーとして実行されているプロセスを、別のユーザー名前空間のrootユーザーにマップできることです。ユーザー名前空間を使用すると、プロセスがコンテナー内のroot権限を持っていることがわかりますが、それはホスト上の通常のユーザーにすぎません。

User Namesapceは、root権限なしで作成できます。以下では、通常のユーザーとしてユーザー名前空間を作成します。コマンドは次のとおりです。

[centos@centos7 ~]$ unshare --user -r /bin/bash

[root@centos7 ~]#

CentOS7は、デフォルトでユーザー名前空間の作成を0に許可します。上記のコマンドの実行が失敗した場合(unshareコマンドによって返されるエラーはunshare:unshare failed:無効な引数)、次のコマンドを使用しての数を変更する必要があります。システムで作成できるユーザー名前空間コマンドは次のとおりです:echo 65535> / proc / sys / user / max_user_namespaces次に、ユーザー名前空間の作成を再試行します。

次に、idコマンドを実行して、現在のユーザー情報を確認します。

[root@centos7 ~]# id

uid=0(root) gid=0(root) groups=0(root),65534(nfsnobody) context=unconfined_u:unconfined_r:unconfined_t:s0-s0:c0.c1023

上記の出力から、新しいユーザー名前空間ですでにrootユーザーであることがわかります。以下では、ホストのrootユーザーのみが実行できるrebootコマンドを使用して確認し、現在のコマンドラインウィンドウでrebootコマンドを実行します。

[root@centos7 ~]# reboot

Failed to open /dev/initctl: Permission denied

Failed to talk to init daemon.

ご覧のとおり、私たちは新しく作成されたユーザー名前空間のrootユーザーですが、再起動コマンドを実行する権限がありません。これは、分離されたユーザー名前空間では、ホストのルート権限を取得できないことを示しています。つまり、ユーザー名前空間はユーザーとユーザーグループの分離を実現します。

(6)ネット名前空間

ネット名前空間は、ネットワークデバイス、IPアドレス、ポートなどの情報を分離するために使用されます。ネット名前空間を使用すると、各プロセスが独自の独立したIPアドレス、ポート、およびネットワークカード情報を持つことができます。たとえば、ホストIPアドレスは172.16.4.1であり、コンテナ内で独立したIPアドレスを192.168.1.1に設定できます。

また、検証例を使用します。最初にip aコマンドを使用して、ホスト上のネットワーク情報を確認します。

$ ip a

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

  inet6 ::1/128 scope host

​    valid_lft forever preferred_lft forever

2: eth0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UP group default qlen 1000

  link/ether 02:11:b0:14:01:0c brd ff:ff:ff:ff:ff:ff

  inet 172.20.1.11/24 brd 172.20.1.255 scope global dynamic eth0

​    valid_lft 86063337sec preferred_lft 86063337sec

  inet6 fe80::11:b0ff:fe14:10c/64 scope link

​    valid_lft forever preferred_lft forever

3: docker0: <NO-CARRIER,BROADCAST,MULTICAST,UP> mtu 1500 qdisc noqueue state DOWN group default

  link/ether 02:42:82:8d:a0:df brd ff:ff:ff:ff:ff:ff

  inet 172.17.0.1/16 scope global docker0

​    valid_lft forever preferred_lft forever

  inet6 fe80::42:82ff:fe8d:a0df/64 scope link

​    valid_lft forever preferred_lft forever

次に、次のコマンドを使用してネット名前空間を作成します。

 unshare --net --fork /bin/bash

同様に、ipaコマンドを使用してネットワーク情報を確認します。

[root@centos7 centos]# ip a

1: lo: <LOOPBACK> mtu 65536 qdisc noop state DOWN group default qlen 1000

link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00

ご覧のとおり、ホストにはlo、eth0、docker0などのネットワークデバイスがあり、新しく作成されたネット名前空間のネットワークデバイスはホストのネットワークデバイスとは異なります。

おすすめ

転載: blog.csdn.net/qq_34939308/article/details/114115443