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
직접 명령을 사용하는 것이 아니라 임시 네임스페이스를 떠나 거나 파괴 하지 않고 중간 셸을 실행하여 임시 네임스페이스를 활성 상태로 유지하는 fork()를 발생시키고 분기가 완료됩니다. . 다음은 긴 명령이 작동하는 방식에 더 가깝습니다.ip netns exec ${NSNAME} nsenter ...
exec()
fork()
nsenter
mount
# 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 command
fork()
&& :
수동 설치/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;'