UbuntuとRaspbianでネットワークネームスペースを使用するときのIfup、ifdownインターフェイスの状態エラー

UbuntuとRaspbianでネットワークネームスペースを使用するときのIfup、ifdownインターフェイスの状態エラー

.NETを使用して複数のネットワーク名前空間を作成しましたip netns add ns1ip netns add ns2

ネットワーク名前空間内でネットワークインターフェイスを起動/停止しようとすると、ifupインターフェイスifdownの状態が正しくありません。

$ ifup lo
ifup: interface lo already configured

これは /run/network/ が状態が保存される場所でありifupifdown上記のように作成されるとデフォルトネットワークネームスペースと追加ネットワークネームスペースとの間で共有されるからだと思います。その理由は、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いません。最初の名前空間でインターフェイスを開く/閉じる/開くifupifdown

$ 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本当に望んでいます。たとえば、インターフェイスを削除します。もちろん、回避策は可能ですが、非常に早く悪くなったり汚れたりします。ifupifdownifdownveth

どういうわけか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名前空間の別々のコピーを提供します。ifupifdown

主な意味は、少なくとも設置が重要な場所では、今必ずしも使用すべきではないということですip netns execnsenter

永続マウントネームスペース用のディレクトリの作成

これは各名前空間で実行するのではなく、起動後に一度行う必要があります。

# 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/

関連情報