Skip to content

Monitoring KO

elecbug edited this page Oct 12, 2026 · 17 revisions

모니터링·접근 로그·연결 진단

Wiki home › 한국어 문서 · 영어 원문

문서 안내 · 소스 저장소

Swarm 배포 가이드에 따라 stack을 배포하십시오. Controller, 선택한 노드마다 Agent 하나, Prometheus와 Grafana를 실행하며 데이터 소스와 KP2PLab Experiment Analysis 대시보드는 자동 등록됩니다. sh scripts/swarm.sh access로 control 노드의 게시 주소를 확인하십시오. 아래 예제의 control-node는 해당 호스트 주소로 바꿉니다.

대시보드는 영어로 작성되어 있으며, Swarm stack은 GF_USERS_DEFAULT_LANGUAGE=en-US로 Grafana UI 기본 언어를 영어로 설정합니다. 사용자나 조직의 언어 설정이 있으면 해당 UI 기본값보다 우선합니다. Grafana 언어 설정 문서

Grafana는 최초 실행 시 SQLite 데이터베이스를 초기화하므로 디스크 성능에 따라 준비까지 수 분이 걸릴 수 있습니다. sh scripts/swarm.sh logs grafana에서 초기화 진행 상황을 확인할 수 있으며, 이후 시작에서는 기존 데이터베이스를 사용합니다.

로컬 SQLite 데이터베이스에는 WAL 모드를 사용합니다. 데이터베이스와 WAL 파일은 같은 Grafana named volume에 보존됩니다. Grafana 데이터베이스 설정

화면 기본 주소
KPL Dashboard http://control-node:8080
Grafana 실험 분석 http://control-node:3000/d/kpl-experiments
Prometheus 쿼리/수집 상태 http://control-node:9090
Controller 지표 원문 http://control-node:8080/metrics

Swarm stack은 Grafana 익명 접속을 비활성화하고 GRAFANA_ADMIN_PASSWORD를 필수로 요구합니다. 설정 helper가 manager 설정에 자격 증명을 저장하며 sh scripts/swarm.sh credentials로 설정된 로그인 정보를 확인할 수 있습니다. 이 stack은 시작할 때 원래 Grafana 관리자 비밀번호를 설정값으로 동기화하며 기존 사용자명과 데이터는 유지합니다.

Swarm은 Prometheus/Grafana 포트를 control 노드에 게시합니다. 각 Agent의 전용 metrics listener도 해당 노드의 KPL_AGENT_METRICS_PORT(기본 9091)로 게시합니다. scripts/swarm.sh configure로 PROMETHEUS_PORT, GRAFANA_PORT 또는 Agent metrics 포트를 변경한 뒤 다시 배포해 적용하십시오.

대시보드 상단 메뉴는 Prometheus와 Grafana를 새 탭으로 엽니다. 현재 Dashboard의 scheme과 호스트를 유지하고 설정된 게시 포트로 바꿉니다. 브라우저가 사용하는 포트가 설정값과 같으면 직접 접속과 SSH 터널에서 동작합니다. Proxy가 scheme/path를 바꾸거나 로컬 forwarding에 다른 포트를 쓰면 실제 모니터링 주소를 별도로 여십시오.

화면 조작은 대시보드, 실행 복구는 실험, 원본 내보내기와 백업은 저장 결과를 참고하십시오.

실행과 분석

  1. 대시보드의 Run experiment에서 examples/monitoring.yaml을 실행합니다. envelope 발행과 raw 발행을 함께 확인하는 작은 실험입니다. Run 옆 Runs를 1~100으로 지정하면 순차 반복합니다. 회차마다 별도 결과를 남기며 실패 또는 Stop batch는 나머지를 취소합니다. 실행과 반복를 참고하십시오.
  2. Grafana에서 Run(run_id), Agent, Topic을 선택합니다. 여러 run을 고르면 선택한 실험의 트래픽·지연을 합산하며, 네트워크 설정·대역폭 시계열은 범례에서 run별로 구분합니다. 세션 도달률 패널은 Run만, 대역폭·control 패널은 Topic 없이 Run과 Agent를 적용합니다.
  3. 실험이 끝난 뒤에도 시간 범위를 해당 실행 구간으로 지정하면 시계열을 볼 수 있습니다. 기본 새로고침은 5초입니다.

Prometheus는 Controller와 Agent의 /metrics를 5초마다 수집합니다. Controller가 등록된 Agent의 metrics URL을 HTTP service discovery로 반환하고, Prometheus가 service VIP 대신 각 Agent의 host-mode 포트에 직접 접근합니다. Peer를 직접 scrape하거나 각 컨테이너에 exporter를 추가하지 않습니다. Controller는 기존 Peer telemetry를 누적 집계하므로 scope: all에서 telemetry가 손실되면 Controller가 만드는 Peer 지표도 영향을 받습니다. 모니터링 서비스는 별도 Docker network에 있으며 Peer에는 추가 네트워크·권한을 부여하지 않습니다.

지표의 의미

