해결책

해결책

Strongswan 데몬은 .pid 및 .ctl 파일을 /var/run에 넣어 이미 실행 중인지 감지합니다.

서로 다른 네트워크 네임스페이스 내의 동일한 시스템에서 이러한 데몬을 여러 개 실행하고 싶습니다. 나는 다른 디렉토리를 바인드 마운트하여 이를 달성하려고 합니다(예: /etc/namespace1을 네임스페이스1의 /var/run에, /etc/namespace2를 네임스페이스2의 /var/run에). /var/run은 /run에 대한 심볼릭 링크이므로 아래와 같이 마운트를 /run에 바인딩합니다.

거의 다음과 같이 달성할 수 있습니다.

""기본 네임스페이스에 있음""

$:~ sudo echo "red" >> /etc/red/run/pidfile
$:~ sudo echo "blue" >> /etc/blue/run/pidfile
$:~ sudo ip netns exec red

""빨간색 네임스페이스에""

$:~ mount --bind /etc/red/run/ /run/
$:~ cat /var/run/pidfile

빨간색

""파란색 네임스페이스에""

 $:~ mount --bind /etc/blue/run/ /run/
 $:~ cat /var/run/pidfile

파란색

그래서 이것은 잘 작동합니다. 이렇게 하면 데몬이 red 안에 있는 동안 /var/run/charon.pid를 생성할 때 blue 네임스페이스의 /var/run/charon.pid와 혼동되지 않고 두 개의 인스턴스가 시작될 수 있습니다.

그러나 문제는 다음과 같습니다. red 네임스페이스에서 "종료"한 다음 "ip netns exec red bash"를 통해 다시 입력하면 마운트가 더 이상 존재하지 않습니다. 즉, /var/run/redfile이 전혀 없습니다.

그렇다면 문제는 어떻게 이것을 끈끈하게 만들 수 있느냐는 것입니다. /etc/fstab 변경이 필요합니까? 하지만 작동하지 않습니다. 요청하면 "작동하지 않습니다"에 대한 세부 정보를 제공할 수 있습니다.

나는 길을 잃었다. 도움을 주시면 감사하겠습니다.

감사해요!

답변1

간단한 해결책은 Strongswan의 각 인스턴스에 올바른 값을 설정하여 PID 파일을 저장하기 위해 다른 디렉터리를 사용하도록 지시하는 것입니다.IPSEC_PIDDIR시작 및 중지 스크립트의 환경 변수입니다.

답변2

