오늘 하루 동안 홈랩 K3s 클러스터 위에 SENTINEL을 올렸다. 반도체 팹이 설비 데이터를 다루는 방식을 축소해서 흉내 낸 감시 시스템이다. 경보가 울리면 AI 에이전트가 원인을 여섯 종류로 나누고, 분류 카드를 텔레그램으로 보낸다.

결론부터 적으면 이렇다.

  • 센서 노드는 무선 노드 두 대다. 가속도계·자이로·배터리가 달린 삼성 노트북(louise)과 2011년형 맥미니(solomon)다. 여기에 클러스터 안의 SK하이닉스 Gold P31 SSD와 ECC 메모리를 “반도체 제품 자체의 건강 신호”로 붙였다.
  • 탐지는 세 층이다. 빠른 이상(FDC), 느린 드리프트(예지 정비), 오래 지속되는 나쁜 상태(고정 규칙)다. 층을 나눈 이유는 지난주에 1시간 창 모델이 느린 과부하를 놓친 일 때문이다.
  • 에이전트는 경보 이름을 믿지 않는다. 운영 데이터로 처음 돌렸을 때 가상 경보 4건 중 3건을 틀렸다. 전부 이름만 보고 판단한 탓이었다. 그래서 “경보 조건이 증거에서 다시 확인되는가”를 첫 단계로 넣었다.

1. 왜 이걸 만들었나

반도체 팹에는 설비 데이터를 다루는 대표적인 일이 세 가지 있다.

팹의 일 뜻 SENTINEL의 축소판
FDC (Fault Detection & Classification) 공정 중 센서 신호가 평소와 다른지 바로 잡고, 원인별로 분류 충격·정전·과열을 잡고 에이전트가 원인을 분류
예지 정비 며칠~몇 주에 걸쳐 설비가 서서히 나빠지는 걸 미리 잡기 2주 기준선 대비 온도·신호·배터리 드리프트
메모리 신뢰성 DRAM·NAND가 현장에서 어떻게 고장 나는지 ECC 오류 카운터, SK하이닉스 NVMe 온도

이 표의 팹 쪽 설명은 일반적인 업계 개념이다. 특정 회사의 내부 방식은 모른다.

센서 정밀도는 비교가 안 된다. 노트북 IMU는 10 Hz라 실제 설비 진동(kHz 대역)은 볼 수 없다. 이 프로젝트가 보여 주려는 건 센서가 아니라 파이프라인이다. 수집하고, 층별로 탐지하고, 에이전트가 분류하고, 사람이 승인하고, 정답이 있는 평가로 검증하는 흐름 전체다.

2. 실측부터 — 클러스터 안에 뭐가 있나

설계 전에 노드마다 SSH로 들어가 읽기만 해서 확인했다.

노드 하드웨어 쓸 수 있는 신호
louise 삼성 950SBE 노트북 가속도·자이로·경사·자세·힌지 센서(IIO, 10 Hz), 배터리(사이클 116회), Wi-Fi
solomon Apple Macmini5,1 CPU 온도, USB Wi-Fi 동글
ilwon 데스크톱 SK하이닉스 Gold P31 1TB 온도(위험 임계 83.85 °C)
isagal Dell R730xd Registered DDR4 ECC, 메모리 컨트롤러 2개의 CE/UE 카운터

두 가지를 새로 알았다. 첫째, 맥미니를 2014년형으로 알고 있었는데 DMI에는 Macmini5,1, 곧 2011년 모델로 나온다. 둘째, 블로그에 “6노드 전부 무선”이라고 적은 적이 있는데, 지금은 두 노드가 본딩의 활성 슬레이브로 유선을 쓰고 있다. 기록과 실제는 자주 어긋난다. 그래서 늘 실측부터 한다.

3. 1주차 — 수집기

파이썬 표준 라이브러리만 쓰는 수집기 하나를 만들었다. 노드에 있는 센서만 자동으로 켠다. 신호 그룹은 여섯 개다. IMU, 전원, Wi-Fi, 온도, NVMe, ECC.

IMU는 0.2초마다 읽어서 60초 창으로 요약한다. 요약 값은 다섯 가지다.

  • 중력을 뺀 진동 RMS와 최댓값
  • 충격 횟수. 정지 노이즈의 약 25배인 0.4 m/s²를 넘을 때 센다(가속도계 글).
  • 기준 자세에서 기울어진 각도
  • 값이 멈춘 최대 샘플 수. 센서 고장을 판별하는 데 쓴다.