지표 의미
kpl_events_total Controller가 수신한 이벤트 누적 수. run_id, agent_id, event_type, topic으로 구분
kpl_message_bytes_total 발행/수신 이벤트의 fields.wireBytes 합계. Envelope 사용 시 JSON/base64를 포함한 PubSub data이며 libp2p framing 및 TCP/IP 헤더 제외
kpl_p2p_stream_bytes_total, kpl_p2p_protocol_stream_bytes_total Run·Agent·방향별 실제 libp2p 스트림 누적 바이트. 전체 및 negotiated protocol별 값
kpl_p2p_stream_bits_per_second, kpl_p2p_protocol_stream_bits_per_second 소스 수집 구간의 평균 bit/s gauge. rate() 없이 직접 조회
kpl_p2p_bandwidth_sample_timestamp_seconds, kpl_p2p_bandwidth_sessions 최근 소스 표본 시각과 정상 host 종료 후 표본 수신·미수신 세션 수. 대역폭 품질과 한계 참고
kpl_gossipsub_control_rpcs_total 각 GossipSub 제어 타입을 포함한 RPC envelope 수. send, recv, 로컬 송신 전 drop으로 구분
kpl_gossipsub_control_entries_total 해당 RPC에 담긴 repeated protobuf control entry 수
kpl_gossipsub_control_message_ids_total IHAVE, IWANT, IDONTWANT entry 안의 중복 제거하지 않은 메시지 ID 참조 출현 횟수
kpl_gossipsub_control_peer_exchange_records_total PRUNE entry에 담긴 peer-exchange record 수
kpl_window_stable_pairs, kpl_window_reached_pairs 기간이 지난 메시지 중 수신 기간 전체의 구독이 증명된 수신 세션 쌍 및 기한 내 성공. run_id로 구분
kpl_window_unknown_pairs, kpl_window_missed_pairs, kpl_window_late_pairs 안정 쌍의 수신 불명·확인된 미도달. 기한 내 수신이 없는 late 수는 앞의 두 결과 중 하나와 겹침
kpl_window_delivery_ratio (bound: lower / upper) 안정 대상 조건부 도달률의 논리적 상·하한. 안정 쌍이 없으면 생략하며 신뢰구간이 아님
kpl_window_initial_pairs, kpl_window_initial_reached_pairs, kpl_window_initial_unknown_pairs 확인된 발행 시점 대상, 이탈자를 포함한 기한 내 성공, 수신 불명 수
kpl_window_initial_delivery_ratio (bound: lower / upper) 확인된 발행 시점 대상 안의 논리적 도달률 범위. 해당 집단이 비었을 때만 생략
kpl_window_stable_coverage, kpl_window_stable_coverage_upper_bound coverage 하한인 안정/확인된 발행 시점 대상과 상한인 (안정 + 지속 여부 불명)/확인된 발행 시점 대상. 확인된 집단이 비었을 때만 생략
kpl_window_departed_pairs, kpl_window_continuity_unknown_pairs 마감 전 이탈이 확인된 발행 시점 쌍과, 이탈·마감까지 지속 어느 쪽도 증명하지 못한 쌍 수
kpl_window_publication_availability_unknown_pairs, kpl_window_availability_unknown_pairs 발행 시점 생존을 증명하지 못한 후보 쌍과 발행 시점·지속 불명의 합계
kpl_window_pending_publications, kpl_window_finalized_publications 마감 전 메시지와 기간이 지난 메시지. 확정 결과도 늦은 telemetry로 정정 가능
kpl_window_measurement_incomplete, kpl_window_legacy_publications 관측된 측정 범위 불명 stream 여부(0/1)와 과거 정의 발행 수. 0도 아예 보이지 않은 telemetry는 검출하지 못함
kpl_window_propagation_latency_seconds 안정 대상의 기한 내 첫 원격 envelope 수신 지연. run_id, 수신 agent_id, topic으로 구분. raw·로컬·마감 후·이탈·불명·무효 표본 제외
kpl_window_duplicate_copies, kpl_window_duplicates_per_reached_pair 안정 대상의 원격 성공 쌍에서 기간 안에 관측한 추가 PubSub 복사본 및 성공당 평균
kpl_operation_failures_total onError: continue 정책에서 기록한 publish/leave 실패
kpl_telemetry_dropped_events_total 보고된 telemetry 유실. P2P 패킷 손실이나 미보고 유실이 0이라는 증거가 아님
kpl_nodes 실험·Agent·그룹·역할·타입·상태별 피어 수
kpl_agent_* Controller에서 관측한 Agent 상태·용량·heartbeat 및 Agent + Peer CPU/메모리 gauge
kpl_experiment_* 실험 상태, 단계, job 상태
kpl_network_configured_* starting/ready 피어의 확정 설정을 그룹별 집계. delay는 평균/최소/최대, jitter/loss는 평균
kpl_local_* 각 Agent의 로컬 피어 상태, 용량, 정리 대기, telemetry 큐 길이
go_*, process_* scrape 대상 Controller/Agent 프로세스의 런타임·CPU·메모리. Peer 컨테이너 전체 자원 사용량은 아님

kpl_network_configured_loss_ratio는 설정한 패킷 손실률이며 실제 관측 손실률이 아닙니다. 설정 delay도 실제 RTT와 구분합니다. graft/prune/remove_peer 이벤트는 PubSub mesh 변화를 분석하는 자료이며 TCP 연결 그래프나 완전한 mesh snapshot을 뜻하지 않습니다.

예약 네트워크 변경의 configured gauge는 Peer가 적용 성공을 보고한 최신 조건을 따릅니다. networkPending: "true"인 Peer는 보고 전까지 집계에서 제외합니다. 상태 보고·Agent heartbeat·Prometheus scrape만큼 관측 지연이 있으며, scope: all은 로컬 예약이 계속 동작하는 중에도 보고를 더 늦출 수 있습니다.

예약 Peer는 초기 적용과 이후 변경마다 network_config_applied에 fields.network, reference, after, revision, initial, lateByMs를 기록합니다. 초기 이벤트는 시작 조건의 적용을 확인하며 이후 이벤트는 tc 성공 직후 기록합니다. 지연은 선택한 예약 시점 기준으로 계산하며 초기 이벤트에는 초기화 시간도 포함합니다. 중간 revision을 건너뛰면 늦은 입장 또는 타이머 지연을 따라잡은 경우입니다. Clock basis·offset·uncertainty는 기존 시계 동기화 이벤트 규칙을 따릅니다. network_config_failed에는 실패한 revision·기준·예정 경과 시간·오류를 기록하고, Peer는 확인되지 않은 조건으로 계속 진행하지 않고 오류로 종료합니다. 이 이벤트는 events.jsonl에 저장합니다. 시나리오 전체가 이후 실패하는지는 readiness·publish·오류 처리 phase에도 달려 있습니다. 예약 네트워크 변경을 참고하십시오.

제어 counter는 run_id, agent_id, direction, control_type label만 사용합니다. IWANT와 IDONTWANT에는 topic이 없고 하나의 RPC가 여러 topic을 담을 수 있으므로 Topic filter는 적용하지 않습니다. send는 원격 수신이 아닌 outbound queue 수락, recv는 이후 router 정책 검사 전 관측, drop은 netem 손실이 아닌 로컬 queue/크기 거부입니다. RPC, entry, 메시지 ID 참조, PRUNE peer-exchange 수를 서로 다른 단위로 읽으십시오. RPC별 정확한 topic 수와 metrics.json의 Agent별 누적치는 결과 ZIP에 남습니다. 실험 지표 정의를 참고하십시오.

현재 관계는 Dashboard의 대화형 토폴로지가 Peer 상태 snapshot으로 transport·Kademlia 라우팅 테이블·GossipSub mesh를 각각 표시합니다. Controller는 observations.jsonl에도 표본 프로토콜 그래프를 저장하며, 이 그래프는 프로토콜 안에서 토픽 간선을 합치고 중간 전이 전부나 개별 점수 쌍을 보존하지 않습니다. Prometheus에는 이에 대응하는 전체 그래프 이력이 없습니다.

Grafana 세션 패널에는 Run 필터만 적용하고 백분율 평균이 아닌 수신 쌍 합계로 집계합니다. 범위는 관측된 집단에 대한 값이며 보이지 않는 모집단을 증명하지 않습니다. 발행 시점 가용성 경고나 measurementIncomplete가 있어도 확인된 발행 시점 도달률과 안정 coverage를 표시하며, 선택한 run 전체에 확인된 발행 시점 쌍이 하나도 없을 때만 N/A입니다. 각 집계에서 확인된 발행 시점 대상 = 안정 + 이탈 + 지속 여부 불명이 성립합니다. 과거 발행 패널은 새 결과에서 제외한 과거 데이터를 표시합니다. 새 패널은 kpl_window_*만 사용하고 이전 kpl_delivery_*·kpl_propagation_latency_seconds는 과거 의미를 유지하므로 섞지 마십시오.

전체 deliver에는 로컬 수신도 포함되므로 발행 수로 나누어 도달률을 구하지 않습니다. TCP 재전송은 패킷 손실을 지연으로 바꿀 수 있습니다. 지표 정의와 수식을 확인하십시오. 늦은 배치가 기간 gauge와 histogram 버킷을 정정할 수 있어 rate/increase 대신 직접 조회합니다. Grafana 지연은 실험 전체 누적 분위수이며 선택 시간 범위만의 분위수가 아닙니다.

