ネットワーク名前空間からネットワーク名前空間を作成できないようです。 「エラー:ピアnetns参照が無効です。」という結果になります。
これはバグですか、それとも私が気付いていないような制限がありますか?
以下は、エラーのcmdトレースです。
# ip netns add foo1
# ip netns exec foo1 ip netns add foo2
# ip netns
Error: Peer netns reference is invalid.
Error: Peer netns reference is invalid.
foo2
foo1
# ip netns exec foo2 /bin/bash
setting the network namespace "foo2" failed: Invalid argument
TL; DR:奇妙なことに、これは実際にはnetwork名前空間の問題ではなく、mount名前空間の問題であり、予期されていることです。
すべての新しい「ip netns名前空間」を作成する必要があります(意味については後で参照)。つまり、すべてのip netns add ...
コマンドを、ip netns exec ...
で入力した「ip netns名前空間」内からではなく、最初の(ホスト)「ip netns名前空間」から実行します。 createしない限り、自由にswitchを自由に入れ替えて、ip netns exec ...
を使用してコマンドを入れ子にすることができます。
次のステップバイステップの例を使用した詳細な説明...
ip netns
はネットワーク名前空間に特化していますが、すべての機能を処理するために、(少なくとも、私が知っている)2つの理由でマウント名前空間と混ざる必要があります。
代替サービス/デーモン構成を管理するために/etc/netns/FOO/SOMESERVICE
を/etc/SOMESERVICE
にバインドをバインド
他のネットワーク名前空間でいくつかの(ネットワーク関連の)デーモンを簡単に実行するのに便利な機能ですが、これ以外にもまだ「ホスト」の一部です。 ULでの質問に対する私の回答をチェックできます: ip netns(iproute2)によるネームスペース管理 。以下の機能と同じ扱いが必要なため、これ以上は触れません。
階層内の新しいネットワーク名前空間のネットワークデバイスを公開するための/sys
の再マウント
これは必須の機能です。問題を明らかにする例:
「初期ホスト」から:
# ip link add dev dummy9 type dummy
# ip -br link show dummy9
dummy9 DOWN f6:f6:48:9c:12:b9 <BROADCAST,NOARP>
# ls -l /sys/class/net/dummy9
lrwxrwxrwx. 1 root root 0 Apr 4 22:09 /sys/class/net/dummy9 -> ../../devices/virtual/net/dummy9
下位ツール を使用して、他の(一時的な)ネットワーク名前空間に変更します。
# unshare --net ip -br link show dummy9
Device "dummy9" does not exist.
# unshare --net ls -l /sys/class/net/dummy9
lrwxrwxrwx. 1 root root 0 Apr 4 22:13 /sys/class/net/dummy9 -> ../../devices/virtual/net/dummy9
それが問題です。/sys
は、新しいネットワーク名前空間のインターフェイスではなく、初期のホストのインターフェイスを公開します。これは、ネットワーク名前空間と/sys
のマウントとの相互作用がある場所です。/sys
が新しいネットワーク名前空間からマウントされている場合、選択したディレクトリ階層(/sys/class/net
および/sys/devices/virtual/net
など)で新しいネットワークインターフェイスを公開するように切り替わります。これは動的ではなく、マウント時にのみ行われます。一部の高度なネットワーク設定は、そこに読み取りまたは書き込みを行うだけで簡単に利用できるため、提供する必要があり、その逆も当てはまります。新しいネットワーク環境で実行されている分離されたプロセスは、初期ホストのインターフェースを表示または変更できません。
したがって、ip netns exec FOO ...
(ip netns add FOO
は除く)は nsharing -mount名前空間によってこれを解決し、その内部に/sys/
を再マウントして、初期ホストのネットワーク名前空間を中断しないようにします。ただし、重要なのは、このマウント名前空間自体が一時的なものであることです。2つのip netns exec FOO ...
コマンドを個別に実行すると、同じマウント名前空間にはなりません。それらはそれぞれ独自のものを持っており、/sys
が同じネットワーク名前空間を指すように再マウントされています。
今までは問題ありません。これが発生したときは、2つのタイプの名前空間が関係しているため、これを「ip netns名前空間」と呼びます。これまでのところ:
用語1:
# ip netns add FOO
# ls -l /proc/$$/ns/{mnt,net}
lrwxrwxrwx. 1 root root 0 Apr 4 22:28 /proc/1712/ns/mnt -> mnt:[4026531840]
lrwxrwxrwx. 1 root root 0 Apr 4 22:28 /proc/1712/ns/net -> net:[4026531992]
# ip netns exec FOO bash
# ls -l /proc/$$/ns/{mnt,net}
lrwxrwxrwx. 1 root root 0 Apr 4 22:33 /proc/1864/ns/mnt -> mnt:[4026532618]
lrwxrwxrwx. 1 root root 0 Apr 4 22:33 /proc/1864/ns/net -> net:[4026532520]
用語2:
# ls -l /proc/$$/ns/{mnt,net}
lrwxrwxrwx. 1 root root 0 Apr 4 22:32 /proc/1761/ns/mnt -> mnt:[4026531840]
lrwxrwxrwx. 1 root root 0 Apr 4 22:32 /proc/1761/ns/net -> net:[4026531992]
# ip netns exec FOO bash
# ls -l /proc/$$/ns/{mnt,net}
lrwxrwxrwx. 1 root root 0 Apr 4 22:33 /proc/1866/ns/mnt -> mnt:[4026532821]
lrwxrwxrwx. 1 root root 0 Apr 4 22:33 /proc/1866/ns/net -> net:[4026532520]
Ip netns名前空間を変更した後、新しいネットワーク名前空間はterm1とterm2で同じであるが、新しいマウント名前空間は互いに(および初期ホストと)異なることに注意してください。 。
term1で新しいip netns名前空間を作成するとどうなりますか?どれどれ:
用語1:
# ip netns add BAR
# ip netns ls
BAR
FOO
用語2:
# ip netns ls
Error: Peer netns reference is invalid.
Error: Peer netns reference is invalid.
BAR
FOO
これは、プロセスなしで既存の名前空間BARが他の場合と同様にmounted(新しく作成された空のファイル)/var/run/netns/BAR
であるからです(もう一度、 前のリンク)を参照してください たとえば)。マウント名前空間は異なりますが、ルートディレクトリは同じです。つまり、初期ホストのルートです。したがって、もちろん、この新しく作成された空のファイル/var/run/netns/BAR
は、作成時にどこでも確認できます(初期、term1のマウントns、term2のマウントns)。
残念ながら、マウントはterm1のFOOのマウント名前空間で行われ、term1でのみ表示され、term2では表示されません。それ以外の場合は、マウントネームスペースが異なるためです。したがって、term1(のFOO ip netns名前空間)では、/var/run/netns/BAR
はnsfs
疑似ファイルシステムに属する疑似ファイルです。
用語1:
# stat -f -c %T /var/run/netns/BAR
nsfs
tmpfs
(実際の/run
マウントから)上の空のファイルです。
用語2:
# stat -f -c %T /var/run/netns/BAR
tmpfs
その他の端末:
$ stat -f -c %T /var/run/netns/BAR
tmpfs
現在の「ip netns名前空間」を終了しない限り、term1で引き続き表示されます。 term1からまだip netns名前空間を切り替える場合でも、新しい非共有の一時的なマウント名前空間は、すべてのマウントを含む以前のマウントのコピーであるため、問題ありません。
終了すると、そのマウントポイントは失われます(つまり、そのマウントポイントを使用しているプロセスまたはファイル記述子がない場合、BARの対応するネットワーク名前空間は、このマウントポイントによってのみ保持されていたため、表示されなくなります)。この後、ip netns ls
コマンドはどこにでも文句を言うでしょう。古くて役に立たないファイル/run/netns/BAR
を削除するだけで修正できます。
この段階的な説明の後、覚えておくべきことは、現在ip netns add
で入力されているネームスペース内にip netns exec
を持つcreate新しいネームスペースを使用してはならないということです。すべてを初期(ホスト)名前空間から作成する必要があります。その後、任意のip netns名前空間から自由に切り替えることができます。
もちろん、/var/run/netns/
(つまり、マウントポイント/run
)が(あいまいなままの)名前空間間で異なる場合、相互作用はなく、各ip netns
の呼び出しは他から隔離され、他の操作や相互作用は行われません。これは通常どこで起こりますか?フルコンテナでは、マウントとネットワークの両方の名前空間が分離され、最初から個別のリソースをポイントします。
[〜#〜] update [〜#〜]:コメントで質問されたように、この問題を「修復」する方法を確認しましたが、見つかりませんでした簡単な解決策。
最初に前提条件があります。上記のように、新しい "ip netns"名前空間BARがFOO内に作成され、FOOが残されると、BARへの唯一の参照が消えるため、BARも消えます。さらに何かが必要です。
実際には、 名前空間への参照 を保持する方法は3つあります。
ip netns
で使用されるメソッドです):プロセスなしで名前空間を保持できます。内部にネットワーク設定(インターフェース、ブリッジ、tcルール、ファイアウォールルールなど)のみを持つ名前空間を作成できます。1番目または3番目の方法を使用できます。動作するものを見つける前に失敗したさまざまな試みを次に示します...
前に言ったように、動作しません:
# ip netns add FOO
# ip netns exec FOO ip netns add BAR
first "ip netns"名前空間で一時的に実行しているプロセスをその一時的なmount名前空間部分に残すだけで、-newへの必要な参照を維持できます。 = "ip netns"名前空間のnetwork名前空間を作成し、後で(初期名前空間から)外部から再利用します。
どちらも機能しません:
# ip netns add FOO
# ip netns exec FOO sh -c 'ip netns add BAR; sleep 999 < /var/run/netns/BAR & echo $!'
28344
# strace -e trace=readlink,mount mount --bind /proc/6295/fd/0 /var/run/netns/BAR
readlink("/proc/6295/fd/0", "/run/netns/BAR", 4095) = 14
readlink("/var/run", "/run", 4095) = 4
mount("/run/netns/BAR", "/run/netns/BAR", 0x55c88c9cccb0, MS_BIND, NULL) = 0
+++ exited with 0 +++
# stat -f -c %T /run/netns/BAR
tmpfs
strace
で見られるように、mount
コマンドは、この使用例では必要ないときにシンボリックリンクをたどりました(注:マウントはまだスリーププロセスにリンクされているため、アンマウントするために強制終了する必要があります)それ)。
これ(sleep
の入力mount名前空間にアクセスして、BARのマウントされたnetwork隠された名前空間にアクセスする)は機能しますが、sleep
の継続的な存在に依存していますまたは継続使用のためのプロセス:
# ip netns add FOO
# ip netns exec FOO sh -c 'ip netns add BAR; ip -n BAR link add dummy8 type dummy; sleep 999 & echo $!'
12916
# nsenter --target=12916 --mount ip -n -brief BAR link show
lo DOWN 00:00:00:00:00:00 <LOOPBACK>
dummy8 DOWN 8e:ce:b3:d1:9c:bb <BROADCAST,NOARP>
奇妙なことに、これは(名前空間のマウントショートカット /proc/pid/root/
を使用)が機能しない(理由がわからない):
# stat -f -c %T /proc/12916/root/var/run/netns/BAR
tmpfs
最後に何がうまくいくでしょう:
# ip netns add FOO
# ip netns exec FOO sh -c 'ip netns add BAR; ip -n BAR link add dummy8 type dummy; ip netns exec BAR sh -c '\''sleep 999 & echo $!'\'
14124
# mount --bind /proc/14124/ns/net /var/run/netns/BAR
# ip -n BAR -brief link show
lo DOWN 00:00:00:00:00:00 <LOOPBACK>
dummy8 DOWN 3a:48:65:20:68:c1 <BROADCAST,NOARP>
したがって、このようなものを最後に使用できます。 sleepコマンドが終了する前の直後に削除しようとすると、競合状態が発生する可能性があります。
# ip netns add FOO
# mount --bind /proc/$(ip netns exec FOO sh -c 'ip netns add BAR; ip netns exec BAR bash -c '\''sleep 5 </dev/null >/dev/null 2>&1 & echo $!; disown'\')/ns/net /var/run/netns/BAR
このような構成をどのように使用できますか?ネストされた「ip netns」の問題が発生する前の元の問題が示されていないため、私にはわかりません。 「ネストされたネットワーク名前空間」を作成することなく、より簡単なソリューションを利用できる場合があります。