돌려 보면서 고친 것이 셋 있다.

  • 샘플이 10초에 32개밖에 안 나왔다. 매번 보정값 파일까지 다시 읽은 탓이었다. 보정값을 한 번만 읽게 캐시하고 주기를 맞추자 1분에 약 300개로 늘었다.
  • 맥미니 내장 Wi-Fi가 0 dBm, -5 dBm 같은 불가능한 신호값을 낸다. 규칙은 실제로 트래픽이 나가는 인터페이스만 보게 했다.
  • Prometheus 연결 방식을 바꿨다. 원래는 node-exporter의 textfile 방식을 쓰려 했다. 노드마다 root로 디렉터리를 만들어야 하는데, 원격 에이전트 세션에서는 sudo 실행이 허용되지 않았다. 그래서 수집기가 노드 LAN IP에 직접 포트를 열고 Prometheus가 가져가게 했다. 인증이 없는 포트이지만, 내보내는 값은 온도·신호 세기·부품 모델명뿐이다.

이 단계에서 층3 고정 규칙 16개를 올렸다. 정전, 충격, 기울어짐, 센서 멈춤, NVMe 과열, ECC 오류, 무선 열화, 배터리 열화 같은 것들이다. 규칙마다 원인 분류 라벨을 붙여 두었다. 적용하기 전에는 Prometheus 컨테이너 안의 promtool로 문법을 검사했다.

4. 2주차 — 원인 분류 에이전트

경보 하나가 들어오면 에이전트는 이렇게 처리한다.

  1. 증거 수집. Prometheus 조회만 쓴다. 경보 전 15분 동안의 노드 신호 20개와 클러스터 신호 2개를 요약한다.
  2. 규칙 분류. 여섯 종류 중 하나로 나눈다.
    • 설비 이상
    • 전원 이상
    • 메모리·스토리지 이상
    • 환경·통신 이상
    • 센서 자체 이상
    • 정상 변동
  3. LLM 분류(선택). 결과는 스키마로 검증한다.
  4. 카드 발송. 조치는 제안만 하고 실행하지 않는다.

센서 자체 이상을 따로 둔 게 핵심이다. 팹 FDC에서도 “설비가 고장 났나, 센서가 고장 났나”를 가르는 게 중요하다. 실제로 이 노트북 가속도계는 값이 8초 동안 멈춘 적이 있다. 판별 예시는 이렇다.

  • 충격과 AC 분리가 같은 창에 있으면 전원 이상이다. 케이블을 뽑다가 흔들린 것이다.
  • 가속도 값이 멈췄거나 정지 중력이 9.0~10.6 m/s² 범위를 벗어나면 센서 이상이다.
  • 여러 노드가 동시에 과열되면 환경 이상이다. 실내 온도 같은 공통 원인을 뜻한다.

LLM 경로에는 WATCHMAN과 같은 안전장치를 걸었다.

  • 분류는 정해진 여섯 값만 받는다.
  • 근거는 실제로 수집했고 값이 있는 증거 키만 인용할 수 있다. 수집하지 않은 키를 대면 거부한다.
  • 허용 목록 밖의 조치는 버린다.
  • 두 번 검증에 실패하면 규칙 분류로 폴백한다.

운영 데이터가 잡아 준 버그

평가 시나리오로는 규칙 분류가 전부 맞았다. 그런데 운영 Prometheus에 붙여 가상 경보 4건을 넣자 3건이 틀렸다.

가상 경보 실제 증거 처음 분류
NVMe 과열 53 °C (기준 70 °C) 메모리 이상 ✗
ECC 정정 가능 오류 증가 0건 메모리 이상 ✗
수집기 다운 정상 응답 중 센서 이상 ✗

셋 다 경보 이름만 보고 판단한 탓이었다. 그래서 첫 단계에 재현 검사를 넣었다. 경보 조건이 증거 창에서 다시 확인되지 않으면, 라벨과 상관없이 정상 변동이다. 같은 유형의 시나리오도 평가에 추가했다.

평가는 정답이 붙은 시나리오 24종에 변형을 3개씩 줘서 72건을 돌렸다. 규칙 분류는 72/72를 맞혔다. 하지만 규칙과 시나리오를 같은 사람이 만들었으니 이 숫자는 회귀 검증일 뿐이다. 의미 있는 숫자는 LLM 정확도와 실제 사건에서 나온다. 둘 다 아직 없다(7절).

5. 층2 — 느린 드리프트