누적 카운터는 최근 300개 웹 이벤트 버퍼와 독립적입니다. Controller 프로세스가 재시작되면 카운터가 초기화되며 과거 events.jsonl을 자동 재생하지 않습니다. Prometheus에 이미 저장된 시계열은 유지되고 rate/increase는 관측된 카운터 재설정을 처리합니다. 단, scrape 전에 사라진 이벤트나 telemetry 전송 실패를 복구하는 기능은 아닙니다. increase는 scrape 표본으로 추정한 구간 증가량이므로 누적 정수 이벤트 수와 항상 정확히 일치하지는 않습니다.

저장 Run을 삭제하면 Controller의 해당 이벤트 카운터, 지표 초기화 캐시, 상세 live 집계, phase 타이밍 이력과 최근 이벤트 참조를 해제합니다. 영속 삭제 표식은 재시작 후에도 늦은 telemetry나 heartbeat 초기화가 해당 카운터를 다시 만들지 못하게 합니다. 종료 Peer 인벤토리는 수명주기 차단을 위해 유지합니다. Prometheus가 이미 scrape한 표본은 자체 보존 정책에 따라 남습니다. 삭제하지 않은 완료 Run의 live 집계는 Run 삭제 또는 Controller 재시작까지 유지합니다.

KPL CPU와 메모리

KPL 사용량은 각 Agent 컨테이너와 소속 실행 중 Peer 컨테이너의 합계입니다. CPU는 Docker 호스트의 전체 논리 CPU 용량을 100%로 표시하며 공식은 100 × 사용 코어 수 / 호스트 논리 CPU 수입니다. 예를 들어 16코어 호스트에서 4코어를 사용하면 25%입니다. Agent는 Docker stats의 online_cpus 또는 구형 per-CPU 배열을 읽고, 없으면 제한시간과 캐시를 적용한 /info 조회를 사용합니다. 분모는 호스트 전체 용량이며 Agent 컨테이너의 CPU quota나 Peer capacity 설정이 아닙니다. 분자는 KPL 컨테이너만 포함하며 다른 호스트 프로세스는 포함하지 않습니다. 메모리는 cgroup 사용량 합계이며 기본 표시는 inactive file cache를 제외한 working set, 캐시 포함 원본 사용량도 별도로 제공합니다.

Agent + Peers(기존 합계), Agent only(Agent 컨테이너), Peers only(소속 실행 중 Peer 컨테이너 합계)를 함께 제공합니다. 같은 Docker 읽기·표본 시각·호스트 CPU 수를 재사용하므로 분리 측정을 위한 추가 폴링이나 Docker 요청이 없습니다. 각 범위는 측정/대상 컨테이너 수와 유효성을 별도로 판단합니다. Agent 컨테이너 사용량은 기존 process_*의 프로세스 CPU·resident memory와 구분하며, 기존 프로세스 전용 패널도 유지합니다.

전체 Agent CPU는 최신 표본과 CPU 수가 있는 Agent에 대해 100 × 사용 코어 합계 / 호스트 논리 CPU 합계로 용량 가중 계산합니다. 백분율의 합이나 단순 평균이 아닙니다. 표준 배포처럼 호스트마다 Agent 하나를 실행할 때 참여 호스트 전체 용량에서 KPL이 차지하는 비율입니다. 메모리는 측정 가능한 모든 Agent를 합산합니다. 구형 Agent처럼 호스트 CPU 수가 없으면 메모리는 표시하고 CPU 백분율은 미상으로 남기며, 전체 CPU 측정 Agent 수도 별도로 알립니다. 기존 원시 코어 gauge와 process counter는 유지합니다. Grafana의 Agent 프로세스 전용 CPU 패널도 호스트 전체를 100%로 환산하며, 프로세스 메모리는 KPL 합계와 별도로 유지합니다.

Agent는 별도 루프에서 약 10초마다 로컬 Docker Engine을 읽으며 동시 읽기 4개, 한 주기 제한시간 8초를 적용합니다. one-shot 읽기와 이전 CPU 카운터를 재사용하고 처음 관측한 컨테이너만 공통 1초 대기 후 다시 읽습니다. 표본이나 Peer마다 Docker CLI 프로세스를 만들지 않으며 Prometheus scrape와 heartbeat도 Docker 읽기를 기다리지 않습니다. 주기 시작 시 실행 중인 컨테이너 목록을 측정 대상으로 삼으므로, 표본 사이에 생성·종료된 컨테이너나 짧은 피크는 복원할 수 없습니다.

일부 측정이 빠져도 사용 가능한 값을 표시합니다. 47개 중 46개를 측정했다면 해당 46개의 CPU·메모리 합계를 표시하고 Partial · 46/47 containers를 함께 보여줍니다. 누락 컨테이너의 사용량은 추정하지 않습니다. 전체 측정 실패, Offline Agent, 30초보다 오래된 표본은 현재 합계에 포함하지 않으며 대상 컨테이너가 있는데 측정된 컨테이너가 0개면 N/A로 남깁니다. 정상 조회 결과 실행 중 Peer가 0개라면 Peers 범위는 CPU·메모리 0의 완료 표본으로 기록하며, 인벤토리 조회 실패를 빈 목록으로 취급하지 않습니다. Agent 컨테이너 측정만 실패해도 측정 가능한 Peer 값은 유지하고 반대의 경우도 같습니다. 범위별 전체 합계는 각각의 측정 Agent 수와 CPU 분모를 사용하므로 누락된 표본이 서로 다르면 전체 백분율의 합이 기존 합계와 다를 수 있습니다. churn 중 사용량 감소를 해석할 때 측정 비율도 함께 확인하십시오.

Controller는 agent_id gauge로 kpl_agent_cpu_usage_percent(호스트 백분율), kpl_agent_cpu_capacity_cores(분모), kpl_agent_cpu_usage_cores(원시 사용 코어 수), kpl_agent_memory_working_set_bytes, kpl_agent_memory_usage_bytes, kpl_agent_resource_sample_timestamp_seconds, kpl_agent_resource_sample_complete, kpl_agent_resource_containers(kind="expected" 또는 "measured")를 제공합니다. 부분 측정은 값을 내보내더라도 complete flag가 0이며, stale/offline/측정 불가 상태의 measured 컨테이너 수는 0입니다. Grafana는 Agent별·전체 가중 CPU, 메모리 합계와 컨테이너 측정 비율을 표시합니다. 기존 5초 Controller scrape를 사용하므로 컨테이너별 TSDB label을 추가하지 않습니다.

새 kpl_agent_component_* gauge는 위 CPU·메모리·표본 시각·완료 여부·컨테이너 수 suffix를 그대로 사용하며 agent_id, component="agent" 또는 component="peers" label을 가집니다(컨테이너 수에는 kind도 포함). 기존 합계 kpl_agent_* 이름과 label은 유지합니다. Grafana에는 Agent 컨테이너·Peer 컨테이너별 CPU/메모리, 범위별 전체 합계, 대상/측정 컨테이너 수 패널을 추가합니다. Agent마다 고정된 두 범위이며 Peer마다 시리즈를 만들지 않습니다.

