systemd-nspawn 컨테이너가 시작될 때까지 기다리는 방법은 무엇입니까?

systemd-nspawn 컨테이너가 시작될 때까지 기다리는 방법은 무엇입니까?

다음 내용의 스크립트가 있습니다.

sudo machinectl start "$machinename"
sudo systemd-run -PM root@"$machinename" "$command"
Failed to connect to bus: No such file or directory
Failed to start transient service unit: Transport endpoint is not connected

첫 번째 줄은 컨테이너를 시작하기 때문에 실패합니다. 두 번째 줄은 컨테이너 시작이 완료되기 전에 실행됩니다. 현재 컨테이너의 상태를 계속 폴링하고 준비가 될 때까지 차단하는 솔루션이 있습니다.

while [ "$(sudo systemctl show "systemd-nspawn@$machinename" -P StatusText)" != "Container running: Ready." ]
do
true
done

컨테이너 상태를 지속적으로 폴링하지 않고 컨테이너 시작이 완료될 때까지 어떻게 기다릴 수 있나요?

답변1

당신이하고 싶은 일에 따라 다릅니다. 귀하의 질문에 직접 답변한 다음 몇 가지 대안을 드리겠습니다. 컨테이너에서 init 시스템으로 systemd를 사용하고 있다고 가정합니다. 컨테이너 OS가 Debian/Arch/Ubuntu 또는 이와 유사한 기반인 경우 실제로 그렇습니다.

nspawn 컨테이너를 시작한 후 명령을 실행합니다.

.nspawn파일( /etc/systemd/nspawn/yourcontainer.nspawn) 에 다음을 추가합니다.

[Exec]
NotifyReady=yes

그런 다음 sudo machinectl start yourcontainer컨테이너가 종료되기 전에 시작이 완료될 때까지 기다립니다. 이제 컨테이너가 준비되었으므로 스크립트의 두 번째 줄이 작동합니다(컨테이너가 시작되지 않아 폴링이 무한 루프에 빠지지 않는 한).

내부적으로 호스트는 systemd-nspawn컨테이너에 Unix 도메인 소켓을 설정하고 있습니다. /run/host/notify컨테이너의 systemd가 준비되면(즉, multi-user.target대상에 도달하면) READY=1해당 소켓에 알림을 보냅니다. 호스트의 systemd-nspawn서비스가 메시지 수신을 기다리고 있습니다.

이 접근 방식의 단점은 더 이상 컨테이너를 비동기식으로 시작할 수 없다는 것입니다( &기호를 사용하지 않는 한). 이는 디버깅 중이고 시작 시간이 긴 경우 성가실 수 있습니다.

기타 방법(복잡도 순):

chroot에서 명령 실행

컨테이너가 실행되고 있지 않다고 가정하면,

sudo chroot /var/lib/machines/yourcontainer /bin/bash -c "$command"

이는 방금 컨테이너를 생성하고 프로그래밍 방식으로 여러 번 초기화한 경우에 유용합니다. 분명히 샌드박스 기능의 이점을 얻지 못하는 것 같습니다. PrivateUsers=yes파일이 chown높은 UID로 편집되므로 이전에 동일한 컨테이너를 실행한 경우에도 작동하지 않습니다 . 컨테이너가 이미 실행 중인 경우 정의되지 않은 결과가 나타날 수 있습니다.

systemd-nspawn을 직접 사용

이 방법은 과연아니요NotifyReady=yes|no위의 설명이 필요합니다 .

systemd-nspawn -M yourcontainer -P /bin/bash -c "$command"

이렇게 하면 모든 샌드박스가 활성화된 컨테이너 내에서 명령이 실행되지만 명령은 유일한 프로세스로(및 PID=1) 실행됩니다. 즉, init 서비스가 실행되지 않습니다. 예를 들어, 호스트 네트워킹을 사용하지 않는 한 네트워킹을 사용할 수 없습니다.

컨테이너가 이미 실행 중이면 이 명령은 아무런 효과가 없습니다.

소켓 활성화

컨테이너의 서버가 준비될 때까지 기다리는 경우 소켓 활성화를 사용하면 됩니다(서버가 호환된다고 가정). 이것은다른 곳에서 더 나은 설명요약하면 systemd는 소켓(예: TCP 포트 80)에 대한 연결을 기다립니다. 클라이언트가 연결되면 systemd는 컨테이너를 시작한 다음 컨테이너로 트래픽을 전달합니다. 고대에도 inetd똑같은 일이 행해졌습니다 .

이를 위해서는 파일 [email protected]에 있는 것과 같은 줄이 필요합니다 .socket.

관련 정보