애플리케이션이 크래시했는데 자동으로 안 살아난 이유 — systemd Restart 정책
문제 발생
systemd 서비스로 등록한 애플리케이션이 예외로 죽었는데, 자동으로 재시작되지 않고 그대로 멈춰서 다음 날 아침까지 서비스가 중단된 채로 있었습니다.
원인 분석
systemd 서비스 유닛 파일의 Restart= 지시자는 기본값이 no입니다 — 명시적으로 설정하지 않으면, 프로세스가 어떤 이유로 종료되든(정상 종료든 크래시든) systemd는 자동으로 재시작하지 않습니다. 이건 systemd가 문제라기보다, "이 서비스가 예기치 않게 죽으면 자동으로 다시 살려야 하는가"를 운영자가 명시적으로 결정하도록 설계된 것입니다.
해결 방안
Restart=지시자를 서비스 성격에 맞게 명시합니다.
[Service]
ExecStart=/usr/bin/node /opt/app/server.js
Restart=on-failure # 비정상 종료(0이 아닌 종료 코드, 시그널)일 때만 재시작
RestartSec=5s # 재시작 전 대기 시간주요 옵션: no(기본값, 재시작 안 함), on-failure(비정상 종료 시에만), always(어떤 이유로 종료되든 항상), on-abnormal(시그널/타임아웃 등으로 종료된 경우만) — 대부분의 장기 실행 서비스에는 on-failure나 always가 적합합니다.
- 재시작 폭주(restart loop)를 막는 안전장치도 함께 설정합니다 — 설정 오류처럼 시작하자마자 계속 실패하는 상황에서,
Restart=always만 있으면 초당 여러 번 재시작을 반복하며 로그를 도배하고 리소스를 낭비할 수 있습니다.
[Service]
Restart=on-failure
RestartSec=5s
StartLimitIntervalSec=60s # 이 기간 안에
StartLimitBurst=5 # 5번 이상 재시작 시도하면
# 이후 자동 재시작을 멈추고 유닛을 failed 상태로 전환RestartSec에 고정값 대신 점진적으로 늘어나는 백오프를 직접 구현하려면 systemd 자체 기능만으로는 한계가 있어, 애플리케이션 자체의 재시도 로직(DB 연결 재시도 등)과 systemd의 재시작 정책을 함께 설계하는 것이 현실적입니다.- 재시작 정책을 설정한 뒤에는 실제로 프로세스를 강제 종료(
kill -9)해보고 의도한 대로 재시작되는지, 재시작 폭주 방지가 실제로 작동하는지 직접 검증합니다 — 설정 파일 문법이 맞아도 실제 동작은 별개로 확인이 필요합니다. - 컨테이너 환경(Docker/Kubernetes)에서는 이 역할을
docker run --restart정책이나 Kubernetes의restartPolicy가 대신 담당합니다 — systemd와 컨테이너 오케스트레이터의 재시작 정책을 이중으로 겹쳐서 설정하면 오히려 예측하기 어려운 상호작용이 생길 수 있으므로, 어느 계층이 이 책임을 맡을지 명확히 정합니다.
댓글0
댓글을 남기려면 로그인이 필요해요. 로그인
아직 댓글이 없어요. 첫 의견을 편하게 남겨 보세요.