Agent Status → Current CSV는 현재값, complete/partial 상태, 측정 범위와 전체 합계를 제공합니다. CPU는 cpu_percent_host, 분모는 cpu_capacity_cores입니다. 5분부터 24시간까지 기간을 선택해 History CSV 또는 Summary CSV로 표본 수·평균·최솟값·최댓값·첫/마지막 시각을 받습니다. 이력 CPU는 cpu_percent 지표와 percent_host 단위를 사용하며 메모리는 bytes입니다. 측정 범위도 containers_expected, containers_measured 시리즈로 내보냅니다. 평균에는 부분 측정값도 포함하며 누락 사용량을 추정하거나 보간하지 않습니다. 평균은 정확한 시간 적분이 아닙니다. CPU 백분율은 별도 새 gauge를 사용하므로 이전 1코어 기준 값을 섞거나 과거 값을 현재 CPU 수로 나누지 않습니다. 새 CPU 이력은 Agent·Controller 업그레이드 후 보고되는 시점부터 제공됩니다. 이력은 Prometheus에만 보존하고 실험 ZIP·SSE·NAS 실행 로그에는 추가하지 않습니다.

현재·이력·요약·구간 CSV는 scope가 agent_and_peers, agent, peers인 사용 가능한 기록을 함께 내보냅니다. 다운로드 분석 시 scope별로 구분해야 하며 세 범위를 전부 더하면 같은 사용량을 중복 계산합니다. 분리 이력은 Agent·Controller 업그레이드 후 Prometheus가 새 gauge를 수집한 시점부터 생깁니다. 구형 Agent와 과거 합계 전용 기록의 분리값을 0으로 채우거나 프로세스 counter로 추정하지 않습니다.

Agent Status의 Interval measurement에서 Start measurement로 Controller의 현재 시각을 시작점으로 저장하고 Stop measurement로 종료 시각을 확정합니다. 완료 구간을 선택해 Interval CSV 또는 Interval summary CSV를 받습니다. 진행 중인 구간 하나를 모든 브라우저가 공유하며 페이지를 닫아도 유지됩니다. Controller 데이터 디렉터리를 보존하면 재시작 후에도 복원됩니다. 24시간이 지나면 자동 종료합니다. 최근 100개 구간은 runs 밖의 <data-dir>/agent-resource-measurements.json에 보존하며, 한도에 도달한 뒤 새 구간을 시작하면 가장 오래된 구간 기록을 제거합니다. 현재값과 최근 이력 내보내기도 계속 사용할 수 있습니다.

구간 다운로드 옆의 Delete interval로 선택한 완료 측정을 삭제합니다. 진행 중 측정은 먼저 종료하십시오. 삭제는 재시작 후에도 유지되며 저장 구간·다운로드 항목을 제거합니다. 공용 Prometheus 이력과 이미 받은 CSV는 유지합니다.

Agent Status → ⚙️ → Disable Agent에서 ID별 참여 여부를 저장합니다. 비활성 Agent의 하드웨어 사용량은 Excluded로 표시하며 전체 합계의 사용량과 CPU 분모에서 모두 제외하고 토폴로지 및 새 배치 후보에서도 숨깁니다. Agent와 기존 Peer는 계속 실행됩니다. 다음 scrape부터 Controller 리소스 gauge에서 제외하고 다음 discovery 갱신부터 프로세스 전용 Agent target도 제외합니다. 과거 이력은 소급해서 제외하거나 지우지 않으며, 비활성화 시점을 포함한 구간에는 해당 Agent가 집계 대상이던 시점의 표본이 남습니다. 재활성화하면 참여를 재개합니다.

구간은 Prometheus scrape 시각이 (startedAt, endedAt]에 속하는 표본을 선택합니다. 수집기를 추가 실행하거나 Agent 수집 주기를 바꾸지 않습니다. CPU 값은 직전 Agent 수집 기간(보통 약 10초)을 요약하므로 시작 경계 이전의 일부 시간이 반영될 수 있고, 여러 scrape에 같은 최신 Agent 표본이 기록될 수도 있습니다. 너무 짧은 구간은 표본이 없을 수 있습니다. Controller 종료·재시작 등의 누락 구간은 통계에서 제외합니다. 종료는 Prometheus 없이도 가능하며 다운로드는 Prometheus 복구 후 재시도할 수 있습니다. 구간 인덱스는 시각만 보관하므로 실제 다운로드 가능 여부는 Prometheus 보존 기간과 내보내기 크기 제한에 따릅니다. 장기 보관하려면 CSV를 저장하십시오.

Swarm은 KPL_SWARM_TASK_NAME의 task 이름으로 Agent 자신을 식별하고 기존 Docker socket mount에서 읽기 전용 조회를 수행합니다. 별도 실행에서는 --self-container <container-name>, --docker-socket <socket-path>를 지정할 수 있습니다. 식별자나 socket이 없으면 Peer만 합산해 표시하지 않고 KPL 측정을 사용할 수 없다고 알립니다. Controller의 이력 조회 주소는 --prometheus-url / KPL_PROMETHEUS_URL이며 stack은 http://prometheus:9090, 별도 Controller의 기본값은 http://127.0.0.1:9090입니다. Prometheus가 없어도 현재값은 표시합니다. 이력 다운로드는 대시보드 로그인을 사용하며 동시 요청 2개·15초·응답 16 MiB·250,000개 표본으로 제한하므로 큰 요청은 기간을 줄이십시오. 수집을 적용하려면 Controller·Agent를 재빌드·재배포하고 버전이 붙은 Grafana dashboard config도 반영해야 합니다. 과거에 수집하지 않은 값은 소급 생성할 수 없습니다.

Controller 메모리와 요청 부하

Controller는 본문 디코딩 전에 telemetry 수락 수를 제한합니다. 정확한 제한과 재시도 계약은 API에 있습니다. kpl_controller_telemetry_inflight_requests는 디코딩·저장 중 요청, kpl_controller_telemetry_waiting_requests는 본문을 읽지 않은 대기 요청, kpl_controller_telemetry_rejected_total은 디코딩 전에 거절한 요청을 나타냅니다. 거절이 이미 수락한 telemetry의 폐기를 뜻하지는 않으므로 Agent spool 적체·저장 지연과 함께 해석하십시오. /metrics는 동시 수집 두 개를 허용하고 초과 요청에는 503을 반환합니다. 수집 클라이언트가 시간 초과되어도 수집과 응답이 끝날 때까지 해당 슬롯을 유지합니다.

Live session-window-v1 지표는 세션 증거를 보존하면서 별도의 legacy 수신자·cohort 인덱스를 중복 보관하지 않습니다. 캐시는 전파 표본 전체의 복사본 대신 집계한 지연 histogram bucket을 유지합니다. 저장 분석은 원본 로그에서 수신 그룹·표본 상세를 계속 재구성합니다. 늦은 증거와 도달 기한 경과에도 같은 정확한 측정을 갱신합니다. 집계는 Run별 잠금을 사용하므로 느린 집계를 기다리는 동안 인벤토리·영구 저장 잠금을 점유하지 않습니다. Dashboard SSE는 제한된 snapshot 계산을 공유하고 취소된 조회를 해제합니다.

이 변경이 Controller 전체 heap의 상한을 정하지는 않습니다. Run 측정 증거는 결과 삭제 전까지 늦은 보정을 위해 보존하고, 종료 Peer 식별자는 생명주기 차단을 위해 유지하므로 보관한 Run·관측 수에 따라 메모리가 증가할 수 있습니다. Controller 호스트의 MemAvailable·파일/slab 캐시를 Controller 프로세스 RSS·Go heap·컨테이너 working set과 비교하고 Prometheus·Grafana도 별도로 확인하십시오. MemFree가 낮다는 사실만으로 Go 누수를 확정할 수는 없습니다. 정상 운영에 강제 GC나 커널 캐시 초기화를 사용하지 않습니다.