최근 24시간 평균을 “1일 전~15일 전” 평균·표준편차와 비교한다. z > 3 상태가 6시간 이어지면 경보다. 대상은 CPU·NVMe 온도, 무선 신호, 배터리 건강도의 7일 기울기다.

  • 계산 비용 줄이기. 14일 범위를 매 평가마다 계산하면 무겁다. 그래서 5분 간격으로 노드당 시계열 하나만 기록하고, 통계는 그 기록 위에서 낸다.
  • 이력이 짧을 때는 조용히. 이력이 7일 미만이면 경보를 내지 않는다. 수집을 오늘 시작했으니 10월 초부터 의미가 생긴다.
  • 드리프트도 분류가 갈린다. 한 노드만 서서히 나빠지면 그 설비나 부품 문제다. 여러 노드가 같이 나빠지면 공통 환경 문제다.

한계도 실측으로 이미 안다. 높은 상태가 며칠 계속되면 기준선이 따라 올라가서 경보가 멈춘다(르무엘 사례). 그 뒤는 층3 고정 규칙이 받는다. 세 층으로 나눈 이유가 바로 이것이다.

6. 배포와 알람 배선

에이전트는 클러스터 안에 올렸다. 구성은 이렇다.

  • 컨테이너: 비루트, 읽기 전용 파일시스템, 모든 capability 제거
  • 네트워크: Alertmanager에서만 들어오고, Prometheus·DNS·텔레그램(공인 IP 443)으로만 나간다
  • 웹훅 토큰: 새로 생성해 곧바로 sops로 암호화했다. 평문은 화면에도 디스크에도 남지 않았다.

Alertmanager 라우팅을 바꾸면서 amtool이 사고 하나를 막아 줬다. Sentinel 경보의 복사본만 에이전트로 보내려고 continue: true 라우트를 추가했다. 그런데 테스트해 보니 warning 경보가 기존 WATCHMAN 경로로 가지 않게 됐다. Alertmanager는 자식 라우트가 하나라도 매칭되면 루트의 기본 receiver를 쓰지 않기 때문이다. 기존 경로를 라우트로 명시해서 해결했다. 배포 전에 경보 종류별 라우팅 결과를 전부 찍어 보고, 이전과 같은지 확인한 뒤에 push했다.

마지막으로 critical 경보(정전 등)는 분류 카드만 받게 했다. 원문 알람까지 오면 같은 사건이 두 통씩 오기 때문이다. 대신 원문 경로를 뺀 만큼 바닥을 다시 깔았다.

  • 에이전트 다운 알람. 에이전트가 3분 넘게 떠 있지 않으면 critical 원문으로 알린다. 이름을 AgentDownSentinel로 지은 데는 이유가 있다. “Sentinel”로 시작하면 이 알람 자체가 죽은 에이전트에게 배달된다.
  • 카드 재시도. 발송이 실패하면 5초 뒤, 20초 뒤에 다시 보낸다.
  • critical은 전송 상한에서 제외. 시간당 20통 상한이 있지만 critical 카드는 막지 않는다.
  • 정상 변동 카드는 무음. 오탐으로 분류된 카드는 알림음 없이 온다.

7. 아직 못 한 것

  • LLM 분류 평가. 클러스터 안의 소형 모델(nemotron-nano-4b)은 40토큰짜리 응답이 200초 안에 오지 않았다. 게이트웨이 모델로 평가할 스크립트는 준비해 뒀고, 키 승인을 기다리는 중이다.
  • 실제 정전 테스트. AC를 뽑고 노드 sysfs 시각을 기준으로 탐지 지연을 재는 스크립트는 만들어 뒀다. 지연은 수집 60초, 스크레이프 60초, 규칙 평가 60초가 쌓여 최대 약 3분으로 예상한다. 5초마다 확인하는 기존 정전 감지기와 비교할 예정이다.
  • SSD 마모율(SMART). root 권한이 필요해서 뺐다.

하루를 돌아보며

오늘 가장 값진 순간은 테스트가 다 통과했을 때가 아니었다. 운영 데이터가 테스트를 틀렸다고 말해 준 순간이었다. 평가 72/72가 나온 분류기가, 실제 Prometheus에 붙자마자 4건 중 3건을 틀렸다. 라우팅도 마찬가지다. 설정 파일로는 맞아 보였지만, amtool로 경보마다 경로를 찍어 보자 WATCHMAN 경로가 빠진 게 드러났다.

AI 에이전트를 운영에 붙일 때도 결국 같은 원칙으로 돌아온다. 경보 이름도, 모델의 답도, 내 설정 파일도 믿지 말고 증거로 다시 확인한다.

References