콘텐츠로 이동

AI & 자가치유

PureCVisor AI Agent는 복수의 AI 프로바이더에 동시 질의하여 합의(consensus) 기반으로 의사결정한다.

프로바이더용도설정
Claude (Anthropic)범용 분석API Key + 모델 고정
OpenAI범용 분석API Key + 모델 고정
Gemini (Google)범용 분석API Key
Ollama로컬 추론엔드포인트 URL

프로바이더별 가중치를 부여하여, 가중 합산이 60% 초과 시 합의 성립.

Terminal window
# AI Agent 설정
pcvctl agent config
# 프로바이더 설정
pcvctl agent set --provider claude --api-key "sk-ant-..." --weight 0.3
pcvctl agent set --provider openai --api-key "sk-..." --weight 0.3
pcvctl agent set --provider ollama --endpoint "http://localhost:11434" --weight 0.2
pcvctl agent set --provider gemini --api-key "AI..." --weight 0.2
# 합의 이력
pcvctl agent history

정책별로 dry-run 모드를 설정하여 실제 실행 없이 의사결정 결과만 확인.

anomaly_detector.c에서 Z-Score 기반 이상 탐지를 수행한다.

Z = (현재값 - 평균) / 표준편차
|Z| > 3.0 이면 이상(anomaly) 판정

기준선 리셋 (v1.0): 배포/유지보수 후 기준선을 수동 리셋하여 오탐을 방지.

Terminal window
# RPC — 기준선 리셋
echo '{"jsonrpc":"2.0","method":"ai.baseline.reset","params":{},"id":"1"}' \
| nc -U /var/run/purecvisor/daemon.sock
Layer 5: 승인 큐 — 승인이 필요한 액션은 관리자 승인 대기
Layer 4: Rate Limit — 5분 내 최대 3개 자동 액션 (alert_only 제외)
Layer 3: 쿨다운 — VM은 정책·대상별, 호스트 알림은 정책별 최소 간격
Layer 2: 합의 검증 — 4-프로바이더 가중 쿼럼 60%+
Layer 1: 정책 매칭 — 사전 정의된 치유 정책

self-healing CPU 알림은 호스트 CPU 이상 또는 예측 부하에 대한 cpu-overload 정책의 alert_only 기록입니다.
CPU를 강제로 제한하거나 VM을 재시작하는 지시가 아닙니다.
기본 [ai].modedry_run이므로 판단을 로그·감사·치유 이력에 기록합니다.
active에서도 CPU·메모리 정책의 액션은 alert_only입니다.

정책이상 이벤트 입력의 Z-score 하한5분 뒤 사용률 예측 조건액션쿨다운
cpu-overload3.0CPU 예측값 > 85%alert_only600초
mem-pressure2.5메모리 예측값 > 90%alert_only600초

이상 이벤트와 예측은 별도 진입 경로입니다.
85%·90%는 현재 사용률의 고정 알림 임계값이 아니라 예측 경로의 조건이며, 이상 이벤트는 수집·학습과 탐지 조건을 먼저 통과해야 합니다.

2026-09-15 공개 수정부터 호스트 정책은 실제 첫 발동 여부를 따로 저장합니다.
조건에 맞는 첫 이벤트는 부팅 후 600초 이내에도 기록하며, 이후 같은 정책의 반복은 600초 동안 억제합니다.
CPU와 메모리는 서로의 쿨다운을 소비하지 않습니다.
이 수정이 이상탐지의 초기 학습 시간을 없애지는 않습니다.
VM 대상 정책의 쿨다운은 기존처럼 정책·VM 조합별로 유지합니다.

실제 VM 재시작은 대상이 지정된 vm-unresponsive의 별도 restart 정책과 실행 모드·안전 가드를 따릅니다.
CPU 알림을 자동 vCPU 증설, 메모리 balloon 조정이나 스냅샷 정리 완료로 해석하지 않습니다.