장기 실험 중 Agent 메모리

Agent는 Peer 컨테이너 제거가 확인되면 실패한 프로세스까지 포함해 토폴로지·점수 snapshot을 해제합니다. Controller가 확인한 종료 이력은 최근 64개만 메모리에 남기고 오래된 축약 식별자와 실행 세대 차단 정보는 Agent 로컬 peer-history/에 보관합니다. runs 아래가 아닙니다. 종료 Peer는 개별 JSON 파일 대신 bbolt DB 파일 하나인 peer-history/nodes에 보관하고, runs/와 fences/에는 실행별 정보만 둡니다. 디스크 키로 조회하며 Controller 재등록 시에도 전체 이력을 Go heap에 다시 올리지 않고 제한된 페이지로 복구합니다. 네트워크 전송 중에는 DB 트랜잭션을 유지하지 않습니다. 미확인 종료 기록과 제거 실패 컨테이너는 버리지 않습니다. 정리를 기다리는 완료 기록 또는 이벤트 큐 진입을 기다리는 종료 표식이 각각 4,096개에 도달하면 전달/저장소 복구 전까지 신규 생성에 503을 반환하고 기존 Peer는 계속 실행합니다. 중복 ID 및 세대 차단 검사를 유지하려면 Agent 데이터 볼륨을 보존하십시오.

첫 시작 시 기존 peer-history/nodes/ JSON을 제한된 batch로 복사·검증하고 경로를 원자적으로 교환하여 DB를 설치합니다. 이 변환에는 rename-exchange를 지원하는 Linux 파일시스템이 필요하며 실패하면 원본을 남기고 시작 오류를 보고합니다. 기존 디렉터리는 nodes.migrating/가 되며 유지보수 작업이 DB와 대조하여 일치하는 파일을 회당 최대 128개씩 정리합니다. 재시작 후에도 정리를 이어갑니다. 변환된 nodes 경로는 디렉터리를 기대하는 구버전 Agent의 시작을 막아 중복 ID 차단 정보가 조용히 누락되는 것을 방지합니다. 이 형식을 지원하는 Agent를 계속 사용해야 하며 telemetry 전달을 끝내더라도 변환된 이력을 구버전 이미지로 읽을 수는 없습니다.

Agent /metrics에서 kpl_local_history_records{kind="peers"|"run_fences"}, kpl_local_history_retired_total{kind="peers"|"run_fences"}, kpl_local_history_cleanup_errors_total을 제공하며 모두 agent_id 라벨을 사용합니다. 정상 상태에서 확인된 기록은 Peer 64개·차단 캐시 128개로 정리되고 진행 중인 확인/정리 작업만큼 일시적으로 늘 수 있습니다. kpl_local_cleanup_pending, kpl_local_telemetry_queue_events, go_memstats_heap_alloc_bytes, process_resident_memory_bytes를 함께 확인하십시오. Go의 사용 중 heap, 프로세스 RSS, 컨테이너 working set은 다른 값이므로 객체를 해제해도 RSS/working set이 즉시 떨어지지는 않을 수 있습니다. 수치를 숨기기 위한 강제 GC나 임의의 0 표시를 사용하지 않습니다. 합성 churn 회귀 검증을 참고하십시오.

Peer 종료 대기는 Peer마다 docker wait 프로세스를 유지하는 대신 로컬 Docker Engine API 연결을 사용합니다. 자원 측정과 별도 연결 풀을 사용하고 Peer 생존 시간에 제한을 두지 않으며, 취소하면 기존 컨테이너 제거 절차를 실행합니다. --docker-socket은 측정과 종료 대기 양쪽에 사용하므로 Peer를 생성하는 Docker CLI와 같은 daemon을 가리켜야 합니다. 컨테이너 제거와 최종 heartbeat 확인이 끝난 Peer의 설정 파일은 최근 기록을 포함하여 history 유지보수에서 삭제합니다. 다른 파일·수명 이력·제거 실패 기록은 유지합니다. 이전 Agent 프로세스가 남긴 고아 설정 디렉터리를 소급하여 전체 삭제하지는 않습니다.

수락한 telemetry 본문은 로컬 디스크 spool에 두고 메모리에는 파일 위치/Run 인덱스와 전송할 최대 5,000개 / 직렬화 기준 1 MiB 구간만 유지합니다. 개별적으로 유효한 큰 이벤트 하나는 예외적으로 이 구간을 넘을 수 있으나 기존 batch envelope 포함 10 MiB 전송 제한을 따릅니다. 이는 직렬화 데이터 한도이며 Go heap 자체의 상한은 아닙니다. 재시작 복구도 기존 spool 배열을 순차 읽고 이 구간만 적재합니다. 수신 디코딩·저장은 동시 2개로 제한하고, 최대 64개 요청만 본문을 읽지 않은 채 1초까지 기다립니다. 대기열이 가득 차거나 시간이 지나거나 새 batch가 대기량 50,000개 / 256 MiB를 넘기면 503과 Retry-After로 재시도를 요청합니다. 디스크 및 전송 중 이벤트도 대기량에 포함합니다. 가득 찬 동안 새 Peer 배치도 일시 중단하여 churn으로 종료 기록이 계속 늘어나는 것을 막고, 이미 실행 중인 Peer의 최종 증거는 유지하므로 일시적으로 정상 한도를 넘을 수 있습니다. 기존 한도 초과 적체는 삭제하지 않고 전달합니다. 실험 종료 확인은 해당 Run의 디스크 대기량과 전송 중 자료까지 기다리며 재시도 시 이벤트 ID와 순서를 유지합니다.

종료 증거의 큐 진입과 telemetry backlog 확인 대기는 Agent 상태 잠금 밖에서 수행합니다. spool 쓰기가 지연되어도 heartbeat snapshot과 다른 Peer의 수명 만료 취소 처리는 계속 가능합니다. 생성 admission은 용량을 예약하기 전에 취소와 Run 세대 차단을 다시 확인합니다. 생성 허용과 정리를 참고하십시오.

작은 batch는 4 MiB를 목표로 교체하는 append-only .jsonl 파일을 공유하고, ACK도 체크섬이 있는 journal에 추가합니다. 개별 큰 batch 하나는 기존 segment 제한 안에서 목표 크기를 넘을 수 있습니다. 전부 확인된 활성 파일 하나는 재사용하므로 대기 이벤트가 0이어도 spool 디렉터리가 비어 있지는 않을 수 있습니다. batch마다 payload·cursor 파일을 만들고 바꾸는 작업을 줄여 inode/dentry 생성 및 커널 캐시 부담을 줄입니다. 전송은 저장된 JSON을 Fields map으로 다시 풀지 않고 바이트 한도 내에서 직접 복사하고, 복구 시에도 파일 위치 인덱스만 유지합니다. 이벤트 수 제한을 250개에서 5,000개로 늘려 작은 이벤트도 기존 1 MiB 한도를 활용합니다.

입장 전에 거절된 503은 Controller가 안전하게 재시도합니다. Agent 미지정 배치는 Retry-After 동안 해당 Agent를 제외하고 다른 가능한 Agent에 배치할 수 있으며, 특정 Agent 지정 또는 single-agent 배치는 선택한 Agent를 유지하여 기다립니다. 시나리오 context가 대기 시간을 제한하고 중지·취소하면 예약을 즉시 반환합니다. 생성 여부가 불확실한 일반 503·연결 오류·timeout은 다른 Agent에 무조건 재생성하지 않습니다. 대기는 Run/Agent ID와 함께 로그에 남으며 지속적인 과부하에서는 입장 시각이 지연될 수 있습니다.

