ssuperjun 님의 블로그
[장애 이력 자동 작성 도구9] Redis Segfault 장애 상황 연출 및 로그 수집 코드 구현 본문
Valkey 기준 장애 연출 - deprecated
참고
valkey는 systemd로 관리되지 않고 irteam 계정으로 직접 실행 중이므로, journalctl이 아닌 valkey 로그 파일(/home1/irteam/valkey_10379/valkey_10379.log)에 기록될 가능성이 높음
Too many connections 연출 시 Valkey 변경한 항목 되돌리기
/home1/irteam/valkey_10379/bin/redis-cli -p 10379 -a 비밀번호 redisconfig set maxclients 10000
# 확인
/home1/irteam/valkey_10379/bin/redis-cli -p 10379 -a 비밀번호 redisconfig get maxclients
장애 연출 계획
방법 1: SIGSEGV 직접 전송
sudo kill -11 $(pgrep redis-server)
방법 2: gdb로 실제 segfault 유발
redis-server 프로세스에 gdb를 붙여서 실제 메모리 오류를 발생시킴. 설치 및 권한이 필요
*gdb = GNU Debugger의 약자로, 실행 중인 프로세스에 붙어서 내부 상태를 확인하거나 강제로 오류를 발생시킬 수 있는 디버깅(실행 상태 분석) 도구
방법1이 훨씬 간단하고, 로그 패턴은 동일하게 찍히므로 방법1 선택
이유
실제 코드 버그로 엉뚱한 메모리를 건드려서 발생한 진짜 Segfault든, 관리자가 밖에서 kill -11로 강제로 쏜 가짜 Segfault든, Redis 프로세스 입장에서는 동일하게 "11번 시그널을 받았다!"라고 인지, 동일한 결과(로그)가 나오기 때문
1. kill -11 실행
# irteam 계정에서 valkey pid 확인
ps -ef | grep valkey | grep -v grep
# SIGSEGV 전송
kill -11 2044758
# 로그 확인
tail -20 /home1/irteam/valkey_10379/valkey_10379.log
# segfault 전후 전체 로그 확인
grep -n "SIGSEGV\|crashed\|SEGV\|BUG REPORT\|Ooops\|signal" /home1/irteam/valkey_10379/valkey_10379.log | tail -30
2. Valkey 정상화
# valkey 재시작
/home1/irteam/valkey_10379/bin/redis-server /home1/irteam/valkey_10379/valkey_10379.conf &
# 확인
ps -ef | grep valkey | grep -v grep
3. 전후 맥락 더 확인
# BUG REPORT 시작 전후 포함한 전체 맥락 확인
sed -n '1,20p' /home1/irteam/valkey_10379/valkey_10379.log
# valkey가 재시작된 후 로그 파일에 기동 로그가 추가됐는지도 확인
tail -10 /home1/irteam/valkey_10379/valkey_10379.log
결과
파악된 로그 패턴 정리
Segfault 로그 패턴
=== VALKEY BUG REPORT START: Cut & paste starting from here ===
{pid}:M {날짜} # valkey 8.1.4 crashed by signal: 11, si_code: 0
{pid}:M {날짜} # Killed by PID: {killer_pid}, UID: {uid}
...
=== VALKEY BUG REPORT END. ===
기동 로그 패턴
{pid}:M {날짜} * oO0OoO0OoO0Oo Valkey is starting oO0OoO0OoO0Oo
{pid}:M {날짜} * Ready to accept connections tcp
특징
- journalctl이 아닌 valkey 로그 파일에만 기록됨
- systemd 관리 대상이 아니므로 자동 재시작 없음
- crashed by signal: 11 → signal 11 = SIGSEGV
핵심
- redis-server는 systemd에 등록돼 있지만, valkey는 그렇지 않음
- redis-server의 로그는 systemd(journalctl)에 기록되지만, valkey는 직접 실행되는 경우라 journalctl에 기록되지 않고 valkey 로그 파일에만 기록됨
- valkey 로그 파일은 재시작돼도 휘발되지 않음
참고
현재 valkey(직접 실행 방식)의 장애 수집 방법
| 장애 유형 | 수집 위치 |
| OOM Kill | dmesg 또는 /var/log/syslog (커널 로그) |
| Segfault | valkey 로그 파일 |
| 기동/종료 | valkey 로그 파일 |
=> 기존의 journalctl 로그 수집 로직으론 valkey 장애 로그 수집할 수 없음
결론
실제 운영 환경에서는 db가 systemd에 등록돼 있을 가능성이 높다고 판단
=> 일단 journalctl 기반으로 스크립트 구현 후 '직접 실행 인스턴스(현재 valkey같은 상황)’도 대응하기 -> 고도화
이유
- 서버 재부팅 시 자동 기동이 필요하므로 systemd 등록이 표준 관행
- 모니터링, 로그 수집 인프라가 journalctl 기반으로 구성된 경우가 많음
- 패키지 매니저(apt, yum)로 설치하면 자동으로 systemd 서비스로 등록됨
redis-server 기준 장애 연출 재개
1. systemd 메모리 한도 해제
# 50-MemoryLimit.conf 파일 확인
sudo cat /etc/systemd/system.control/redis-server.service.d/50-MemoryLimit.conf
# MemoryLimit 값을 직접 제거
sudo sed -i 's/MemoryLimit=31457280/MemoryLimit=infinity/' /etc/systemd/system.control/redis-server.service.d/50-MemoryLimit.conf
# 확인
sudo cat /etc/systemd/system.control/redis-server.service.d/50-MemoryLimit.conf
# 적용
sudo systemctl daemon-reload
2. Redis maxmemory 해제
# redis.conf에서 maxmemory 확인
sudo grep "^maxmemory" /etc/redis/redis.conf
# 런타임으로 0으로 설정 (제한 없음)
redis-cli -p 6379 config set maxmemory 0
# 확인
redis-cli -p 6379 config get maxmemory
3. 재시작 후 확인
sudo systemctl restart redis-server
sudo systemctl status redis-server | grep Memory
4. segfault 장애 연출
# redis-server pid 확인
sudo systemctl status redis-server | grep "Main PID"
# SIGSEGV 전송
sudo kill -11 <pid>
# journalctl 확인
sudo journalctl -u redis-server --no-pager --output=short-iso | tail -20
결과
segfault 로그 패턴
code=dumped, status=11/SEGV
Failed with result 'core-dump'.
지금까지의 로그패턴 정리
| 장애 유형 | journalctl 패턴 |
| OOM Kill | Failed with result 'oom-kill' |
| Segfault | Failed with result 'core-dump' |
| 외부 Signal Kill | Failed with result 'signal' |
실행 결과 사진

