Skip to content
isdnetworks
Go back

무한 반복이 된 자동 재시작

(수정됨)

컨테이너가 계속 재시작되면서 로그가 초당 수백 줄씩 쌓이고 있었다. 확인하니 Docker 의 --restart always 와 systemd 유닛의 Restart=always 양쪽에 재시작 설정이 켜져 있었다.

Table of contents

Open Table of contents

원인 — 살리는 설정보다 먼저 볼 것

살리는 설정이 겹친 것도 문제이지만 더 앞의 문제는 왜 죽느냐였다. 로그를 보니 Class not found 로 시작하자마자 죽고 있었고 배포에서 파일 하나가 빠진 것이었다.

살리는 설정 때문에 계속 다시 뜨고 계속 죽는 상태였다. 살리는 쪽을 먼저 손대면 증상만 멈추고 원인은 그대로 남는다.

조치 — 상한과 알림

재시작에 on-failure:5 로 상한을 둬서 몇 번 실패하면 그만두게 했다. 계속 도는 것보다 멈춰 있는 편이 낫기 때문이다.

멈춰 있으면 알림이 가게 했는데 여기서 하나를 놓칠 뻔했다. 계속 재시작하는 동안에는 상태가 exited 가 아니라 restarting 이라 --filter status=exited 에 안 잡히므로 재시작 상태도 함께 봐야 했다.

검증 — 겹친 관리를 하나로

살리는 계층을 하나로 정했다. Docker 공식 문서도 재시작 정책을 호스트의 프로세스 관리자와 함께 쓰지 말라고 경고한다. 두 가지 방법이 있었는데 systemd 가 관리하고 Docker 쪽을 no 로 끄는 것과 Docker 에 맡기고 서비스 유닛을 지우는 것이다. 뒤쪽을 골랐다. 이유는 다른 컨테이너들이 이미 Docker 정책으로만 관리되고 있어서다. 대신 호스트 부팅 순서를 systemd 로 제어하지 못하는 것을 감수했다.

둘이 겹치면 서로 싸우는데 한쪽이 멈추라고 하는 동안 다른 쪽이 살린다.

주의 — 로그와 디스크

재시작 간격이 점점 늘어나는 방식이라도 처음 몇 번은 빠르므로 그 사이에 로그가 수천 줄 쌓인다. 그래서 --log-opt max-size=10m 과 max-file=3 으로 상한을 뒀다.

상한을 안 두면 디스크가 차는데 실제로 재시작 반복으로 디스크가 찬 적이 있었다. 시작하다 죽는 것과 돌다가 죽는 것도 갈라서 HEALTHCHECK 에 --start-period 를 두고 그 안에 건강해지지 않으면 문제로 보게 했다.

배경 — 종료 코드와 횟수

무엇 때문에 죽었는지는 종료 코드로 갈렸다. 0 과 1 과 메모리 부족에 의한 137 과 SIGTERM 의 143 이 각각 다른 코드로 나온다.

메모리 부족은 애플리케이션 로그를 봐도 안 나오므로 docker inspect 의 OOMKilled 로 확인해야 한다. RestartCount 도 세어 지표로 보냈는데 계속 살아나는 동안에는 겉으로 정상으로 보이므로 그 숫자를 봐야만 알 수 있다.

정리


Share this post on:

Previous Post
조건을 더해도 인덱스를 못 타는 형태
Next Post
목록에 섞여 있던 내부 API