zioinfo-mail/manual/21_zio서버_장애대응_가이드.md
DESKTOP-TKLFCPR\ython 11c670f2a0 refactor: 101.79.17.164 → zioinfo.co.kr 전체 도메인 변환 + Manager UI 배포
- 37개 파일 IP → zioinfo.co.kr 치환 (소스/매뉴얼/설정/하네스)
- Manager DrConsole/NetworkConsole/CsapConsole 빌드 + /var/www/manager/ 배포
- 테스트: Manager HTTP 200, ITSM 신규 API 7개 전체 200

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-31 10:09:17 +09:00

10 KiB

zio-server 장애 대응 가이드 (Runbook)

서버: zio-server | IP: zioinfo.co.kr
작성일: 2026-05-30
목적: 장애 발생 시 빠른 진단과 복구를 위한 단계별 절차서


긴급 연락 및 접속

# 즉시 서버 접속
ssh -i "zio-server-key.pem" root@zioinfo.co.kr
# 또는
ssh root@zioinfo.co.kr   # 비밀번호: 1q2w3e!Q

1. 빠른 현황 진단 (첫 번째로 실행)

#!/bin/bash
echo "=== 서비스 상태 ==="
for s in nginx zioinfo zioinfo-deploy guardia gitea jenkins postgresql ollama; do
    status=$(systemctl is-active $s 2>/dev/null)
    icon="✅"; [ "$status" != "active" ] && icon="❌"
    printf "%s %-22s %s\n" "$icon" "$s" "$status"
done

echo ""
echo "=== 리소스 ==="
free -h | grep Mem
df -h / | tail -1

echo ""
echo "=== 최근 에러 ==="
journalctl -p err --since "30 minutes ago" --no-pager | tail -10

2. 장애 유형별 대응


