.NETを使用して複数のネットワーク名前空間を作成しましたip netns add ns1
。ip netns add ns2
ネットワーク名前空間内でネットワークインターフェイスを起動/停止しようとすると、ifup
インターフェイスifdown
の状態が正しくありません。
$ ifup lo
ifup: interface lo already configured
これは /run/network/ が状態が保存される場所でありifup
、ifdown
上記のように作成されるとデフォルトネットワークネームスペースと追加ネットワークネームスペースとの間で共有されるからだと思います。その理由は、network 名前空間内に veth インターフェイスを作成すると、そのエントリが /run/network のメインスペースに表示されるためです。この質問はlo
インターフェースにも当てはまります。
Ubuntu-12-LTSと2020-02-13-raspbian-buster-liteでも同じ問題が発生します。しばらく前に同様の症状があり、原因を調査せずに処理していたCentOS-7.4
記憶がどんどん残っています。
(Raspbianで)デモンストレーションするために、各ネットワーク名前空間内にブリッジを作成し、ifup / ifdownし、デフォルトのスペースで/ run / network /の内容を確認しました。
設定
$ echo 'iface br2 inet manual' > /etc/network/interfaces.d/br2
$ ip netns add ns1
$ ip netns add ns2
$ ip netns exec ns1 ip link add br2 type bridge
$ ip netns exec ns2 ip link add br2 type bridge
確認br2
ステータスが存在しません。
$ cat /run/network/ifstate.br2
cat: /run/network/ifstate.br2: No such file or directory
いいですね。どの名前空間でも編集されてbr2
いません。最初の名前空間でインターフェイスを開く/閉じる/開くifup
ifdown
$ ip netns exec ns1 ifup br2
$ cat /run/network/ifstate.br2
br2
$ ip netns exec ns1 ifdown br2
$ cat /run/network/ifstate.br2
$ ip netns exec ns1 ifup br2
$ cat /run/network/ifstate.br2
br2
いいですね。 2番目の名前空間で同じup / down / upを実行すると、エラーが発生します。
$ ip netns exec ns2 ifup br2
ifup: interface br2 already configured
$ cat /run/network/ifstate.br2
br2
それが問題だ! 2番目の名前空間を介してインターフェイスを停止します(最初の名前空間を介して起動しました)。
$ ip netns exec ns2 ifdown br2
$ cat /run/network/ifstate.br2
これで最初の名前空間に戻ります。
$ ip netns exec ns1 ifdown br2
ifdown: interface br2 not configured
$ cat /run/network/ifstate.br2
上記と同様の問題で、2 番目のネームスペースではインターフェイス wad が停止しましたが、1 番目のネームスペースではダウンしていることが報告されました。
残念ながらこれは機能するので、lo
単に各名前空間内で一意の名前を使用するだけではこれを避けることはできません。この問題を解決するには、「上/下/上」サイクルインターフェイスを引き続き使用する必要があります。これを行うよりクリーンな方法があったらと思います。
マイユースケースと目標:上記のテストに似た複数の同じ名前空間を作成し、システムインスタンス化されたサービス単位でラップしてそのインターフェイスを起動しました(問題を解決するには、上/下/上に移動する必要がありました)。私はip netns exec nsX prog args
通常、異なるシステムサービスを介して各名前空間内でプログラムを異なる時間に開始します。しばらくすると、一部の名前空間を解体し、この作業を慎重に行う必要があります。ifdown
仕事のクリーンアップ中に自分の役割を正しく実行するには、このツールが必要です。複数のveth
インターフェイス、ブリッジ、接続、およびiptables
設定を含むネットワーキングは単純ではないので、何かがうまく機能し、他の名前空間の状態によって混同されないことをsysctl
本当に望んでいます。たとえば、インターフェイスを削除します。もちろん、回避策は可能ですが、非常に早く悪くなったり汚れたりします。ifup
ifdown
ifdown
veth
どういうわけかtmpfsをネットワークネームスペースにマウントする必要があるようですが、/run/network
方法がわかりません。バインディングは、ip netns exec
プログラムの実行中に非常に小さなエントリだけをインストールし、ネットワークネームスペース自体に永続的に接続されているようには見えません。インストール呼び出し中にマウントをバインドするとip netns exec ns1 ifup ...
終了し、後で作業を実行する必要がある場合は使用できません.... ifdown
。
私はネットワークネームスペースを作成するさまざまなアプローチで開いています。異なる時点で正しい名前空間で複数のプログラムを起動できるように物事を追跡する方法が必要です。
答え1
問題は、ip netns add
永続ネットワーク名前空間のみが作成されることです。ip netns exec ...
永続ネットワークネームスペースに入ると、一時マウントネームスペースも作成されます。この質問を直接尋ねる質問があって、そこにもっと詳しく答えました。https://unix.stackexchange.com/a/581618/142686
私のソリューションはunshare
。その後、名前空間tmpfs
内にマウントします。これは使用する/run/network
名前空間の別々のコピーを提供します。ifup
ifdown
主な意味は、少なくとも設置が重要な場所では、今必ずしも使用すべきではないということですip netns exec
。nsenter
永続マウントネームスペース用のディレクトリの作成
これは各名前空間で実行するのではなく、起動後に一度行う必要があります。
# Create a dir for persistent mount namespaces
$ mkdir /run/mntns
# Bind mount it with --make-private as required by `unshare --mount=/path`
$ mount --bind --make-private /run/mntns /run/mntns
ネットワーク作成+永続的な名前空間のマウント
$ NSNAME=testns # give it a name
# Create files for persistent mounts.
# For network namespace use same paths as used by `ip netns` for interoperability
$ touch /run/netns/${NSNAME} /run/mntns/${NSNAME}
# Create persistent mount and network namespaces and
# as part of the setup the command (inside the namespace) adds a mount.
$ unshare --net=/run/netns/${NSNAME} --mount=/run/mntns/${NSNAME} \
mount -t tmpfs tmpfs /run/network
それを書く
# Bring up the loopback interface, this used to fail.
$ nsenter --net=/run/netns/${NSNAME} --mount=/run/mntns/${NSNAME} \
ifup lo
# Good.
追加テスト
今重要な部分です。ネットワークインターフェイスを名前空間に移動します。ここで使用してくださいip
。
# Plug a veth interface into the namespace, use the `ip netns link`
$ ip link add veth1a type veth peer name veth1b netns ${NSNAME}
# Verify it is there (although here `ip netns exec` would work just as well)
$ nsenter --net=/run/netns/${NSNAME} --mount=/run/mntns/${NSNAME} \
ip link
1: lo: <LOOPBACK> mtu 65536 qdisc noop state DOWN mode DEFAULT group default qlen 1000
link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
2: veth1b@if17: <BROADCAST,MULTICAST> mtu 1500 qdisc noop state DOWN mode DEFAULT group default qlen 1000
link/ether e6:1b:ea:e5:77:b4 brd ff:ff:ff:ff:ff:ff link-netnsid 0
重要
この方法は動作しますが、ip netns exec
代わりにnsenter --net=... --mount=...
!
名前空間間でインターフェイスを移動するには、「ip link」を使用することはまだ機能します。
/etc/netns/NETNS_NAME/*
欠点は、提供する自動バンドルマウントを取得できないことですip netns exec NETNS_NAME cmd
。これは手動で追加するのは難しくありません。
# either during unshare or later as nsenter.
# The important difference is here it is done once and result persists
# unlike with `ip netns exec` which does this every time
NSNAME="${NSNAME}" \
nsenter --net=/run/netns/${NSNAME} --mount=/run/mntns/${NSNAME} \
/bin/sh -e -x -c \
'cd "/etc/netns/${NSNAME}"; for f in *; do mount --bind "/etc/netns/${NSNAME}/${f}" "/etc/${f}"; done;'
ip netns exec
利点は、呼び出し間で内容が変わるたびに変更するのではなく、一貫したインストールを一度に実行できることです。/etc/netns/NETNS_NAME/