서버가 자꾸 꺼진다 — Intel I219-V NIC가 가짜 전원 버튼을 누르고 있었다
몇 주 멀쩡했던 Proxmox 호스트가 어느 날부터 외부 접속이 끊겼다. systemd 로그에서 'Power key pressed short'를 발견했지만 누른 사람이 없었다.
집에 있는 Proxmox 호스트(vm0.lab-it.net)가 어느 날부터 갑자기 외부에서 안 잡혔다. Cloudflare Tunnel 503, SSH 타임아웃, 모든 VM 접근 불가.
처음엔 그냥 재부팅으로 넘겼다. 그런데 다음날 또. 그 다음날 또.
처음 본 단서
journalctl --boot=-1로 전 부팅의 마지막 로그를 보니 이게 떴다.
systemd-logind[xxx]: Power key pressed short.
systemd-logind[xxx]: Powering off...
systemd[1]: Stopped target Graphical Interface.
...
아 누가 전원 버튼을 눌렀구나. 처음엔 그렇게 결론 내렸다. 가족 중에 누가 청소하다가 살짝 눌렀나? 본체에 케이블 정리하다가?
사용자한테 “혹시 누가 만진 거 아닌지 확인해주세요” 했더니 돌아온 답:
누가 껐을리가 없음 몇 주 동안 정상적으로 작동했고 끌 사람도 없어
맞는 말이다. 몇 주 멀쩡하다가 갑자기 매일 꺼지는 게 사람 손 탓일 수가 없다. 다시 봐야 했다.
더 깊이 파기
journalctl -k --boot=-1로 커널 로그를 따로 보니 시점이 보였다. Power key 신호가 들어오기 직전에 이런 게 있었다.
e1000e 0000:00:1f.6 eno1: Detected Hardware Unit Hang:
TDH <87>
TDT <a3>
next_to_use <a3>
next_to_clean <85>
buffer_info[next_to_clean]:
time_stamp <100bcec73>
next_to_watch <87>
jiffies <100bcef00>
next_to_watch.status <0>
e1000e 0000:00:1f.6 eno1: Reset adapter unexpectedly
e1000e는 인텔 I219-V 같은 칩셋의 이더넷 드라이버다. 이게 하드웨어 유닛이 멈췄다(Unit Hang) 고 판단해서 NIC을 강제 리셋한다. 리셋이 진행되는 동안 PCI 버스에 노이즈가 발생하고, 그 노이즈가 ACPI 전원 버튼 신호로 잘못 해석되는 케이스가 있다.
systemd-logind는 ACPI Power Button 이벤트를 보면 그게 진짜 사람 누름이든 가짜 신호든 구분 못 한다. 기본 동작은 “정상 종료(HandlePowerKey=poweroff)”. 그러니 NIC 한 번 뻗을 때마다 서버가 깔끔하게 셧다운된다.
누가 누른 게 아니라 NIC이 누르고 있었다.
왜 갑자기?
e1000e 드라이버에는 오래된 버그가 있다 — 특정 오프로딩 기능(TSO/GSO/GRO/LRO)이 켜진 상태에서 트래픽 패턴이 일정 조건에 걸리면 NIC 큐가 멈춘다. 커널 메일링 리스트에 수년간 보고된 문제다.
평소엔 트리거 안 되다가 어느 시점에 트래픽이 늘거나 패턴이 바뀌면 갑자기 매일 발생한다. 내 경우엔 허니팟이 본격 가동되면서 들어오는 패킷 수가 늘어난 시점과 일치했다.
두 층 방어
원인 분석한 만큼, 한 군데만 막아선 안 된다.
1) NIC 오프로딩 끄기 — 근본
/etc/network/interfaces에 post-up 훅으로 ethtool 호출.
iface nic2 inet manual
post-up /usr/sbin/ethtool -K $IFACE tso off gso off gro off lro off || true
부팅마다 인터페이스 올라올 때 자동으로 오프로딩 4종 비활성화. NIC이 자체적으로 큐 처리하는 대신 커널이 다 처리하니 hang 트리거가 사라진다. 약간의 CPU 비용은 있지만 트래픽 양 자체가 작아 무시 가능.
2) Power Key 무시 — 안전망
NIC이 또 hang을 일으키더라도 이젠 호스트 자체는 종료되지 않게.
/etc/systemd/logind.conf:
HandlePowerKey=ignore
HandlePowerKeyLongPress=poweroff
짧게 누르면(또는 가짜 신호 들어오면) 무시. 정말 종료하고 싶으면 길게 누르면 됨. 가족이 “왜 전원 안 꺼져?” 할 가능성은 있지만, 어차피 무인 서버라 상관 없다.
systemctl restart systemd-logind
재시작 후 적용.
검증
배포하고 며칠 관찰. 더 이상 자동 셧다운 없음. 가끔 dmesg에 e1000e hang 감지 로그가 한 번씩 뜨긴 한다 — 하지만 NIC이 자기가 알아서 reset하고 끝나고, 호스트는 살아남는다.
$ uptime
up 8 days, 3:47, 1 user, load average: 0.41 0.38 0.35
처음에 헷갈렸던 것들
“전원 버튼 = 사람”이라는 가정. 로그에 Power key pressed short가 찍혀 있으면 자동으로 사람이 눌렀다고 가정하기 쉽다. 하지만 ACPI 이벤트는 누른 사람이 없어도 발생할 수 있다. 메인보드 칩셋 결함, 펌웨어 버그, 드라이버 hang의 부산물 등.
한 줄 로그만 보고 결론 내리지 말기. Power key pressed short 직전에 무엇이 있었는지가 진짜 단서였다. 단일 메시지는 끝나는 지점이지 시작점이 아니다.
“몇 주 멀쩡했음”이 강한 신호. 사용자가 “원래는 됐는데 어느 날부터 안 됨”이라고 하면 평소 환경에서 갑자기 트리거된 변수가 있다는 뜻. 내 경우엔 트래픽 증가가 트리거였다.
정리
| 증상 | 표면 원인 | 진짜 원인 |
|---|---|---|
| 서버 자동 종료 | Power key pressed short | e1000e NIC hang의 부산물 ACPI 신호 |
| 외부 접속 불가 | Cloudflare Tunnel 503 | 호스트가 종료된 후 재부팅 안 됨 |
| 매일 같은 시간대 발생 | 우연 | 트래픽 패턴이 e1000e 버그 조건 충족 |
| 조치 | 위치 | 효과 |
|---|---|---|
| NIC 오프로딩 비활성화 | /etc/network/interfaces | hang 자체 예방 |
| HandlePowerKey=ignore | /etc/systemd/logind.conf | hang이 일어나도 호스트 생존 |
서버 운영의 절반은 로그를 어디까지 거슬러 올라가서 읽느냐다. 끝줄만 보면 사람 탓을 하게 된다.