재부팅했더니 모니터링만 13시간 죽어있던 이유
새벽 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에 바인딩해도 조용히 성공한다. 잘못 친 주소로 서비스가 떠서 아무도 못 붙는데 에러는 없는... 그런 상황이 가능해짐 홈서버에선 감수할만하다고 봤다.
마치며
부팅이 잘 되는지는 재부팅을 해봐야 안다. 다음 커널 업데이트 때 확인해볼 예정