redis-server 기준 segfault 장애 로그 수집 스크립트 코드 구현
Failed with result 'core-dump' 패턴을 감지해 다음과 같이 코드 변경 및 추가
| 위치 | 변경 내용 |
| collect_journal_events | core-dump → segfault 이벤트 타입 추가 |
| TAG_MAP | "segfault": "[SEGFAULT]" 추가 |
| detect_cause | segfault → Segfault 반환 추가 |
| kill_types (3곳) | segfault 추가 → 장애 묶음 추출/정상화 판단에 포함 |
정상화 판단 근거는 oom과 동일하게 '마지막 재시작 후 kill 없이 30초’로 설정(oom과 마찬가지로 프로세스가 죽은 뒤 systemd가 재시작하는 패턴이므로)
구현 완료한 부분 정리
| 장애 유형 | 감지 패턴 | 원인 출력 |
| OOM Kill | Failed with result 'oom-kill' | OOM Kill |
| Segfault | Failed with result 'core-dump' | Segfault |
| Signal Kill | Failed with result 'signal' | Signal Kill (원인 수동 확인 필요) |
| 미확인 | 위 셋 모두 없음 | 미확인 (로그 수동 확인 필요) |
*미확인 장애 유형이어도, 타임라인에 [RESTART], [STARTED], [STOPPED] 등은 정상적으로 출력됨
궁금증
kill -11과 실제 Segfault의 동일성
| 구분 | kill -11 | 실제 코드 버그 Segfault |
| journalctl | code=dumped, status=11/SEGV | code=dumped, status=11/SEGV |
| Redis 로그 파일 | crashed by signal: 11 기록될 수도 있음 | crashed by signal: 11 + 스택 트레이스 |
| core dump | 생성될 수도 있음 | 생성 |
- journalctl 패턴은 동일. 둘 다 SEGV signal로 프로세스가 종료되기 때문
- 다만 실제 코드 버그 Segfault는 Redis가 signal handler를 거쳐 스택 트레이스(구체적으로 어느 함수에서, 어디서 죽었는가)를 로그 파일에 남기는 반면, kill -11은 외부에서 강제로 signal을 보내는 것이라 Redis가 signal handler를 실행하지 못하고 즉시 종료되는 경우도 있음
*코어 덤프(core dump) = 서버가 비정상적으로 종료됐을 때, 그 순간의 메모리 상태를 파일로 기록한 것
코어 덤프를 디테일하게 분석하는 건 고도화 부분으로 미뤄두는 게 낫다고 판단
'인턴' 카테고리의 다른 글
| [장애 이력 자동 작성 도구11] Redis 복제 구조 장애 상황 연출 및 로그 수집 코드 구현 (0) | 2026.03.10 |
|---|---|
| [장애 이력 자동 작성 도구10] Redis Sentinel 구조 장애 로그 수집 코드 구현 (0) | 2026.03.10 |
| [장애 이력 자동 작성 도구8] Redis Too many connections(maxclients 초과) 장애 상황 연출 및 deprecated 이유 & CPU 병목 스킵 이유 (0) | 2026.03.10 |
| [장애 이력 자동 작성 도구7] Redis 디스크 full 장애 상황 연출 및 deprecated 이유 (0) | 2026.03.10 |
| [장애 이력 자동 작성 도구6] 로그 수집 & 두레이 등록 스크립트 코드 개선 (0) | 2026.03.06 |