CASE 1: 홈페이지(http://zioinfo.co.kr) 접속 불가

증상: 브라우저에서 접속 시 연결 거부 또는 502 오류

# Step 1: Nginx 확인
systemctl is-active nginx || {
    nginx -t && systemctl start nginx
    echo "Nginx 재시작"
}

# Step 2: Nginx 502 (백엔드 응답 없음)
curl -s -o /dev/null -w "%{http_code}" http://localhost:8082/api/company
# → 000 또는 연결 실패 시: Spring Boot 재시작
systemctl restart zioinfo
sleep 8
systemctl is-active zioinfo

# Step 3: Spring Boot 로그 확인
tail -30 /var/log/zioinfo/spring.log

# Step 4: 포트 확인
ss -tlnp | grep -E ":(80|8082)"

# 완료 확인
curl -s -o /dev/null -w "홈페이지: HTTP %{http_code}\n" http://localhost/

예상 복구 시간: 1~3분


CASE 2: 관리자 페이지(/admin) 로그인 불가

증상: admin/Admin@2026! 로그인 실패 또는 JWT 오류

# Step 1: Spring Boot API 응답 확인
curl -s -X POST http://localhost/api/admin/login \
  -H "Content-Type: application/json" \
  -d '{"username":"admin","password":"Admin@2026!"}' | python3 -m json.tool

# Step 2: 401 Unauthorized → 계정 확인
# SQLite DB 접속
sqlite3 /opt/zioinfo/app/data/zioinfo.db "SELECT username, enabled FROM admin_user;"

# Step 3: 계정 비활성화 시 활성화
sqlite3 /opt/zioinfo/app/data/zioinfo.db \
  "UPDATE admin_user SET enabled=1 WHERE username='admin';"

# Step 4: Spring Boot 재시작
systemctl restart zioinfo

CASE 3: GUARDiA ITSM(포트 8001) 응답 없음

증상: http://zioinfo.co.kr:8001 접속 불가

# Step 1: 서비스 상태
systemctl status guardia

# Step 2: 로그 확인
tail -30 /opt/guardia/logs/error.log

# Step 3: PostgreSQL 연결 확인
systemctl is-active postgresql || systemctl start postgresql
psql -h 127.0.0.1 -U guardia -d guardia_db -c "SELECT 1" 2>&1

# Step 4: GUARDiA 재시작
systemctl restart guardia
sleep 5

# Step 5: FastAPI 응답 확인
curl -s -o /dev/null -w "GUARDiA: HTTP %{http_code}\n" http://localhost:8001/docs

예상 복구 시간: 2~5분


CASE 4: PostgreSQL 연결 오류

증상: GUARDiA 또는 Gitea에서 DB 연결 실패 로그

# Step 1: 상태 확인
systemctl status postgresql

# Step 2: 재시작
systemctl restart postgresql
sleep 3

# Step 3: 연결 테스트
sudo -u postgres psql -c "\l" 2>&1

# Step 4: 로그 확인
tail -20 /var/log/postgresql/postgresql-16-main.log

# Step 5: DB 접속 정상화 확인
psql -h 127.0.0.1 -U guardia -d guardia_db -c "SELECT count(*) FROM pg_tables"

CASE 5: CI/CD 배포 실패

증상: git push 후 변경 내용이 적용되지 않음

# Step 1: 웹훅 서버 상태
systemctl is-active zioinfo-deploy
journalctl -u zioinfo-deploy -n 20 --no-pager

# Step 2: 배포 로그 확인
tail -50 /var/log/zioinfo/deploy.log

# 오류 유형별 대응:
# [git pull] 실패 → 네트워크 또는 Gitea 확인
systemctl is-active gitea
curl -s http://localhost:3000/api/v1/version -u "zio:Zio@Admin2026!"

# [npm build] 실패 → node_modules 재설치
cd /opt/zioinfo/src/frontend && rm -rf node_modules && npm install --legacy-peer-deps

# [mvn package] 실패 → Maven 캐시 클리어
cd /opt/zioinfo/src/backend && mvn clean -q

# Step 3: 수동 배포 실행
cd /opt/zioinfo/src
git pull origin main
cd frontend && npm ci && npm run build
cd ../backend && mvn clean package -DskipTests -q
cp target/zioinfo-web-*.jar /opt/zioinfo/app/app.jar
cp -r src/main/resources/static/. /var/www/zioinfo/
systemctl restart zioinfo

CASE 6: Gitea 접속 불가 (포트 3000)

증상: http://zioinfo.co.kr:3000 접속 불가

# Step 1: 서비스 상태
systemctl status gitea
journalctl -u gitea -n 20 --no-pager

# Step 2: PostgreSQL 확인 (Gitea DB 의존)
systemctl is-active postgresql

# Step 3: 재시작
systemctl restart gitea
sleep 5
curl -s -o /dev/null -w "Gitea: HTTP %{http_code}\n" http://localhost:3000/

CASE 7: 서버 메모리 부족 (OOM)

증상: 서비스 갑자기 종료, journalctl에서 OOM killer 메시지

# Step 1: 메모리 현황
free -h
dmesg | grep -i "oom" | tail -10

# Step 2: 메모리 사용량 상위 프로세스
ps aux --sort=-%mem | head -10

# Step 3: Ollama가 주요 원인 (4.7GB 점유)
# 사용 안 할 때 중지
systemctl stop ollama

# Step 4: 필수 서비스 재시작
for s in nginx zioinfo guardia postgresql gitea; do
    systemctl is-active $s || systemctl start $s
done

# Step 5: 임시 스왑 설정 (재부팅 시 사라짐)
[ ! -f /swapfile ] && {
    fallocate -l 2G /swapfile
    chmod 600 /swapfile
    mkswap /swapfile
    swapon /swapfile
    echo "2GB 스왑 설정 완료"
}
free -h

CASE 8: 디스크 용량 부족

증상: 로그 쓰기 실패, DB 오류

# Step 1: 디스크 현황
df -h
du -sh /var/log/* 2>/dev/null | sort -rh | head -10
du -sh /opt/* 2>/dev/null | sort -rh | head -10

# Step 2: 로그 정리
# journald 로그 정리
journalctl --vacuum-size=500M

# Nginx 로그 압축
gzip /var/log/nginx/access.log.1 2>/dev/null
gzip /var/log/nginx/error.log.1 2>/dev/null

# 오래된 배포 로그 정리
find /var/log/zioinfo -name "*.log" -mtime +30 -delete

# Maven 캐시 정리 (~/.m2)
rm -rf /var/lib/jenkins/.m2/repository/*/

# npm 캐시 정리
npm cache clean --force 2>/dev/null

# Step 3: PostgreSQL 로그 정리
find /var/log/postgresql -name "*.log" -mtime +7 -delete

# Step 4: 확인
df -h

CASE 9: Jenkins 응답 없음 (포트 8080)

# Step 1: 상태 확인
systemctl status jenkins
curl -s -o /dev/null -w "Jenkins: HTTP %{http_code}\n" http://localhost:8080/

# Step 2: 재시작
systemctl restart jenkins
sleep 10
systemctl is-active jenkins

# Step 3: Java 힙 부족 시 메모리 조정
# /etc/default/jenkins 편집
echo 'JAVA_ARGS="-Xmx512m -Xms256m"' >> /etc/default/jenkins
systemctl restart jenkins

CASE 10: SSH 접속 불가

# 다른 방법으로 접속 (NCloud 콘솔에서 시리얼 콘솔 사용)
# 또는 NCloud 포털 → 서버 → 콘솔 접속

# SSH 서비스 재시작 (서버 콘솔에서)
systemctl restart sshd
systemctl is-active sshd

# 방화벽 SSH 허용 확인
ufw allow 22/tcp
ufw status | grep 22

3. 서버 재부팅 후 복구 절차

# 재부팅 후 전체 서비스 자동 시작 확인
systemctl list-units --type=service --state=failed

# 실패한 서비스가 있을 경우 개별 재시작
systemctl start <서비스명>

# 모든 서비스 한번에 시작
for s in postgresql gitea nginx zioinfo zioinfo-deploy guardia ollama jenkins; do
    systemctl is-active $s || {
        echo "Starting $s..."
        systemctl start $s
        sleep 2
    }
done

# 전체 헬스체크
echo "=== 재부팅 후 헬스체크 ==="
curl -s -o /dev/null -w "홈페이지:    HTTP %{http_code}\n" http://localhost/
curl -s -o /dev/null -w "API:         HTTP %{http_code}\n" http://localhost/api/company
curl -s -o /dev/null -w "GUARDiA:     HTTP %{http_code}\n" http://localhost:8001/docs
curl -s -o /dev/null -w "Gitea:       HTTP %{http_code}\n" http://localhost:3000/
curl -s -o /dev/null -w "Jenkins:     HTTP %{http_code}\n" http://localhost:8080/

4. 정기 점검 체크리스트

#!/bin/bash
# 주 1회 실행 권장
echo "===== zio-server 정기 점검 ====="
echo "점검일: $(date)"
echo ""

echo "[ 서비스 상태 ]"
for s in nginx zioinfo zioinfo-deploy guardia gitea jenkins postgresql ollama; do
    status=$(systemctl is-active $s)
    printf "  %-20s %s\n" $s $status
done

echo ""
echo "[ 리소스 현황 ]"
echo "  디스크: $(df -h / | tail -1 | awk '{print $3"/"$2" ("$5")"}')"
echo "  메모리: $(free -h | grep Mem | awk '{print $3"/"$2}')"
echo "  스왑:   $(free -h | grep Swap | awk '{print $3"/"$2}')"

echo ""
echo "[ 응답 테스트 ]"
for url in \
    "http://localhost/:홈페이지" \
    "http://localhost/api/company:API" \
    "http://localhost:8001/docs:GUARDiA" \
    "http://localhost:3000/:Gitea" \
    "http://localhost:8080/:Jenkins"; do
    url_part="${url%%:*}"
    name="${url##*:}"
    code=$(curl -s -o /dev/null -w "%{http_code}" "$url_part" 2>/dev/null)
    icon="✅"; [[ "$code" != "200" && "$code" != "302" ]] && icon="❌"
    printf "  %s %-12s HTTP %s\n" "$icon" "$name" "$code"
done

echo ""
echo "[ 최근 에러 로그 (1시간) ]"
journalctl -p err --since "1 hour ago" --no-pager 2>/dev/null | grep -v "^--" | tail -5 || echo "  없음"

echo ""
echo "[ Gitea 저장소 ]"
curl -s http://localhost:3000/api/v1/repos/search -u "zio:Zio@Admin2026!" 2>/dev/null | \
    python3 -c "import json,sys; [print('  '+r['full_name']) for r in json.load(sys.stdin)['data']]" 2>/dev/null

echo ""
echo "[ PostgreSQL DB 상태 ]"
sudo -u postgres psql -c "\l" 2>/dev/null | grep -E "(guardia|gitea|zioinfo)" | awk '{print "  "$1}'

echo "============================="

5. 긴급 연락처 및 에스컬레이션

단계 담당 연락처 조건
L1 운영팀 서비스 재시작으로 해결 가능
L2 개발팀 코드/설정 변경 필요
L3 NCloud 지원 1544-5117 서버 하드웨어/네트워크 장애

문서 버전: 1.0 | 최종 수정: 2026-05-30