Ubuntu 및 Raspbian에서 네트워크 네임스페이스를 사용할 때 Ifup, ifdown 인터페이스 상태 오류

Ubuntu 및 Raspbian에서 네트워크 네임스페이스를 사용할 때 Ifup, ifdown 인터페이스 상태 오류

.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되지 않았습니다 . 첫 번째 네임스페이스에서 인터페이스 열기/닫기/열기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

좋습니다. 이제 두 번째 네임스페이스에서 동일한 up/down/up을 수행하면 오류가 발생합니다.

$ ip netns exec ns2 ifup br2
ifup: interface br2 already configured

$ cat /run/network/ifstate.br2
br2

그것이 문제이다! 두 번째 네임스페이스를 통해 인터페이스를 중지합니다(첫 번째 네임스페이스를 통해 시작되었습니다).

$ 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

위와 비슷한 문제로, 두 번째 네임스페이스에서는 인터페이스 wad가 중지되었지만 첫 번째 네임스페이스에서는 작동 중지된 것으로 보고되었습니다.

불행히도 이것은 작동하므로 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 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/

관련 정보