커널 패치는 왜 재부팅해야 적용될까? Livepatch 와 자동 재부팅
새로 만든 서버를 점검하다가 이걸 봤습니다.
설치됨: linux-image-...-29, libc6
실행 중: ...-28
/var/run/reboot-required 존재자동 보안 업데이트는 켜져 있었고, 대기 중인 패치는 0건이었습니다. 겉보기에는 완벽했습니다. 그런데 실제로 돌고 있는 커널은 패치 전 버전이었습니다.
설치와 적용은 다릅니다
unattended-upgrades 는 이름 그대로 무인 업그레이드를 해 줍니다. 다만 커널에 대해서는 하는 일이 정확히 이겁니다.
새 커널 패키지를 내려받아 디스크에 설치한다. ← 여기까지실행 중인 커널은 메모리에 올라가 있습니다. 디스크의 파일을 바꿔도 이미 돌고 있는 커널이 교체되지는 않습니다. 재부팅해서 새 커널로 부팅해야 비로소 적용됩니다.
그래서 이런 상태가 만들어집니다.
| 보이는 것 | 실제 |
|---|---|
| 자동 업데이트 enabled | 맞습니다 |
| 대기 패치 0건 | 맞습니다. 설치가 끝났으니까요 |
| 그래서 패치됐다 | 아닙니다 |
apt 는 자기 할 일을 다 했다고 보고합니다. 거짓말이 아닙니다. 다만 우리가 알고 싶은 것("이 서버가 취약한가")과 다른 질문에 답하고 있습니다.
저는 이 상태를 몇 달씩 방치한 서버를 여럿 봤습니다. 대부분 악의도 태만도 아니고, 아무도 재부팅할 이유를 못 찾아서입니다. 잘 돌고 있는 서버를 굳이 껐다 켜는 건 심리적으로 어렵습니다.
확인하는 방법
두 줄이면 됩니다.
uname -r # 지금 돌고 있는 커널
ls /var/run/reboot-required # 이 파일이 있으면 재부팅 대기 중/var/run/reboot-required 는 재부팅이 필요한 패키지가 설치될 때 만들어집니다. 어떤 패키지 때문인지도 볼 수 있습니다.
cat /var/run/reboot-required.pkgs제 경우 linux-image, linux-base, libc6 가 들어 있었습니다.
그래서 자동 재부팅을 켰습니다
unattended-upgrades 설정에 두 줄입니다.
Unattended-Upgrade::Automatic-Reboot "true";
Unattended-Upgrade::Automatic-Reboot-Time "04:30";패치 설치 후 재부팅이 필요하면 지정한 시각에 알아서 재부팅합니다.
이걸 켤 수 있느냐는 그 서버가 상태를 들고 있느냐에 달렸습니다. 제 경우는 프록시와 터널 수신만 하는 서버라 재부팅해도 잃을 게 없었습니다. 켜기 전에 실제로 재부팅해서 확인했습니다.
SSH 복구 20초
서비스 systemd 가 전부 다시 띄움
바깥에서 온 연결 자동 재접속설정에 Restart=always 를 적어 두는 것과 실제로 복구되는 것은 다릅니다. 한 번은 눌러 봐야 압니다.
여기서 실수를 했습니다
04:30 이라고 적어 놓고 새벽에 재부팅될 거라고 생각했습니다. 아니었습니다.
Automatic-Reboot-Time 은 서버의 로컬 시간 기준입니다. 클라우드 인스턴스는 대개 UTC 로 옵니다. 확인해 보니 제 서버도 UTC 였습니다.
Time zone: Etc/UTC그러면 05:30 은 한국 시간 오후 2시 30분입니다. 트래픽이 가장 많은 시간에 재부팅하도록 걸어 놓은 겁니다. 다행히 다음 재부팅 전에 발견했습니다.
고치는 건 한 줄입니다.
timedatectl set-timezone Asia/Seoul시간대를 맞춰 두면 설정 파일의 숫자가 의도한 대로 읽힙니다. 로그 타임스탬프도 같이 읽기 편해지고요.
클라우드 서버에 시각이 들어가는 설정을 넣을 때는 시간대부터 확인하시길 권합니다. cron, 백업 스케줄, 로그 회전도 같은 함정이 있습니다.
재부팅을 안 하는 방법도 있습니다
Canonical 의 Livepatch 는 재부팅 없이 커널 보안 패치를 적용합니다. 실행 중인 커널의 코드를 메모리에서 바꿔치기하는 방식입니다.
Ubuntu Pro 에 포함되고, 개인 사용은 5대까지 무료입니다(공식 커뮤니티 멤버는 50대). 등록하면 이렇게 켭니다.
sudo pro attach <토큰>
sudo pro enable livepatch솔깃하지만, 조건을 읽어 보니 생각보다 좁았습니다.
첫째, 커널 CVE 중에서도 high·critical 만 다룹니다. 문서에 따르면 낮은 등급의 보안 수정, 일반 버그 수정, 성능 개선은 포함되지 않습니다.
둘째, 커널만입니다. 제 서버가 대기 중이던 libc6 는 커널이 아닙니다. Livepatch 를 켰어도 그건 그대로 남습니다.
셋째, 결국 재부팅해야 하는 경우가 있습니다. ABI 가 바뀌거나 구조가 크게 달라지면 실행 중에 안전하게 못 바꿉니다. 그런 문제가 나오면 Livepatch 클라이언트가 kernel-upgrade-required 상태를 보고하고, 그 이전 커널은 더 이상 livepatch 되지 않습니다.
Canonical 자신도 이렇게 적어 두었습니다.
모든 재부팅을 피하려 하면 보안 패치 적용이 불완전해지고 취약한 패치 전략으로 이어진다
그래서 뭘 골랐나
저는 자동 재부팅으로 갔습니다. 이유는 단순합니다.
| 자동 재부팅 | Livepatch | |
|---|---|---|
| 커버 범위 | 커널·유저스페이스 전부 | 커널 high·critical CVE |
| 다운타임 | 새벽 20초 | 없음 (다만 가끔 재부팅 필요) |
| 필요한 것 | 설정 두 줄 | Ubuntu Pro 등록, 도구 하나 추가 |
제 서버는 20초 단절이 문제가 되지 않는 성격입니다. 그러면 커버 범위가 넓고 관리할 것이 적은 쪽이 낫습니다.
반대 상황이라면 답도 반대입니다. 세션을 오래 물고 있는 서버, 재시작에 시간이 걸리는 데이터베이스, 새벽에도 트래픽이 끊기면 안 되는 서비스라면 Livepatch 의 값어치가 큽니다. 그때도 자동 재부팅을 완전히 끄지는 말고 주기를 길게 잡는 편이 낫습니다. 언젠가는 새 커널로 갈아타야 하니까요.
정리하면 확인할 것 셋
서버를 하나 새로 세우셨다면 이것부터 보시길 권합니다.
uname -r # 돌고 있는 커널
cat /var/run/reboot-required.pkgs # 대기 중인 것
timedatectl # 시간대. 시각 설정을 넣기 전에자동 업데이트가 켜져 있다고 안심하고 있었는데, 재보니 옛 커널로 돌고 있었습니다. 설치와 적용은 다르고, 그 차이는 재부팅 한 번입니다.
함께 읽기
- Next.js 프리페치와 fail2ban: 앱이 자기 IP를 차단시키는 경로오후에 사내에서 서비스가 통째로 안 열린다는 이야기를 들었습니다. 한 곳이 아니라 여러 곳이었습니다. 업무 시스템 데모도, 웹 데스크톱도, 파일 전송망도 전부 응답이 없었습니다. 그런데 같은 주소가 바깥에서는 멀쩡히 열렸습니다.
- Cache-Control 없는 정적 페이지: iframe 안에서만 옛 화면이 뜬 이유백업 현황 페이지에 칸을 하나 더 그려 올렸는데, 새 탭에서는 새 화면이 뜨고 랜딩 페이지의 데모 모달 안에서는 전날 화면이 떴습니다. 같은 주소, 같은 서버, 같은 파일인데 화면이 둘이었습니다. 원인은 응답 헤더 하나가 처음부터 빠져 있던 데 있었고, 그 헤더를 찾다가 같은 자리에서 빠져 있던 보안 헤더들도 같이 찾았…
- 웹서비스 외부 백업: S3에 올린 사본이 같이 지워지지 않게 하는 방법매일 밤 서버에서 이런 명령이 돈다고 해 보겠습니다.
- 모니터링 서비스 비교: Better Stack부터 Datadog까지 7곳Better Stack 첫 화면에는 표가 하나 있습니다. 한 달에 트레이스·로그·지표를 각각 1TB씩 보낼 때 Datadog은 약 $55,574, Better Stack은 $687이라고 적혀 있습니다. 표 아래 각주는 이 숫자가 추정치이며 연 결제, 유럽 데이터 위치, 응답자 1명, Tera 번들, 평균 이벤트 크기 1…
- 사이트맵이 6일째 멈춘 이유: revalidateTag 가 닿지 않는 자리글을 두 편 발행하고 사이트맵을 열어 봤습니다. 둘 다 없었습니다.