기존 .json spool 배열도 복구합니다. format-v2.json은 구버전 Agent가 롤백 때 대기 중인 .jsonl 자료를 무시하지 않도록 시작을 막는 형식 표식입니다. 전달을 끝내고 정상 종료하면 빈 활성 파일과 표식을 제거합니다. 이때 해제되는 것은 spool 보호 장치뿐이며, 변환된 Peer 이력 DB는 계속 호환되는 Agent 이미지를 필요로 합니다. 업데이트·복구 중에도 Agent volume은 유지해야 합니다.

Agent 메모리 증가 원인을 구분하는 지표도 제공합니다.

지표 해석
kpl_local_agent_memory_bytes{kind="…"} (usage, working_set, anonymous, file, inactive_file, kernel, slab, slab_reclaimable, slab_unreclaimable, kernel_stack, page_tables, socket) 기존 자원 표본의 Agent 컨테이너 cgroup 수치이며 자식 프로세스도 포함합니다. 미지원 항목은 생략합니다. 항목끼리 중복되므로 합산하지 마십시오.
kpl_local_agent_memory_sample_timestamp_seconds 원본 표본 시각입니다. 현재성을 확인하고 해석하십시오. 자기 컨테이너 측정이 실패하면 상세 항목을 생략합니다.
kpl_local_peer_wait_connections Docker CLI 프로세스를 생성하지 않는 Engine 종료 대기 연결 수입니다.
kpl_local_telemetry_backlog_bytes, kpl_local_telemetry_window_bytes 직렬화된 전체 대기량과 메모리 적재/전송 구간 크기입니다. Go heap 측정값은 아니며 전체 대기량에는 디스크 자료도 포함합니다.
kpl_local_telemetry_decoders, kpl_local_telemetry_decoder_waiters, kpl_local_telemetry_decoder_rejected_total 현재 디코딩·저장 요청 수(최대 2개), 본문을 읽지 않은 대기 요청 수(최대 64개), 디코딩 전 거부 횟수입니다. 거부된 batch는 재시도해야 합니다.
go_threads, go_memstats_stack_sys_bytes Go 런타임의 OS 스레드 수와 스택용 예약 메모리입니다. cgroup kernel_stack과 함께 초기 런타임 증가와 이력·캐시 누적 비용을 구분합니다.
go_gc_heap_live_bytes, go_gc_heap_goal_bytes, go_gc_cycles_total_gc_cycles_total 마지막 GC의 live heap·다음 heap 목표·GC 횟수입니다. 기존 go_memstats_*, go_gc_duration_seconds와 함께 확인합니다.
go_cpu_classes_gc_total_cpu_seconds_total, go_cpu_classes_gc_mark_assist_cpu_seconds_total, go_memory_classes_* Go 런타임의 GC CPU 추정치·할당 시 GC 보조 비용·heap/metadata 구분입니다. Agent Go 프로세스를 측정합니다.

첫 실험 후 증가는 런타임 스택, 연결 풀, 재사용 버퍼를 포함할 수 있습니다. 활성 Peer 수가 비슷하고 telemetry 큐가 빈 휴지 구간끼리 비교하십시오. 스레드 수와 live heap이 안정적인데 누적 종료 Peer와 함께 slab_reclaimable이 늘면 Go 객체보다 파일시스템 메타데이터 비용을 의심할 수 있습니다. 단일 파일 이력 저장소는 Peer별 inode 증가를 없애지만 DB 파일 크기, OS 페이지 캐시, 전체 컨테이너 메모리에 상한을 두지는 않습니다. 관측한 이력·캐시 추세를 참고하십시오.

Agent only working set, process_resident_memory_bytes, Go live heap을 비교하십시오. 프로세스 RSS는 낮은데 컨테이너 수치가 크다면 cgroup file/kernel 항목을 확인해야 합니다. 강제 GC로 다른 프로세스 메모리를 해제하거나 커널 사용량 전체를 설명할 수는 없습니다. 메모리 회귀 검증은 운영 중 강제 GC 없이 큐 복구·전달 보존을 확인합니다.

Controller 및 관리 서비스

Agent Status → Controller & services는 Agent 목록 위에 Controller, Prometheus, Grafana와 자원 수집기의 상태를 별도로 표시합니다. 각 표 행에는 서비스명과 Docker 호스트, 컨테이너 실행 상태, 호스트 전체를 100%로 계산한 CPU, working-set 메모리, 측정/대상 컨테이너 수가 표시되며 Controller 가동 시간도 제공합니다. Controller & services와 Agents & Peers 표는 모두 맨 위에 Total 행을 표시합니다. 서비스 메모리는 측정값을 합산하고, 서비스 CPU는 측정된 CPU 사용량 합계를 해당 호스트들의 CPU 용량 합계로 나누며 같은 호스트의 용량을 중복 계산하지 않습니다. 측정 누락이나 부분 측정은 커버리지로 구분합니다. Agent 합계는 전체·Agent만·Peers만 구분을 유지하며 비활성 Agent를 제외합니다. Peer 수와 용량은 활성화된 온라인 Agent만 합산합니다. Running은 Docker 컨테이너의 실행 상태이며 애플리케이션 준비 완료를 보장하지 않습니다. 서비스 중단, 인벤토리 조회 실패, 오래된 수집기 보고를 CPU·메모리 0으로 기록하지 않습니다. 일부만 측정되면 성공한 컨테이너 값을 표시하고, 30초가 지난 보고는 stale로 처리합니다.

스택은 대상 Linux Swarm 노드마다 resource-monitor 태스크를 하나 배포합니다. Agent 배치 라벨이나 UI의 Agent 활성화 설정과 독립적으로 동작합니다. 기존 Docker 샘플러를 재사용하여 약 10초 간격, 동시 GET 요청 최대 4개, 샘플링 제한 시간 8초로 수집하며 새 컨테이너의 CPU 카운터 준비 대기는 함께 수행합니다. 자신의 스택에 속하며 컨테이너 라벨 io.kpl.resource-monitor=true가 있는 컨테이너만 선택하고 소유권을 재확인합니다. Agent와 managed Peer는 중복 집계를 피하기 위해 제외합니다. 기본 라벨 대상은 Controller·Prometheus·Grafana·수집기 자체이며 수집기 비용은 monitor 범위에 따로 기록합니다. 설정된 제어 노드는 처음부터 실행되지 못한 기본 서비스도 누락 상태로 보고합니다. 같은 스택의 다른 관리 서비스도 이 컨테이너 라벨로 참여할 수 있습니다. 다른 호스트의 복제본은 별도 레코드로, 같은 호스트의 복제본은 해당 호스트 CPU 분모로 합산합니다.

수집기는 로컬 Docker 소켓과 클러스터 보고용 인증 정보를 사용합니다. 웹 Controller에는 Docker 소켓을 추가하지 않고 기존 사용자 권한을 유지합니다. 읽기 전용 소켓 마운트 자체가 Docker API 메서드를 제한하지는 않으며, 수집 코드에서 GET 요청만 사용합니다. 제한된 크기의 인증 보고를 monitoring 오버레이로 보내고 Controller는 노드별 최신 보고만 캐시합니다. 이력은 runs가 아닌 Prometheus에 남습니다. UI는 Agent 탭이 보일 때만 서비스 현재 값을 조회하며 SSE에 서비스 이력을 추가하지 않습니다. 10분 동안 보고하지 않은 호스트는 실시간 목록에서 만료되고 Prometheus 이력은 유지됩니다.