위험도가 높은 자가치유 액션은 자동 실행하지 않고 승인 큐에 등록한다.
1시간 이내에 승인/거부하지 않으면 자동 만료.

Terminal window
# 승인 대기 목록
echo '{"jsonrpc":"2.0","method":"ai.approval.list","params":{},"id":"1"}' \
| nc -U /var/run/purecvisor/daemon.sock
# 승인
echo '{"jsonrpc":"2.0","method":"ai.approval.approve","params":{
"action_id":"heal-001"
},"id":"1"}' | nc -U /var/run/purecvisor/daemon.sock
# 거부
echo '{"jsonrpc":"2.0","method":"ai.approval.reject","params":{
"action_id":"heal-001"
},"id":"1"}' | nc -U /var/run/purecvisor/daemon.sock

Web UI에서도 approve/reject 가능 (v1.0).

12.5 per-VM 압력(PSI) 연결 (2.0.0, NXV-F1/F2)

섹션 제목: “12.5 per-VM 압력(PSI) 연결 (2.0.0, NXV-F1/F2)”

per-VM PSI 연결 전의 이상탐지는 /proc/pressure/*노드 전역 PSI만 봤다.
그래서 VM 한 대가 메모리에 굶어도 호스트 평균이 낮으면 놓쳤고(미탐), 무관한 부하가 평균을 밀어 올리면 멀쩡한 VM이 범인이 됐다(오탐).
2.0.0 현행 정본은 cgroup 단위로 PSI를 수집해 이 사각을 없앤다.

  • 수집 범위: machine.slice(qemu/libvirt-lxc/nspawn)와 lxc 두 레이아웃을 깊이 1 고정으로 스캔해 비용을 상수화한다.
    항목 상한은 64이며, 초과분은 조용히 자르지 않고 truncated 게이지 + WARN(300초 스로틀)으로 드러낸다.
  • 라벨 방어: 게스트 이름은 사용자 입력이다.
    systemd 이스케이프를 디코드한 뒤 제어문자·DEL·"·\가 섞여 있으면 그 항목을 거부한다(잘라 쓰지 않는다 — 잘린 이름은 다른 게스트와 충돌한다).
  • 정리: 사라진 게스트의 라벨은 기존 TTL 5분 sweep이 걷어간다.
  • 노드 전역 수집은 그대로다.
    기존 대시보드 의존은 변하지 않는다.

여기서 붙는 vm_name 라벨을 이상탐지가 읽어 치유 액션에 target_vm으로 넘긴다.
그 결과 자가치유가 “호스트 어딘가”가 아니라 대상 VM을 지목해 판단할 수 있게 됐다.

  • 자동 watch 등록/회수: 매 주기 mark → discover → sweep.
    새 시계열이 보이면 등록하고, 3주기 연속 보이지 않을 때만 회수한다(1주기 결손으로 지우면 5분치 학습분이 날아가고 워밍업으로 되돌아간다).
    렌더 결과를 한 번도 못 읽은 주기는 동기화를 아예 건너뛴다 — “못 봤다”를 “사라졌다”로 읽으면 레지스트리 일시 장애 한 번에 전 VM 감시가 회수되기 때문이다.
  • 슬롯: 자동 64 + 고정 예약 16 = 80. 고정 감시 10건이 자동 등록에 밀려나지 않음이 컴파일 시점 불변식(static_assert)으로 고정돼 있다.
  • 정책: vm-mem-pressure가 추가됐고 alert_only이다.
    restart·migrate처럼 게스트에 영향을 주는 액션은 넣지 않았다 — 자동 조치로의 승격은 운영 결정이며 별도 선행 조건이 있다.

알림 라벨은 WS 브로드캐스트와 최근 이벤트 JSON에 실릴 때 이스케이프된다.
라벨 값에 원시 "가 들어가 수신측 JSON.parse가 실패하던 알림 유실은 같은 2.0.0 시정 묶음에서 해소됐다.