질문
systemd-nspawn 컨테이너를 systemd 단위로 관리하는 방법은 무엇입니까?
설정
이미지 설치
# machinectl pull-raw --verify=no https://ftp.halifax.rwth-aachen.de/fedora/linux/releases/30/Cloud/x86_64/images/Fedora-Cloud-Base-30-1.2.x86_64.raw.xz
이미지 이름을 찾았습니다.
# machinectl list-images
NAME TYPE RO USAGE CREATED MODIF
Fedora-Cloud-Base-30-1.2.x86_64 raw no 891.6M Fri 2019-04-26 02:14:49 UTC Fri 2
1 images listed.
Fedora 컨테이너 내에서 대화형 셸 시작
# systemd-nspawn -M Fedora-Cloud-Base-30-1.2.x86_64
/root/app.py에서 신호를 처리하는 python3 애플리케이션 작성
# https://stackabuse.com/handling-unix-signals-in-python/
import signal
import os
import time
import sys
def terminateProcess(signalNumber, frame):
print(f'received signal {signalNumber}')
print ('exiting...')
sys.exit()
def receiveSignal(signalNumber, frame):
print(f'received signal {signalNumber}')
return
if __name__ == '__main__':
# register the signals to be caught
signal.signal(signal.SIGHUP, receiveSignal)
signal.signal(signal.SIGINT, terminateProcess)
signal.signal(signal.SIGQUIT, receiveSignal)
signal.signal(signal.SIGILL, receiveSignal)
signal.signal(signal.SIGTRAP, receiveSignal)
signal.signal(signal.SIGABRT, receiveSignal)
signal.signal(signal.SIGBUS, receiveSignal)
signal.signal(signal.SIGFPE, receiveSignal)
#signal.signal(signal.SIGKILL, receiveSignal)
signal.signal(signal.SIGUSR1, receiveSignal)
signal.signal(signal.SIGSEGV, receiveSignal)
signal.signal(signal.SIGUSR2, receiveSignal)
signal.signal(signal.SIGPIPE, receiveSignal)
signal.signal(signal.SIGALRM, receiveSignal)
signal.signal(signal.SIGTERM, terminateProcess)
# output current process id
print(f'pid {os.getpid()}')
# wait in an endless loop for signals
while True:
time.sleep(1)
키 조합을 사용하여 컨테이너 종료
Control + ]]]
애플리케이션 서비스 체험 1
/etc/systemd/system/app.service 단위 파일을 작성합니다.
[Service]
ExecStart=/usr/bin/systemd-nspawn --keep-unit -M Fedora-Cloud-Base-30-1.2.x86_64 python3 -u /root/app.py
SyslogIdentifier=%N
--keep-unit
system.slice/app.service
cgroup 에 systemd-nspawn 및 app.py를 유지하도록 전환-u
버퍼링되지 않은 출력 스위치%N
접미사가 없는 장치 이름인 "app" 문자열을 사용하는 SyslogIdentifier 지정자
systemd 데몬을 다시 로드하세요.
# systemctl daemon-reload
다른 터미널에서는 systemd-journald를 사용하여 로그 출력을 추적합니다.
# journalctl -f -u app.service
app.service 단위 시작
# systemctl start app.service
app.service 단위 중지
# systemctl stop app.service
관찰 기록
-- Logs begin at Fri 2019-08-23 16:58:11 UTC. --
Aug 23 17:26:42 srv0 systemd[1]: Started app.service.
Aug 23 17:26:42 srv0 app[12745]: Spawning container Fedora-Cloud-Base-30-1.2.x86_64 on /var/lib/machines/Fedora-Cloud-Base-30-1.2.x86_64.raw.
Aug 23 17:26:42 srv0 app[12745]: Press ^] three times within 1s to kill container.
Aug 23 17:26:42 srv0 app[12745]: Failed to create directory /tmp/nspawn-root-afZQoJ/sys/fs/selinux: Read-only file system
Aug 23 17:26:42 srv0 app[12745]: Failed to create directory /tmp/nspawn-root-afZQoJ/sys/fs/selinux: Read-only file system
Aug 23 17:26:42 srv0 app[12745]: pid 1
Aug 23 17:26:54 srv0 systemd[1]: Stopping app.service...
Aug 23 17:26:54 srv0 app[12745]: Container Fedora-Cloud-Base-30-1.2.x86_64 terminated by signal KILL.
Aug 23 17:26:54 srv0 systemd[1]: app.service: Main process exited, code=exited, status=1/FAILURE
Aug 23 17:26:54 srv0 systemd[1]: Stopped app.service.
Aug 23 17:26:54 srv0 systemd[1]: app.service: Unit entered failed state.
Aug 23 17:26:54 srv0 systemd[1]: app.service: Failed with result 'exit-code'.
Aug 23 17:26:54 srv0 systemd[1]: Stopped app.service.
systemd-nspawn은 SIGTERM 대신 SIGKILL을 사용합니다.
Aug 23 17:26:54 srv0 app[12745]: Container Fedora-Cloud-Base-30-1.2.x86_64 terminated by signal KILL.
"app.py를 SIGKILL하고 싶지 않고 SIGTERM하고 싶습니다" 줄을 참조하세요.
애플리케이션 서비스 체험 2
Github 문제 읽기
https://github.com/systemd/systemd/issues/7105#issuecomment-467491778
-a/--as-pid2
스위치 사용
[Service]
ExecStart=/usr/bin/systemd-nspawn --keep-unit --as-pid2 -M Fedora-Cloud-Base-30-1.2.x86_64 python3 -u /root/app.py
SyslogIdentifier=%N
데몬 다시 로드, 시작, 중지
관찰 기록
Aug 23 17:29:59 srv0 systemd[1]: Started app.service.
Aug 23 17:29:59 srv0 app[12841]: Spawning container Fedora-Cloud-Base-30-1.2.x86_64 on /var/lib/machines/Fedora-Cloud-Base-30-1.2.x86_64.raw.
Aug 23 17:29:59 srv0 app[12841]: Press ^] three times within 1s to kill container.
Aug 23 17:29:59 srv0 app[12841]: Failed to create directory /tmp/nspawn-root-jaGbcx/sys/fs/selinux: Read-only file system
Aug 23 17:29:59 srv0 app[12841]: Failed to create directory /tmp/nspawn-root-jaGbcx/sys/fs/selinux: Read-only file system
Aug 23 17:29:59 srv0 app[12841]: pid 2
Aug 23 17:30:06 srv0 systemd[1]: Stopping app.service...
Aug 23 17:30:06 srv0 app[12841]: Container Fedora-Cloud-Base-30-1.2.x86_64 terminated by signal KILL.
Aug 23 17:30:06 srv0 systemd[1]: app.service: Main process exited, code=exited, status=1/FAILURE
Aug 23 17:30:06 srv0 systemd[1]: Stopped app.service.
Aug 23 17:30:06 srv0 systemd[1]: app.service: Unit entered failed state.
Aug 23 17:30:06 srv0 systemd[1]: app.service: Failed with result 'exit-code'.
app.py는 이제 pid 2로 실행됩니다! 하지만 여전히 SIGTERM 대신 SIGKILL 신호를 받습니다.
답변1
더 많은 Github 문제 읽기
https://github.com/systemd/systemd/issues/7105#issuecomment-467491778
--kill-signal
플래그 사용
[Service]
ExecStart=/usr/bin/systemd-nspawn --keep-unit --kill-signal=SIGTERM -M Fedora-Cloud-Base-30-1.2.x86_64 python3 -u /root/app.py
SyslogIdentifier=%N
systemd를 다시 로드하고 app.service를 시작한 다음 app.service를 중지합니다.
systemctl daemon-reload
systemctl start app.service
systemctl stop app.service
관찰 기록
Aug 23 17:51:32 srv0 systemd[1]: Started app.service.
Aug 23 17:51:32 srv0 app[12994]: Spawning container Fedora-Cloud-Base-30-1.2.x86_64 on /var/lib/machines/Fedora-Cloud-Base-30-1.2.x86_64.raw.
Aug 23 17:51:32 srv0 app[12994]: Press ^] three times within 1s to kill container.
Aug 23 17:51:32 srv0 app[12994]: Failed to create directory /tmp/nspawn-root-71uVxm/sys/fs/selinux: Read-only file system
Aug 23 17:51:32 srv0 app[12994]: Failed to create directory /tmp/nspawn-root-71uVxm/sys/fs/selinux: Read-only file system
Aug 23 17:51:32 srv0 app[12994]: pid 1
Aug 23 17:51:35 srv0 app[12994]: Trying to halt container. Send SIGTERM again to trigger immediate termination.
Aug 23 17:51:35 srv0 app[12994]: received signal 15
Aug 23 17:51:35 srv0 app[12994]: exiting...
Aug 23 17:51:35 srv0 systemd[1]: Stopping app.service...
Aug 23 17:51:35 srv0 app[12994]: Container Fedora-Cloud-Base-30-1.2.x86_64 exited successfully.
Aug 23 17:51:35 srv0 systemd[1]: Stopped app.service.
Aug 23 17:51:35 srv0 systemd[1]: Stopped app.service.
SIGTERM이 app.py에 어떻게 전달되는지 살펴보세요!