5.4 KiB
5.4 KiB
| name | description |
|---|---|
| dr-automation | GUARDiA DR(재해복구) 자동화 구현 스킬. DR 시나리오 관리, Failover 실행, 백업 무결성 검증, 복구 테스트, RTO/RPO 추적 기능을 FastAPI + paramiko 패턴으로 구현한다. 다음 상황에서 반드시 사용: (1) 'DR 구현', '재해복구', 'Failover', 'RTO/RPO' 관련 요청; (2) dr.py 라우터 또는 core/dr_engine.py 작업; (3) 백업 무결성 검증, 복구 테스트 구현; (4) DR 대시보드 구현; (5) 다시 실행, 업데이트, 보완 요청. paramiko SSH 패턴과 SQLAlchemy async 패턴을 따른다. |
DR 자동화 구현 스킬
구현 대상 파일
itsm/core/dr_engine.py— DR 비즈니스 로직itsm/routers/dr.py— FastAPI 라우터
핵심 구현 원칙
- Fail-Safe 시퀀스: 스냅샷 → 대기서버 활성화 → 서비스 전환 → 헬스체크 → 롤백(실패 시)
- 자격증명 보호: paramiko 접속 시 IP/계정 노출 금지, AES 복호화 후 메모리만 사용
- 비동기: asyncio.create_subprocess_exec + paramiko를 run_in_executor로 래핑
- 감사 기록: 모든 DR 작업은 tb_audit_log에 기록
DB 모델 (models.py에 추가)
class DRScenario(Base):
__tablename__ = "tb_dr_scenario"
id = Column(Integer, primary_key=True)
name = Column(String(100), nullable=False)
scenario_type = Column(String(30)) # SITE_FAILURE | SERVER_FAILURE | DATA_CORRUPTION
primary_server_id = Column(Integer, ForeignKey("tb_server_info.id"))
standby_server_id = Column(Integer, ForeignKey("tb_server_info.id"))
rto_minutes = Column(Integer) # 목표 RTO (분)
rpo_minutes = Column(Integer) # 목표 RPO (분)
failover_steps = Column(JSON) # 페일오버 실행 단계 목록
healthcheck_url = Column(String(255))
last_test_at = Column(DateTime)
last_test_result = Column(String(20)) # PASS | FAIL | PARTIAL
is_active = Column(Boolean, default=True)
created_at = Column(DateTime, default=func.now())
class DRTest(Base):
__tablename__ = "tb_dr_test"
id = Column(Integer, primary_key=True)
scenario_id = Column(Integer, ForeignKey("tb_dr_scenario.id"))
test_type = Column(String(20)) # BACKUP_VERIFY | FAILOVER_SIM | RECOVERY
status = Column(String(20)) # RUNNING | PASS | FAIL | PARTIAL
rto_actual = Column(Integer) # 실제 RTO (분)
rpo_actual = Column(Integer) # 실제 RPO (분)
result_detail = Column(JSON) # 단계별 결과
started_at = Column(DateTime, default=func.now())
completed_at = Column(DateTime)
triggered_by = Column(String(100))
core/dr_engine.py 구현 패턴
import asyncio, hashlib, time
from datetime import datetime
from typing import Optional
import paramiko
from sqlalchemy.ext.asyncio import AsyncSession
from core.ssh_exec import _get_server_credentials # 기존 AES 복호화 함수 재사용
from models import DRScenario, DRTest, Server
class DREngine:
async def verify_backup(self, db: AsyncSession, server_name: str) -> dict:
"""백업 파일 무결성 검증 (SHA-256 체크)."""
# 1. 서버 정보 조회 (ip_addr, ssh_user, os_pw_enc)
# 2. AES 복호화로 자격증명 획득
# 3. paramiko SSH 접속
# 4. backup_path 하위 최신 파일 SHA-256 계산
# 5. 결과 반환 (파일명, 크기, 해시, 경로 미노출)
...
async def run_recovery_test(self, db: AsyncSession, scenario_id: int,
triggered_by: str) -> DRTest:
"""복구 테스트 실행."""
# 1. 시나리오 조회
# 2. DRTest 레코드 생성 (status=RUNNING)
# 3. failover_steps 순서대로 SSH 명령 실행
# 4. 각 단계 결과 result_detail에 누적
# 5. healthcheck_url 응답 확인
# 6. RTO 계산 (started_at ~ 헬스체크 성공)
# 7. DRTest status 업데이트 (PASS/FAIL/PARTIAL)
...
def calculate_rto_rpo(self, tests: list[DRTest]) -> dict:
"""최근 5회 테스트 기반 RTO/RPO 통계."""
...
routers/dr.py 엔드포인트 구조
GET /api/dr/scenarios 목록 (ENGINEER 이상)
POST /api/dr/scenarios 등록 (ADMIN 전용)
GET /api/dr/scenarios/{id} 상세
PUT /api/dr/scenarios/{id} 수정 (ADMIN 전용)
POST /api/dr/test 복구 테스트 실행 (ENGINEER 이상)
GET /api/dr/test/{id} 테스트 결과 조회
GET /api/dr/tests 테스트 이력 목록
POST /api/dr/backup-verify 백업 무결성 검증 (ENGINEER 이상)
POST /api/dr/failover/{scenario_id} Failover 실행 (ADMIN 전용, 승인 필요)
GET /api/dr/rto-rpo RTO/RPO 현황 대시보드
GET /api/dr/dashboard DR 전체 현황
보안 규칙
- Failover 실행은
require_admin_role의존성 필수 - 백업 검증은 ENGINEER 이상 허용
- 서버 IP/경로를 API 응답 body에 포함하지 않는다
- SSH 자격증명은
core/ssh_exec.py의 기존 AES 복호화 함수 재사용
헬스체크 URL 검증 방법
import httpx
async with httpx.AsyncClient(verify=False, timeout=10) as client:
resp = await client.get(scenario.healthcheck_url)
return resp.status_code == 200