← 목록

재부팅했더니 모니터링만 13시간 죽어있던 이유

#docker#wireguard#prometheus#homeserver

새벽 4시에 서버가 자동 재부팅됐다(커널 업데이트). 컨테이너 20개 넘게 도는데 다른건 다 멀쩡히 올라왔고 하필 Prometheus, Grafana, Alertmanager만 죽어있었다. 그것도 13시간 동안. 모니터링이 죽으면 죽었다고 알려줄 놈도 같이 죽는다는게 함정이다. 온도 그래프 보다가 그래프에 12시간짜리 구멍이 뚫려있는걸 보고서야 알았음.

왜 걔네만?

부팅 시각의 도커 로그를 뒤져보니 답이 그대로 있었다.

failed to bind host port 10.100.0.1:9090: cannot assign requested address

모니터링은 관리용이라 VPN(WireGuard) IP에만 바인딩해놨다. 외부에서 아예 안 보이게. 그런데 부팅할 때 도커가 WireGuard 인터페이스보다 먼저 뜨면 그 IP가 아직 세상에 없다. 없는 주소에 바인딩하려니 실패하고, 포트 예약 자체가 실패라 restart 정책이고 뭐고 컨테이너가 그대로 주저앉는다.

나머지가 산 이유는 걔네는 0.0.0.0이나 도커 내부망에 붙어있어서. VPN IP에 바인딩한 것들만 정확히 골라서 죽었다. 보안 챙기려고 한 설정이 부팅 경주에서 지는 원인이 된 것임

해결

net.ipv4.ip_nonlocal_bind = 1

아직 존재하지 않는 IP에도 바인딩을 허용하는 커널 설정이다. /etc/sysctl.d/에 넣어두면 재부팅에도 유지된다. 이러면 도커가 WireGuard보다 먼저 떠도 일단 바인딩이 성공하고, 인터페이스가 올라오는 순간부터 트래픽이 흐른다.

systemd 의존성으로 순서를 강제하는 방법도 있긴 한데, 이 서버는 WireGuard 자체도 컨테이너(wg-easy)라 도커가 도커를 기다리는 모양이 돼서 얽힌다. 커널 설정 한 줄이 제일 깔끔했다.

부작용도 알고는 써야 한다. 오타난 IP에 바인딩해도 조용히 성공하게 된다. 잘못 친 주소로 서비스가 떠서 아무도 못 붙는데 에러는 없는... 그런 상황이 가능해짐. 홈서버에선 감수할만한 트레이드오프라고 봤다.

마치며

부팅이 잘 되는지는 재부팅을 해봐야 안다. 다음 커널 업데이트가 테스트가 될 것이다.

← 목록으로
오늘 0·전체 0