물리 서버 코어 덤프 수집부터 디버깅 경로 검증까지

물리 서버 코어 덤프 수집부터 디버깅 경로 검증까지

물리 서버 코어 덤프 수집부터 디버깅 경로 검증까지

업무 프로세스가 갑자기 종료됐을 때 서비스를 재시작하면 운영은 재개할 수 있지만, 충돌 원인까지 알 수 있는 것은 아닙니다. 로그에 시그널 번호만 남았다면 원인을 찾기 위해 충돌 당시의 호출 스택과 해당 빌드가 필요합니다. 이 글에서는 Ubuntu Server 24.04에서 통제된 코어 덤프 수집 체계를 구성하고, 격리된 프로세스로 먼저 검증한 뒤 업무 서비스에 적용할지 결정합니다.

AMDSSH 물리 서버는 128GB 또는 256GB ECC 메모리를 선택할 수 있습니다. 그렇다고 프로세스 덤프를 서버 전체 메모리 용량에 맞춰 무조건 저장해서는 안 됩니다. core 파일에는 비밀번호, 요청 본문, 업무 데이터가 포함될 수 있으므로 수집 범위, 용량 제한, 접근 권한을 함께 설정해야 합니다.

1. 충돌 유형과 기존 수집기 확인

결제 후 콘솔에서 접속 정보를 확인하고 SSH로 로그인합니다. 아래 작업에는 관리자 권한이 필요합니다. 테스트 전에 운영체제, 디스크 여유 공간, 코어 덤프 처리 경로부터 확인합니다.

cat /etc/os-release
df -h /var/lib
sysctl kernel.core_pattern
sudo journalctl -b -p warning --no-pager

kernel.core_pattern이 파이프 문자로 시작하면 커널은 덤프를 현재 디렉터리에 직접 기록하지 않고 사용자 공간의 처리 프로그램에 전달합니다. 시스템에 다른 충돌 수집기가 이미 설치되어 있을 수 있으므로 기존 값과 관련 패키지를 기록해야 합니다. 두 처리 경로를 중복 구성한 뒤 모두 정상 작동할 것이라고 가정해서는 안 됩니다.

먼저 자발적 종료, 시그널에 의한 종료, 메모리 부족으로 인한 강제 종료를 구분합니다. SIGSEGV와 SIGABRT는 일반적으로 코어 덤프를 발생시키지만, SIGKILL은 그렇지 않습니다. 서비스 상태에 비정상 종료가 표시된다고 해서 내려받을 수 있는 파일이 생성됐다는 뜻은 아닙니다.

코어 덤프는 일반적인 운영 로그가 아니라 프로세스 메모리를 담은 증거 자료입니다. 공개 디렉터리에 저장해서는 안 되며, 내용을 확인하지 않은 채 지원 티켓이나 코드 저장소에 첨부해서도 안 됩니다.

이 글에서 사용할 도구를 설치합니다. 패키지 관리자가 기존 수집기를 교체한다고 안내하면 먼저 영향을 확인한 뒤 사용할 방식을 하나로 명확히 선택합니다.

sudo apt-get update
sudo apt-get install systemd-coredump gdb gcc
sysctl kernel.core_pattern
systemctl status systemd-coredump.socket --no-pager

설치 후에는 처리 경로가 systemd의 덤프 처리 프로그램을 가리켜야 합니다. 소켓이 덤프를 받아들이고 처리 서비스는 필요할 때 시작됩니다. 수집 프로세스가 상시 실행 중이지 않다고 해서 기능이 작동하지 않는 것은 아닙니다.

2. 덤프 수집 용량 제한 설정

/etc/systemd/coredump.conf.d/60-controlled-capture.conf를 만들고 다음 설정을 입력합니다.

[Coredump]
Storage=external
Compress=yes
ProcessSizeMax=256M
ExternalSizeMax=256M
MaxUse=512M
KeepFree=2G