Controller /metrics에 kpl_service_cpu_usage_percent, kpl_service_cpu_usage_cores, kpl_service_cpu_capacity_cores, kpl_service_memory_working_set_bytes, kpl_service_memory_usage_bytes, kpl_service_resource_containers (kind=expected|measured), kpl_service_resource_sample_complete, kpl_service_resource_sample_timestamp_seconds를 추가했습니다. 라벨은 service, node_id, scope (controller, third_party, monitor)입니다. kpl_service_running은 신선한 인벤토리에서 실행/부재를 1/0으로 기록하며 unknown·stale에서는 생략합니다. kpl_service_resource_report_fresh는 정상·신선한 보고와 실패·오래된 보고를 구분합니다. 이 지표는 Agent 비활성화 및 Grafana Agent 필터와 독립적입니다. Grafana의 Controller and supporting services 영역에 CPU, 두 메모리 지표, 커버리지, 실행 상태, 보고 상태 그래프가 표시됩니다.

기존 Start measurement / Stop measurement가 저장하는 같은 구간에 서비스와 Agent/Peer 세 범위가 함께 포함됩니다. 현재 값·최근 이력·구간·요약 CSV는 기존 열을 유지하고 entity_type, service, node_id, node_name을 뒤에 추가합니다. Agent 행은 entity_type=agent (현재 합계는 agent_total), 서비스 행은 service이며 Agent 식별자 열은 비워 둡니다. 이력은 안정적인 노드 ID를 사용하고 node_name은 비워 둡니다. 유형·서비스·노드·범위를 함께 구분해야 하며 scope=third_party가 같다고 서로 다른 서비스를 합치거나, 다른 호스트의 CPU 백분율을 더하거나, 중복되는 Agent 세 범위를 더하면 안 됩니다. 실행·보고 상태는 단위가 boolean인 이력 지표이며 평균은 확보된 scrape 표본 중 1의 비율입니다. 정확한 가동률이 아니고 수집 공백은 누락으로 남습니다.

KPL 이미지를 다시 빌드·게시하고 스택을 재배포하면 수집기, 서비스 컨테이너 라벨, Controller 지표, 버전이 갱신된 Grafana 설정이 함께 적용됩니다. 기존 구간은 유지되지만 서비스 이력은 업데이트 이후 scrape부터 쌓입니다. 수집기는 위 라벨이 있는 Swarm 컨테이너가 필요하며 수집기가 없는 단독·사용자 정의 배포에서는 서비스 값을 제공하지 않습니다. 로그는 sh scripts/swarm.sh logs resource-monitor --tail 100으로 확인합니다.

웹 접근·인증 로그

Controller는 <data-dir>/logs 아래에 한 줄당 JSON 객체 하나를 자동 기록합니다. 로컬 기본 경로는 data/logs, Swarm에서는 영속 controller-data volume의 /var/lib/kpl/data/logs입니다.

파일 기록 대상
access.jsonl 대시보드·정적 파일·API 접근, 리다이렉트, 실패 응답, SSE 연결 시작·종료
auth.jsonl 로그인 성공·실패, 로그아웃 시도, 세션 부재·만료로 거절된 접근과 동일 출처 검사 거절

UTC timestamp, event, 서버가 생성한 requestId, remoteIp, HTTP method·path, 응답 status, 본문 bytes, 처리 시간 durationMs, userAgent, 인증 방식 authentication(anonymous·session·internal)과 확인 가능한 user를 기록합니다. 인증 기록에는 outcome과 invalid_credentials, rate_limited, invalid_request, origin_denied, login_required 등의 이유가 포함됩니다. 유효한 JSON 로그인 요청에서는 실패하더라도 입력한 계정명을 남깁니다. 같은 요청의 접근·인증 기록은 request ID로 연결하며, SSE는 응답 시작 즉시 sse_open, 종료 시 sse_close를 남깁니다.

비밀번호, 세션 쿠키, Authorization 헤더, 요청·응답 본문, Referer와 URL 쿼리는 기록하지 않습니다. 입력 문자열의 길이를 제한하고 JSON escaping을 적용합니다. remoteIp는 실제 연결 주소이며 클라이언트가 보낸 Forwarded·X-Forwarded-For를 신뢰하지 않습니다. reverse proxy 뒤에서는 proxy 주소가 기록됩니다. 실험 중 이벤트마다 디스크에 쓰지 않도록 인증에 성공한 정상 Agent·Peer 통신과 정상 health·metrics·Prometheus target 점검은 제외합니다. 해당 요청의 오류와 인증 실패는 기록합니다.

각 파일은 10 MiB를 넘기기 전에 회전하며 현재 파일과 백업 5개(.1이 최신, .5가 가장 오래됨), 두 종류 합계 약 120 MiB까지 보관합니다. 재시작해도 기존 파일에 이어 씁니다. 디렉터리는 0700, 파일은 0600 권한입니다. 시작 시 로그 경로를 사용할 수 없으면 오류로 종료합니다. 실행 중 쓰기 실패는 Controller의 일반 서비스 로그에 알리고 HTTP 요청 처리는 유지하며 이후 요청에서 기록을 재시도합니다. 메모리 큐 없이 파일에 append하지만 건마다 fsync하지는 않습니다. 접근 기록을 보존하려면 Controller volume 백업에 logs를 포함하십시오. 대시보드에서 이 파일을 제공하거나 실험 ZIP에 넣지는 않습니다.

로컬 Controller에서는 다음과 같이 두 파일을 확인합니다.

tail -F data/logs/access.jsonl data/logs/auth.jsonl

Swarm에서는 manager helper로 최근 100줄을 JSONL 원문 그대로 출력합니다.

sh scripts/swarm.sh logs access
sh scripts/swarm.sh logs auth
sh scripts/swarm.sh logs access --tail 500
sh scripts/swarm.sh logs auth --tail all > auth.jsonl

--tail은 양의 정수 또는 all을 받습니다. 현재 파일만 조회하며 회전된 .1~.5 백업은 Controller volume에 남아 있습니다. 명령 실행 시점의 내용을 출력하므로 jq 같은 도구로 파이프 처리할 수 있습니다. 기존 logs controller, logs agent, logs prometheus, logs grafana는 타임스탬프가 있는 서비스 로그를 계속 조회하며 --tail도 사용할 수 있습니다.

Helper는 현재 manager Docker context에서 실행 중인 Controller task를 찾고, docker exec로 파일을 읽습니다. 기본적으로 현재 Docker daemon이 해당 task를 실행하는 노드여야 합니다. Controller가 다른 노드(worker 포함)에 있으면 그 노드의 Docker context를 만들고 파일 조회용으로만 지정하십시오.

# user와 control-node를 실제 SSH 계정과 Controller 호스트로 바꿉니다.
docker context create kpl-control --docker "host=ssh://user@control-node"
sh scripts/swarm.sh logs access --context kpl-control
sh scripts/swarm.sh logs auth --context kpl-control --tail 500