ip netns exec/etc/netns/<netns name>/*이미 바인드가 .NET의 해당 파일/디렉토리에 마운트되었습니다 /etc. 따라서 다음과 같이 StrongSwan을 컴파일할 수 있습니다.--with-piddir=/etc/ipsec.d/run 한 다음 필요한 디렉터리를 생성하여 각 인스턴스가 별도의 디렉터리에 PID 파일을 생성할 수 있습니다.

# mkdir -p /etc/ipsec.d/run
# mkdir -p /etc/netns/<netns name 1>/ipsec.d/run
# mkdir -p /etc/netns/<netns name 2>/ipsec.d/run

자세한 내용은 다음에서 확인할 수 있습니다.StrongSwan 위키.

답변3

문제 원인 AFAIK

ip netns add ${NSNAME}영구 네임스페이스를 다음에 마운트하여 생성합니다./run/netns/${NSNAME} . 아직은 이 자체에는 마운트 네임스페이스가 포함되지 않습니다.

행위ip netns exec ${NSNAME} cmd a가 생성됩니다.일시적인종료될 때까지 존재하는 마운트 네임스페이스는 cmd마운트 네임스페이스가 정리된 후에는 네트워크 네임스페이스만 남습니다. 이는 의 매직 마운팅을 달성하는 데 필요합니다 /etc/netns/${NSNAME}/*. 불행하게도 에서 수행한 모든 마운트 cmd도 정리되었습니다.

에서 man ip-netns:

ip netns exec마운트 네임스페이스를 생성하고 모든 네트워크 네임스페이스 구성 파일을 /etc의 기존 위치에 마운트하여 바인드하여 이 구성, 네트워크 네임스페이스를 인식하지 못하는 응용 프로그램에 대한 파일 규칙 처리를 자동화합니다.

해결책

짧은 버전

    # Init for persistent mount namespaces
    $ mkdir /run/mntns \
        && mount --bind --make-private /run/mntns /run/mntns

    $ NSNAME=red

    # Create persistent network+mount namespaces
    $ ip netns add ${NSNAME} \
        && touch "/run/mntns/${NSNAME}" \
        && ip netns exec "${NSNAME}" \
            sh -x -c "nsenter -t $$ --mount mount --bind /proc/\$\$/ns/mnt '/run/mntns/${NSNAME}' && :"

    # Do NOT use `ip netns exec`
    # (Re)enter the namespaces with `nsenter`, mounts are persistent
    $ nsenter --net=/run/netns/${NSNAME} --mount=/run/mntns/${NSNAME} \
          program arg1 arg2

긴 버전

네트워크 및 마운트 네임스페이스를 모두 영구적으로 생성할 수 있습니다.

이는 매뉴얼 페이지의 예에서 크게 수정되었습니다 unshare.http://man7.org/linux/man-pages/man1/unshare.1.html

주요 의미는 이제 적어도 마운트가 중요한 곳에서는 네트워크+마운트 네임스페이스를 모두 사용하는 대신 을 사용해야 한다는 ip netns exec것 입니다.nsenter

1단계. 준비하세요. 영구 마운트 네임스페이스를 위한 디렉터리 생성

이 작업은 모든 네임스페이스에 대해 수행하는 것이 아니라 부팅 후에 한 번 수행해야 합니다. 여기의 경로는 임의적입니다. 에서 사용하는 것과 유사한 이름을 사용하려고 합니다 ip netns.

    # Try to create a dir for persistent mount namespaces
    # and if it got created (e.g. first attempt since boot),
    # then bind mount it with --make-private as required by `unshare --mount=/path`
    $ mkdir /run/mntns \
        && mount --bind --make-private /run/mntns /run/mntns

이는 mkdir ... && mount ...원자적이지 않으며 이 시퀀스를 수행하는 동시에 여러 서비스를 시작하는 경우 경쟁 조건이 발생할 수 있습니다.

2단계. 네트워크+마운트 영구 네임스페이스 생성

2a. 방법 A, 간단하고 마법의 바인드 마운트가 없습니다.

그러면 영구 마운트+네트워크 네임스페이스가 생성됩니다. 간단하지만 /etc/netns/${NSNAME}/*.

    $ NSNAME=red # give it a name

    # For network namespace use same paths as used by `ip netns` for interoperability
    # touch can fail to update timestamp if file is already mounted
    # Try to create files for persistent mounts.
    # and if touch is successful
    # then create persistent mount and network namespaces
    # Instead of `true` can run a command right away e.g. /bin/bash
    # As it is this is approximate equivalent of `ip netns add ${NANAME}`
    $ touch /run/netns/${NSNAME} /run/mntns/${NSNAME} \
        && unshare --net=/run/netns/${NSNAME} --mount=/run/mntns/${NSNAME} true

2b. 방법 B, ip netns exec마운트를 만들기 위해 활용하되 지속적으로 만듭니다.

바인드 마운트를 완료 ip netns exec ...하고 지속적으로 만들려면 다음과 같이 설정을 수행할 수 있습니다. 이 작업은 매번 수행하는 것이 아니라 네임스페이스를 생성할 때 한 번만 수행해야 합니다.

    $ ip netns add ${NSNAME} \
        && touch "/run/mntns/${NSNAME}" \
        && ip netns exec "${NSNAME}" \
            sh -x -c "nsenter -t $$ --mount mount --bind /proc/\$\$/ns/mnt '/run/mntns/${NSNAME}' && :"

시도된 설명은 끝부분을 참조하세요.

3단계. 사용하기

이제 nsenter영구 마운트 결과를 얻으려면 필요에 따라 두 네임스페이스 내에서 명령을 실행하는 데 사용해야 합니다. 이는 설정이 unshare또는 로 수행되었는지 여부와 관계가 없습니다 ip netns exec NAME sh ... nsneter ... mount ....

    # Get a shell inside the namespaces
    $ nsenter --net=/run/netns/${NSNAME} --mount=/run/mntns/${NSNAME} \
        /bin/bash

예를 들어 OP의 명령을 사용하면 다음과 같습니다.

    # Do your additional mounts (can also be done above as command to `unshare`)
    # This is approximate equivalent of 
    #   `ip netns exec ${NANAME} mount --bind /etc/red/run/ /run/`
    $ nsenter --net=/run/netns/${NSNAME} --mount=/run/mntns/${NSNAME} \
          mount --bind /etc/${NSNAME}/run/ /run/

    # Re-enter the namespaces, check that the mounts are still there
    $ nsenter --net=/run/netns/${NSNAME} --mount=/run/mntns/${NSNAME} \
          sh -c 'ls /run/'

중요한

이 접근 방식은 작동하지만 대신 ip netns execuse nsenter --net=... --mount=...! 가 사용 되면 ip netns exec ...(실행 기간 동안) 마운트 네임스페이스를 대체합니다. 이는 마운트의 지속성을 고려하지 않는 명령에 대해 괜찮을 수 있습니다. 예를 들어

    # This does not touch any files, only operates on network device
    ip netns exec ${NSNAME} ip link set up dev lo

Z단계 - 정리

위의 두 가지 방법 중 어떤 방법을 사용하여 네임스페이스를 생성했는지에 관계없이 다음 두 가지 방법 중 하나로 정리를 수행할 수 있습니다.

    # This deletes the /mnt/netns/${NSNAME} for us
    ip netns del ${NSNAME}
    # Unmount and delete mount namespace holder
    umount "/mnt/mntns/${NSNAME}" \
        && rm "/mnt/mntns/${NSNAME}"

또는

    # Unmount and delete both namespaces' holders
    umount "/mnt/mntns/${NSNAME}" "/mnt/netns/${NSNAME}" \
        && rm "/mnt/mntns/${NSNAME}" "/mnt/netns/${NSNAME}"

설명

긴 텍스트에 대해 사과드립니다. 이것은 부분적으로 나 자신의 이익을 위한 것입니다.

이 명령은 단계에서2b위에는 설명이 필요합니다.

다시 명령.

    $ ip netns add ${NSNAME} \
        && touch "/run/mntns/${NSNAME}" \
        && ip netns exec "${NSNAME}" \
            sh -x -c "nsenter -t $$ --mount mount --bind /proc/\$\$/ns/mnt '/run/mntns/${NSNAME}' && :"

에서man unshare

/proc/pid/ns/type 파일을 파일 시스템 경로에 바인드 마운트하고 프로그램이 종료된 후에도 nsenter(1)를 사용하여 입력하면 네임스페이스를 선택적으로 영구적으로 만들 수 있습니다(영구적으로 실행 중인 init 프로세스가 필요한 PID 네임스페이스 제외). 영구 네임스페이스가 더 이상 필요하지 않으면 umount(8)를 사용하여 영구 네임스페이스를 제거할 수 있습니다.

설명 시작

간단한 단계로 나누어서 수행되는 작업은 다음과 같습니다. 이 데모에는 두 개의 셸이 필요합니다.

    # SHELL-1

    # Init
    $ mkdir /run/mntns \
        && mount --bind --make-private /run/mntns /run/mntns

    # Prep
    $ NSNAME=red

    # Create namespace
    $ ip netns add ${NSNAME}
    # Start a shell inside the namespace
    $ ip netns exec "${NSNAME}" /bin/bash

    # Now inside a shell inside a namespace.
    # Now need to make a bind mount it this shell's mount namespace
    $ echo $$ # Use this in SHELL2 AS SHELL1_PID
    # Go to SHELL-2 before exiting this one
    # SHELL-2

    # Set this to PID from SHELL-1
    $ SHELL1_PID=????

    $ NSNAME=red
    $ touch "/run/mntns/${NSNAME}"

    $ mount --bind /proc/${SHELL1_PID}/ns/mnt "/run/mntns/${NSNAME}"

nsenter이제 두 네트워크+마운트 네임스페이스는 모두 영구적이며 앞서 설명한 대로 다시 입력할 수 있습니다 .

중요한 부분은 마운팅입니다 ip netns exec./proc/pid/ns/net 외부 쉘의 마운트 네임스페이스에~ 전에 ip netns exec..종료됩니다.

설명 계속

따라서 대답은 다음과 같습니다. ip netns exec ...do 내에서 nsenter직접 명령을 사용하는 것이 아니라 임시 네임스페이스를 떠나서 파괴하지 않고 임시 네임스페이스를 활성 상태로 유지하는 중간 셸을 실행하여 분기(fork)를 발생시키기 때문 ip netns exec ${NSNAME} nsenter ...입니다 exec(). 하다 . 다음은 하나의 긴 명령이 작동하는 방식에 더 가깝습니다.fork()nsentermount

    # Init
    $ mkdir /run/mntns \
        && mount --bind --make-private /run/mntns /run/mntns

    # Prep
    $ export NSNAME=red
    $ touch "/run/mntns/${NSNAME}"

    $ export MOUNT_PARENT_PID=$$ # for simplicity

    # Create namespace
    $ ip netns add ${NSNAME}
    # Start a shell inside the namespace, the intermediate shell is important
    $ ip netns exec "${NSNAME}" /bin/bash
    # Now inside a forked namespaced shell

    # Need to mount `ip netns exec` temporary mount namespace to a file
    # within MOUNT_PARENT_PID's namespace to make it persistent
    # nsenter will reference it later

    $$ nsenter -t ${MOUNT_PARENT_PID} --mount \
           mount --bind /proc/$$/ns/mnt "/run/mntns/${NSNAME}"

    # Yes, here $MOUNT_PARENT_PID can be replaced by $PPID
    # But if any intermediate sub-shells and forks get introduced
    # then $PPID can point to a different process.

단일 명령에 대해 bash호출된 일부 버전은 여기서는 fork()가 실제로 필요하므로 이를 강제로 명령 끝 부분에 표시합니다(시작 시 짧은 버전 참조).-c commandfork()&& :

수동으로 장착/etc/netns/${NSNAME}/*

원래 답변에는 이 섹션이 있었으므로 여기에 있지만 그다지 유용하지는 않습니다.

/mnt/netns/${NSNAME}/ 다시 생성 중바인드 마운트*

사용의 단점은 에서 제공하는 unshare자동 바인드 마운트를 얻을 수 없다는 것입니다 . 이는 수동으로 추가하기 어렵지 않습니다./etc/netns/NETNS_NAME/*ip netns exec ${NSNAME} 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;'

관련 정보