이 값은 소규모 테스트 프로세스의 검증을 위한 용량 한도이며, 메모리를 많이 사용하는 업무 프로세스의 권장값이 아닙니다. ProcessSizeMax는 처리 대상 덤프의 크기를, ExternalSizeMax는 외부 파일로 저장할 덤프의 크기를 제한합니다. 한도를 초과하면 전체 메모리 파일 없이 이벤트 메타데이터만 남을 수 있습니다.

MaxUse와 KeepFree는 외부 덤프 디렉터리의 사용량을 제어하기 위한 설정입니다. 디스크 공간 확보를 보장하지 않으며, 로그 데이터베이스의 용량도 제어하지 않습니다. 여러 프로세스가 동시에 충돌하면 여전히 공간 부족이 발생할 수 있으므로 해당 파일 시스템의 여유 공간도 함께 살펴야 합니다.

설정은 이후 실행되는 처리 프로세스가 읽습니다. 다음 명령으로 병합된 설정을 확인할 수 있습니다.

systemd-analyze cat-config systemd/coredump.conf

업무 서비스에 적용하기 전에는 대표적인 프로세스의 메모리 사용 규모와 실제 덤프 크기를 측정한 뒤 한도를 조정해야 합니다. 테스트 프로그램이 검증을 통과했다고 해서 메모리를 많이 사용하는 데이터베이스의 덤프도 온전히 저장할 수 있다고 판단해서는 안 됩니다.

3. 격리된 서비스로 실제 충돌 검증

업무 데이터가 없는 테스트 프로그램 빌드

/tmp/crash-lab.c에 다음 최소 프로그램을 작성합니다.

#include <stdlib.h>

int main(void)
{
    abort();
}

전용 시스템 계정을 만들고 프로그램을 컴파일합니다. -g는 디버그 정보를 포함하고, -O0는 테스트 호출 스택을 확인하기 쉽게 해 줍니다.

sudo useradd --system --no-create-home --shell /usr/sbin/nologin crashlab
sudo install -d -m 0755 /usr/local/libexec
sudo gcc -g -O0 -o /usr/local/libexec/crash-lab /tmp/crash-lab.c

계정이 이미 있다면 먼저 용도를 확인하고 중복 생성하지 않습니다. 이어서 /etc/systemd/system/crash-lab.service를 만듭니다.

[Unit]
Description=Isolated core dump capture test

[Service]
Type=oneshot
User=crashlab
ExecStart=/usr/local/libexec/crash-lab
LimitCORE=infinity
Restart=no

여기서 infinity는 테스트 서비스의 프로세스별 제한만 해제합니다. 수집기에는 여전히 앞 절에서 설정한 용량 한도가 적용됩니다. 이 값을 모든 서비스의 전역 기본값으로 설정하지 마세요.

sudo systemctl daemon-reload
sudo systemctl start crash-lab.service
sudo systemctl status crash-lab.service --no-pager
sudo coredumpctl --no-pager list /usr/local/libexec/crash-lab

시작 명령이 실패를 보고하는 것은 예상된 결과입니다. 테스트 실행 파일과 일치하는 충돌 기록이 보여야 합니다. 기록이 없다면 처리 경로, 서비스 제한, 수집기 로그, 디스크 여유 공간을 차례로 확인합니다. 운영 중인 프로세스에 충돌 시그널을 보내 확인해서는 안 됩니다.

4. 덤프 파일과 디버깅 자료 검증

목록에서 이번 테스트의 PID를 확인해 기록합니다. 동일한 관리자 셸에서 해당 PID를 입력하고, 전용 비공개 디렉터리로 덤프를 내보냅니다.

sudo -i
read -r -p 'Crash PID: ' CRASH_PID
umask 077
install -d -m 0700 /root/crash-evidence
coredumpctl info "$CRASH_PID"
coredumpctl dump "$CRASH_PID" --output=/root/crash-evidence/test.core
gdb -q -batch \
  -ex 'set pagination off' \
  -ex 'thread apply all bt' \
  /usr/local/libexec/crash-lab /root/crash-evidence/test.core
exit

