Notice
Recent Posts
Recent Comments
Link
«   2026/06   »
1 2 3 4 5 6
7 8 9 10 11 12 13
14 15 16 17 18 19 20
21 22 23 24 25 26 27
28 29 30
Tags
more
Archives
Today
Total
관리 메뉴

ssuperjun 님의 블로그

[장애 이력 자동 작성 도구9] Redis Segfault 장애 상황 연출 및 로그 수집 코드 구현 본문

인턴

[장애 이력 자동 작성 도구9] Redis Segfault 장애 상황 연출 및 로그 수집 코드 구현

ssuperjun 2026. 3. 10. 14:30

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) = 서버가 비정상적으로 종료됐을 때, 그 순간의 메모리 상태를 파일로 기록한 것

코어 덤프를 디테일하게 분석하는 고도화 부분으로 미뤄두는 게 낫다고 판단