# zio-server 장애 대응 가이드 (Runbook) > **서버**: zio-server | **IP**: zioinfo.co.kr > **작성일**: 2026-05-30 > **목적**: 장애 발생 시 빠른 진단과 복구를 위한 단계별 절차서 --- ## 긴급 연락 및 접속 ```bash # 즉시 서버 접속 ssh -i "zio-server-key.pem" root@zioinfo.co.kr # 또는 ssh root@zioinfo.co.kr # 비밀번호: 1q2w3e!Q ``` --- ## 1. 빠른 현황 진단 (첫 번째로 실행) ```bash #!/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 오류 ```bash # 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 오류 ```bash # 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` 접속 불가 ```bash # 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 연결 실패 로그 ```bash # 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` 후 변경 내용이 적용되지 않음 ```bash # 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` 접속 불가 ```bash # 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 메시지 ```bash # 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 오류 ```bash # 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) ```bash # 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 접속 불가 ```bash # 다른 방법으로 접속 (NCloud 콘솔에서 시리얼 콘솔 사용) # 또는 NCloud 포털 → 서버 → 콘솔 접속 # SSH 서비스 재시작 (서버 콘솔에서) systemctl restart sshd systemctl is-active sshd # 방화벽 SSH 허용 확인 ufw allow 22/tcp ufw status | grep 22 ``` --- ## 3. 서버 재부팅 후 복구 절차 ```bash # 재부팅 후 전체 서비스 자동 시작 확인 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. 정기 점검 체크리스트 ```bash #!/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*