먼저 이벤트 발생 시각, 실행 파일, 시그널, 저장 상태를 확인합니다. PID가 재사용됐을 때 다른 기록을 가져오는 일을 방지하기 위해서입니다. 검증 결과에는 SIGABRT가 표시되어야 하며, 호출 스택에서 테스트 프로그램의 main을 확인할 수 있어야 합니다. 시스템 라이브러리 프레임에 소스 코드가 없더라도 테스트 수집 체계를 검증하는 데는 지장이 없습니다.

메타데이터만 남았거나, 파일을 내보낼 수 없거나, 덤프가 잘렸다는 메시지가 표시된다면 완전한 수집에 성공한 것으로 볼 수 없습니다. coredumpctl에서 이벤트를 조회할 수 있다고 해서 외부 파일이 아직 존재한다는 보장도 없습니다.

실제 업무 환경에서는 충돌 당시의 실행 파일, 공유 라이브러리, 해당 디버그 심볼도 보관해야 합니다. 업데이트 후 이름이 같은 바이너리가 있다고 해서 원래 빌드와 동일한 것은 아닙니다. readelf -n으로 Build ID를 확인하고 패키지 버전과 빌드 식별자를 기록합니다.

처음부터 bt full로 지역 변수를 출력하지 마세요. 먼저 기본 호출 스택을 확인합니다. 변수를 반드시 살펴봐야 한다면 접근이 제한된 환경에서 작업하고, 내보낸 텍스트를 항목별로 검토합니다. 바이너리를 복사할 때도 해시를 함께 보관해 분석 중 자료가 바뀌지 않았는지 확인할 수 있어야 합니다.

5. 업무 서비스 적용과 테스트 구성 정리

업무 서비스에 적용할 때는 해당 서비스의 전용 drop-in에서 LimitCORE를 설정합니다. daemon-reload를 실행한 다음 통제된 변경 절차에 따라 서비스를 재시작합니다. 설정 파일을 수정해도 이미 실행 중인 프로세스에 새 제한이 자동으로 적용되지는 않습니다. 실제 프로세스의 /proc/PID/limits를 확인해야 합니다.

적용 점검에는 최소한 다음 네 가지가 포함되어야 합니다.

테스트가 끝나면 테스트 서비스 파일, 프로그램, 소스 코드를 삭제하고 daemon-reload와 reset-failed를 실행합니다. 테스트 덤프는 coredumpctl info에 표시된 실제 경로를 기준으로 개별 처리합니다. 와일드카드로 전체 덤프 디렉터리를 비우지 마세요.

수집 정책을 철회하려면 이 글에서 추가한 설정 파일을 제거합니다. 기존 수집기를 복원해야 한다면 패키지 설정을 통해 복원하고 kernel.core_pattern을 다시 확인합니다. 기억에 의존해 처리 경로를 조합해서는 안 됩니다. 마지막으로 전체 검증 결과를 기록합니다. 충돌 이벤트를 조회할 수 있고, 파일을 내보낼 수 있으며, 호출 스택이 올바른 빌드와 일치하고, 자료 접근이 제한되어 있어야 합니다. 그래야 검증되지 않은 설정만 남기는 것이 아니라, 나중에도 확인할 수 있는 장애 증거를 확보할 수 있습니다.

자주 묻는 질문

비정상 종료가 발생하면 항상 코어 덤프가 생성되나요?

아닙니다. 정상적인 프로그램 종료나 SIGKILL은 보통 덤프를 생성하지 않습니다. 덤프를 생성하는 신호라도 프로세스 제한, 수집 정책, 크기 한도와 디스크 여유 공간의 영향을 받습니다.

GDB에서 덤프가 열리면 분석 자료가 충분한가요?

아닙니다. 장애 당시 실행 파일, 공유 라이브러리와 디버그 심볼이 일치해야 합니다. 덤프가 잘리지 않았는지도 확인해야 호출 스택을 신뢰할 수 있습니다.

EPYC 7543P 단독 물리 서버월 $450.2부터

리소스 계획부터 서버 구성까지

서버 모델과 추가 옵션은 월 단위로 합산되며, 구성 페이지에서 전체 내역을 확인할 수 있습니다. 연결 정보는 서버 인도 후 콘솔에서 확인할 수 있습니다.