떨어져 있는

떨어져 있는

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

파란색

그래서 이것은 훌륭하게 작동합니다. 이렇게 하면 데몬이 빨간색 네임스페이스 안에 /var/run/charon.pid를 생성할 때 파란색 네임스페이스의 /var/run/charon.pid와 혼동되지 않고 두 인스턴스를 모두 시작할 수 있습니다.

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

그렇다면 문제는 어떻게 이것을 끈끈하게 만들 수 있느냐는 것입니다. /etc/fstab을 변경해야 합니까? 그러나 이것은 작동하지 않습니다. 누군가 요청하면 "작동하지 않습니다"라는 세부 정보를 제공할 수 있습니다.

나는 그것을 알아낼 수 없다. 도움을 주시면 감사하겠습니다.

감사해요!

답변1

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

답변2

ip netns exec/etc/netns/<netns name>/*이미 바인드가 에 마운트되어 /etc있으므로 eg를 사용하여 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

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

답변3

문제의 원인을 아는 한

ip netns add ${NSNAME}에 마운트하면 /run/netns/${NSNAME}네임스페이스 자체를 마운트하는 작업이 포함되지 않습니다.

ip netns exec ${NSNAME} cmd을 하면일시적인마운트 네임스페이스는 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 exec이 접근 방식은 작동 하지만 사용 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직접 명령을 사용하는 것이 아니라 임시 네임스페이스를 떠나 거나 파괴 ip netns exec ${NSNAME} nsenter ...하지 않고 중간 셸을 실행하여 임시 네임스페이스를 활성 상태로 유지하는 fork()를 발생시키고 분기가 완료됩니다. . 다음은 긴 명령이 작동하는 방식에 더 가깝습니다.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()가 실제로 필요하므로 명령 끝에 강제로 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;'

관련 정보