호출자의 Docker context는 manager에 연결된 상태로 유지합니다. 위 두 명령의 --context는 노드 확인과 파일 조회에만 적용되며, task 탐색은 manager에서 수행합니다. 선택한 daemon이 task의 실제 실행 노드인지 검사합니다. 웹 로그 기능이 포함된 Controller가 실행 중이어야 하며, 파일 부재·task 실행 불가·잘못된 노드는 오류로 안내합니다. 컨테이너를 새로 띄우거나 stack을 변경하지 않습니다. 실시간 추적이나 회전된 백업 조회는 Controller 노드에서 파일을 직접 확인하십시오.

대시보드 스트림 전송량

대시보드가 보이는 동안 Overview가 Off(페이지를 열 때의 기본값)이면 /api/v1/stream?view=dashboard&topology=0, On이면 topology=1을 사용하며 첫 snapshot 이후 snapshot_delta 또는 유휴 heartbeat를 받습니다. Off에서는 상세 그래프 계산·전송을 생략하면서 피어 수와 실험 지표를 계속 갱신합니다. 페이지를 숨기면 연결을 끊고 다시 보이면 동기화합니다. 오래 유지한 연결의 누적 바이트는 정적 페이지 크기가 아닙니다. 본문 형식, 연결 제한시간, 재시도와 기존 클라이언트 규칙은 Dashboard SSE가 정의합니다.

전송량이 크거나 Reconnecting이 지속되면 다음을 확인하십시오.

  1. 이미지 갱신 후 페이지를 새로고침하고 브라우저 Network에서 위의 dashboard view를 사용하는지 확인합니다.
  2. 접근 로그의 sse_close.bytes와 durationMs를 비교하고 sse_open·sse_close, /api/v1/auth/session 응답 상태·시간을 함께 확인합니다.
  3. Controller·서비스의 부하와 연결을 확인합니다. 로그인 거절과 느린 세션 조회는 다르며 브라우저 연결 해제만으로 실험 실패를 판단하지 않습니다. 저장된 실행 상태를 확인한 뒤 복구를 선택합니다.

기존 대용량 trace 측정과 churn 벤치마크는 검증 범위와 함께 성능 근거에 보존합니다.

보존과 운영

Prometheus 시계열은 prometheus-data, Grafana 설정은 grafana-data named volume에 저장됩니다. 일반적인 컨테이너 재생성 후에도 유지됩니다. Prometheus 보존 설정은 15일/5GB이며 먼저 도달한 정책이 적용됩니다. 5GB는 디스크 사용량의 엄격한 상한이 아니며 WAL·head·압축 작업에는 추가 공간이 필요합니다. Prometheus 저장소 문서

Swarm config는 불변이므로 Prometheus와 dashboard 설정 변경은 버전이 붙은 config 참조를 사용하며 stack을 다시 배포해야 적용됩니다. 배포된 원본은 파일로 관리하며 별도 대시보드를 저장하려면 관리자 로그인 후 복사본을 사용하십시오. Grafana provisioning 문서

# 수집 대상 상태 확인
curl http://control-node:9090/api/v1/targets

# manager에서 서비스 상태와 로그를 확인합니다.
sh scripts/swarm.sh status
sh scripts/swarm.sh logs prometheus
sh scripts/swarm.sh logs grafana

Controller target도 브라우저에서 열 수 있는 주소를 사용합니다. GET /api/v1/prometheus/controller-targets는 control 노드의 Swarm 주소와 게시된 KPL_HTTP_PORT를 반환합니다. 배포 helper는 매 배포에서 KPL_CONTROLLER_METRICS_URL과 KPL_PROMETHEUS_EXTERNAL_URL을 생성하며 사용자 지정 포트와 IPv6를 반영합니다. Prometheus 자체 링크에는 후자를 --web.external-url로 전달합니다. 탐색 요청과 Grafana datasource는 내부 DNS를 사용합니다. Prometheus 컨테이너에서 control 노드의 게시된 HTTP 포트에 접근할 수 있어야 합니다. Controller metrics URL이 미설정이면 target 목록은 비어 있습니다.

Swarm stack은 GET /api/v1/prometheus/agent-targets에서 등록된 target을 탐색합니다. sh scripts/swarm.sh access로 광고 주소를 확인하고, 설정한 포트가 선택된 모든 Agent 노드에서 비어 있으며 control 노드에서 TCP 접근이 허용되는지 확인하십시오. 운영자가 Agent metrics 링크를 직접 열 때에는 브라우저가 속한 신뢰 관리망에서도 접근을 허용하고 신뢰하지 않는 출발지는 차단하십시오. up{job="kpl-agent"}를 보면 등록되었지만 방화벽이나 잘못된 Swarm NodeAddr 때문에 접근할 수 없는 target을 성공한 scrape와 구분할 수 있습니다.

현재 이미지 버전은 Prometheus v3.13.2와 Grafana 13.2.1로 고정했습니다. 업데이트 시 공식 Prometheus 다운로드와 Grafana Docker 설치 문서를 참고하고 설정·대시보드를 재검증하십시오.

실제 실행 검증

Linux에서 새 실행을 검증하고 ZIP, 코드 revision 또는 image digest, Prometheus 시간 범위를 보존하십시오. 저장소에는 이전 모니터링 실행 예시의 원본 ZIP이 포함되어 있지 않으므로 해당 과거 수치를 현재 세션 기간 구현의 감사 가능한 기준으로 사용할 수 없습니다.

examples/monitoring.yaml에서는 다음을 확인하십시오.

확인 항목 소스에 따른 기대값
성공 발행 모든 예약 발행이 성공하고 telemetry가 수집되면 envelope 60 + raw 6 = 66건
worker 네트워크 설정 worker 세 개에 delay 50ms, jitter 5ms, loss 1% 설정
도달률 분모 전체 deliver 수가 아니라 각 발행의 수신 기간에 해당하는 동일 run/topic 세션 증거에서 재구성
지연 표본 안정 대상의 기한 내 원격 envelope 쌍만 포함. raw와 발행자 로컬 수신은 제외
관측 품질 pending, unknown, incomplete와 보고된 telemetry-drop 값을 보존. 보고된 drop이 0이어도 완전한 로그를 증명하지 않음
정리 마지막 stop-all이 Peer 제거를 요청하므로 Agent 상태와 각 Linux 호스트의 잔존 Peer 컨테이너 확인

metrics.json을 정확히 같은 events.jsonl 경계와 export.json.exportedAt에 맞춰 비교하십시오. Counter 비교에도 같은 Controller 생명주기와 수집 경계가 필요합니다. Heartbeat가 add_peer/remove_peer의 0 기준값을 초기화하지만 첫 scrape 전 이벤트는 increase 추정에서 누락될 수 있습니다. 수신·중복·mesh 이벤트·지연 합계는 실행과 관측에 따라 달라지므로 고정된 합격 기준값이 아닙니다.

지표 구현과 회귀 사례는 실험 지표에 연결되어 있습니다. Linux 검증 명령은 개발 가이드를 사용하십시오.

Dashboard 내장 시각화

이 내용은 대시보드로 옮겼습니다.

저장 결과 찾기

저장 결과 검색으로 이동했습니다.

패널 접기와 펼치기

대시보드 패널로 이동했습니다.

실험 결과 다운로드

이 내용은 저장 결과로 옮겼습니다.

분석 파일과 이미지 보존

이 내용은 저장 결과로 옮겼습니다.

Clone this wiki locally