상태: 초안 (2026-10-05), 실측 반영. 지표 목록과 값은 실험 환경의 한 노드에서 에이전트, 같은 노드의 Envoy 와 Hubble, 그리고 오퍼레이터 한 개로부터 읽기 전용으로 받은 한 시점의 스냅샷입니다. 지표 의미는 HELP 문구와 Cilium 문서에 근거하며, 이 글을 쓰는 시점에 문서를 다시 열어 대조하지는 않았습니다(미확인). PromQL 예시는 실행하지 않았습니다(미실행). 작성 규칙: 실측 데이터가 기본이고, 못 잰 것은 「미실측」으로 표시합니다.
1. 지표를 내는 곳 네 군데
Cilium 1.20.1(kube-proxy-replacement=true, VXLAN 터널, Hubble 활성)은 네 곳에서 따로 지표를 냅니다. 모두 클러스터 안의 헤드리스 서비스로 열려 있습니다.
| 출처 | 포트 | 서비스 | 지표 계열 | 시계열 수(노드 하나 또는 파드 하나) |
|---|---|---|---|---|
| 에이전트 | 9962 | cilium-agent |
169 | 1,667 |
| 오퍼레이터 | 9963 | cilium-operator |
96 | 769 |
| Envoy | 9964 | cilium-envoy |
450 | 2,863 |
| Hubble | 9965 | hubble-metrics |
14 | 약 8만 |
설정은 enable-metrics=true, enable-hubble-open-metrics=true 입니다. Hubble 이 내보낼 지표는 hubble-metrics 설정이 정합니다.
dns drop tcp flow port-distribution icmp
httpV2:exemplars=true;labelsContext=source_ip,source_namespace,source_workload,destination_ip,destination_namespace,destination_workload,traffic_direction
숫자의 대부분이 Hubble 한 곳에서 나온다는 점이 이 글의 중요한 관찰이어서 6절에서 따로 다룹니다.
2. 에이전트 지표 (cilium_* 약 100개 계열)
에이전트는 계열 169개 중 cilium_* 이 약 100개이고, 나머지는 Go 런타임(go_*)과 프로세스 지표입니다. 의미는 HELP 문구를 한국어로 옮긴 것입니다.
2.1 데이터플레인: 전달, 드롭, 연결 추적
| 지표 | 종류 | 의미 |
|---|---|---|
cilium_forward_count_total, cilium_forward_bytes_total |
counter | 전달한 패킷과 바이트(방향별) |
cilium_drop_count_total, cilium_drop_bytes_total |
counter | 버린 패킷과 바이트(사유, 방향별) |
cilium_datapath_conntrack_gc_runs_total |
counter | 연결 추적 정리 작업 실행 횟수 |
cilium_datapath_conntrack_gc_entries |
gauge | 정리 직후 살아 있는/삭제된 항목 수 |
cilium_datapath_conntrack_gc_duration_seconds |
histogram | 정리 소요 시간 |
cilium_datapath_conntrack_gc_interval_seconds |
gauge | 정리 간격 |
cilium_datapath_conntrack_gc_key_fallbacks_total, …dump_resets_total |
counter | 정리 중 키 대체, 덤프 재시작 횟수 |
cilium_nat_endpoint_max_connection |
gauge | 외부 엔드포인트별 소스 포트 포화도(최대) |
cilium_bpf_ratelimit_dropped_total |
counter | BPF 속도 제한으로 버려진 수 |
cilium_act_processing_time_seconds |
histogram | 활성 연결 추적 맵을 훑는 시간 |
2.2 BPF 자원
| 지표 | 종류 | 의미 |
|---|---|---|
cilium_bpf_map_pressure |
gauge | 맵별 채움 비율(0~1) |
cilium_bpf_map_capacity |
gauge | 맵 그룹별 용량 |
cilium_bpf_map_ops_total |
counter | 맵별 연산 횟수 |
cilium_bpf_maps, cilium_bpf_progs |
gauge | BPF 맵과 프로그램의 개수 |
cilium_bpf_maps_virtual_memory_max_bytes, cilium_bpf_progs_virtual_memory_max_bytes |
gauge | 각각이 쓰는 커널 메모리 상한 |
2.3 엔드포인트, 정체성, 정책
| 지표 | 종류 | 의미 |
|---|---|---|
cilium_endpoint |
gauge | 이 에이전트가 관리하는 엔드포인트 수 |
cilium_endpoint_state |
gauge | 상태별 엔드포인트 수(ready, regenerating 등) |
cilium_endpoint_regenerations_total, …_time_stats_seconds |
counter, histogram | 엔드포인트 재생성 횟수와 시간 |
cilium_endpoint_component_status, …restoration_* |
gauge | 구성 요소 상태, 재시작 후 복원 단계와 소요 시간 |
cilium_identity, cilium_identity_label_sources |
gauge | 할당된 정체성 수(유형별), 레이블 출처별 정체성 수 |
cilium_identity_updater_timer_* |
histogram | 정체성 갱신 타이머의 소요, 대기, 합쳐진 요청 수 |
cilium_ip_addresses, cilium_ipam_* |
gauge, counter | 할당된 IP 수, IPAM 용량과 이벤트 |
cilium_ipcache_errors_total |
counter | IP 대 정체성 캐시 오류 |
cilium_policy, cilium_policy_max_revision |
gauge | 적재된 정책 수, 최대 리비전 |
cilium_policy_endpoint_enforcement_status |
gauge | 강제 방식별 엔드포인트 수(ingress, egress, both, none, audit-*) |
cilium_policy_change_total, …implementation_delay, …incremental_update_duration |
counter, histogram | 정책 변경 횟수, 반영 지연 |
cilium_policy_selector_cache_*, …selector_match_count_max |
gauge, histogram | 셀렉터 캐시 크기, 연산 지연, 한 셀렉터가 고르는 정체성 수 |
cilium_policy_l7_total, …missing_proxy_redirects |
counter, gauge | L7 프록시 처리 요청 수, 빠진 프록시 리다이렉트 수 |
cilium_fqdn_selectors, cilium_fqdn_gc_deletions_total |
gauge, counter | FQDN 셀렉터 수, FQDN 정리 건수 |
cilium_localredirectpolicy_controller_duration_seconds |
histogram | 로컬 리다이렉트 정책 처리 시간 |
2.4 쿠버네티스 연동과 제어면
| 지표 | 종류 | 의미 |
|---|---|---|
cilium_k8s_client_api_calls_total |
counter | kube-apiserver 호출 수(호스트, 메서드, 응답 코드별) |
cilium_k8s_client_api_latency_time_seconds, …rate_limiter_duration_seconds |
histogram | 호출 지연, 클라이언트 속도 제한 대기 |
cilium_k8s_workqueue_* (7계열) |
counter, gauge, histogram | 작업 큐의 추가, 깊이, 대기 시간, 처리 시간, 재시도 |
cilium_kubernetes_events_received_total, …events_total |
counter | 받은/처리한 쿠버네티스 이벤트 수 |
cilium_kubernetes_resource_sync_duration |
gauge | 리소스별 동기화 소요 |
cilium_k8s_terminating_endpoints_events_total |
counter | 종료 중 엔드포인트 이벤트 수 |
cilium_event_ts |
gauge | 제어면에서 마지막 이벤트를 받은 시각 |
cilium_agent_api_process_time_seconds |
histogram | 에이전트 API 호출 처리 시간 |
cilium_api_limiter_* (6계열) |
gauge, counter | API 속도 제한기의 한도, 대기, 진행 중 요청 |
cilium_controllers_failing, …runs_total, …runs_duration_seconds, …group_runs_total |
gauge, counter, histogram | 내부 컨트롤러의 실패 수, 실행 횟수와 시간 |
cilium_hive_* (9계열) |
gauge, counter, histogram | 내부 모듈(hive)의 기동 시간, 상태, 작업 실행 횟수와 시간 |
cilium_drift_checker_config_delta |
gauge | 에이전트 설정과 원본 설정의 불일치 수 |
cilium_errors_warnings_total |
counter | 에러·경고 로그 수(수준, 서브시스템별) |
cilium_subprocess_start_total |
counter | 하위 프로세스 시작 횟수 |
cilium_version |
gauge | 버전 정보 |
2.5 노드와 클러스터
| 지표 | 종류 | 의미 |
|---|---|---|
cilium_nodes_all_num |
gauge | 관리하는 노드 수 |
cilium_nodes_all_events_received_total, …datapath_validations_total |
counter | 노드 이벤트 수, 데이터패스 검증 호출 수 |
cilium_node_health_connectivity_status |
gauge | 다른 노드와의 ICMP·HTTP 연결 상태별 엔드포인트 수 |
cilium_node_health_connectivity_latency_seconds |
histogram | 다른 노드까지 마지막으로 관측한 지연 |
cilium_unreachable_nodes, cilium_unreachable_health_endpoints |
gauge | 도달할 수 없는 노드와 헬스 엔드포인트 수 |
cilium_clustermesh_remote_clusters |
gauge | 연결된 원격 클러스터 수 |
2.6 기능 켜짐 표시 (cilium_feature_* 32개)
값이 1 이면 켜져 있다는 뜻의 게이지 모음입니다. 설정 감사용으로 편리합니다. 한 노드에서 읽은 켜짐 상태는 다음과 같습니다.
- 켜짐(1): 대역폭 관리자, Envoy 설정과 Envoy 프록시, kube-proxy 대체, 노드 포트 설정, 호스트 방화벽, 기본 거부가 아닌 정책. (정체성 할당, IPAM, 데이터패스 모드 같은 항목은 값이 아니라 모드 레이블로 구분되므로 여기서는 해석하지 않았습니다.)
- 꺼짐(0): BGP, 이그레스 게이트웨이, L2 로드밸런서와 L2 파드 광고, SCTP, VTEP, 로컬 리다이렉트 정책, 상호 인증, 엔드포인트 슬라이스, 엔드포인트 라우트.
- 누적 수(counter): 에이전트 시작 이후 적재한 정책의 종류별 누적값이 나옵니다.
암호화 관련 지표는 없습니다. wireguard 와 encrypt 가 포함된 줄이 0 이었습니다. 투명 암호화(WireGuard)가 꺼져 있는 상태와 일치하며, 켠 뒤에 생기는 지표는 직접 켜 보지 못했습니다(미실측, 운영 설정을 바꾸지 않기 위해). 대신 Cilium 공식 지표 문서(Feature Metrics 표)를 읽으니, 투명 암호화 모드를 알리는 게이지(transparent_encryption, 레이블은 mode, node2node_enabled, strict_mode_enabled)가 있고 mode 값에 wireguard 와 ipsec 이 올 수 있다고 적혀 있습니다. 실제 노출되는 이름의 접두사는 확인하지 못했으므로, 켠 뒤에는 grep -i encryption 으로 찾아야 합니다.
2.7 프로세스와 런타임
cilium_process_*(CPU 시간, 열린 파일, 상주 메모리, 네트워크 송수신 바이트 등 9계열)과 go_*(메모리 통계 22계열, GC, 스케줄러)가 있습니다. 에이전트 상주 메모리는 한 노드에서 약 270MiB(283,545,600B)였습니다.
3. 오퍼레이터 지표 (96개 계열)
| 묶음 | 지표 | 의미 |
|---|---|---|
| IPAM | cilium_operator_ipam_* 약 15계열 |
IP 부족 해소, 쿠버네티스 동기화, 재동기화의 큐, 지연, 소요 시간 |
| 정체성 정리 | …identity_gc_entries, …identity_gc_latency, …identity_gc_runs |
정체성 가비지 컬렉션 결과, 소요, 횟수 |
| 이중 쓰기 | …doublewrite_* 4개 |
CRD 와 KVStore 사이 정체성 수 비교 |
| LB IPAM | …lbipam_conflicting_pools, …services_matching, …services_unsatisfied |
풀 충돌, 일치/미충족 서비스 수 |
| CES | …number_of_ceps_per_ces |
CiliumEndpointSlice 하나에 묶인 엔드포인트 수 |
| 기능 켜짐 | …feature_* |
Gateway API, Ingress 컨트롤러, L7 인지 트래픽 관리, LB IPAM, 노드 IPAM 켜짐 |
| 기타 | …unmanaged_pods, …errors_warnings_total, …k8s_client_*, 작업 큐, 프로세스 |
Cilium 이 관리하지 않는 파드 수, 에러 수, API 호출, 큐, 자원 |
실험 환경에서 Gateway API 와 Ingress 컨트롤러가 켜져 있다는 사실이 이 기능 켜짐 지표와 일치합니다.
4. Envoy 지표 (450개 계열)
Cilium 의 Envoy 는 Gateway API 와 L7 정책을 처리하고, 표준 Envoy 지표를 그대로 냅니다. 계열 수는 접두사 기준으로 envoy_cluster_* 191, envoy_http_* 89, envoy_listener_* 78, envoy_server_* 28, envoy_cilium_* 14 순입니다.
| 묶음 | 대표 지표 | 의미 |
|---|---|---|
| 서버 | envoy_server_uptime, _live, _memory_allocated, _concurrency |
가동 시간, 생존, 메모리, 워커 수 |
| 리스너 | envoy_listener_downstream_cx_total, _active |
리스너별 연결 수 |
| HTTP | envoy_http_downstream_rq_total, …rq_xx, …cx_active |
연결 관리자별 요청 수, 응답 코드 계열(1xx~5xx), 활성 연결 |
| 업스트림 | envoy_cluster_upstream_rq_total, …rq_pending_total, …cx_active |
클러스터별 요청, 대기, 활성 연결 |
| Cilium 전용 | envoy_cilium_* |
정책 동기화(NPDS) 등 Cilium 확장 |
한 노드의 Envoy 는 서버 가동 시간 1,019,397초(약 11.8일), 메모리 할당 약 10MB 였습니다. 게이트웨이를 통과한 요청은 리스너 하나에서 14,270건이었고, 응답 코드 계열별로 2xx 12,916, 3xx 1,217, 4xx 51, 5xx 4 건이었습니다. 5xx 가 전체의 약 0.03% 입니다. 다만 이것은 그 노드의 Envoy 한 곳이 처리한 몫이고, 다른 노드의 Envoy 는 합산하지 않았습니다.
5. 실측으로 읽는 에이전트 상태 (한 노드, 가동 약 11.8일)
| 관찰 | 값 | 해석 |
|---|---|---|
| 전달량 | 송신 2.31TB(7.07억 패킷), 수신 0.98TB(6.62억 패킷) | 가동 시간으로 나누면 송신 평균 약 2.3MB/s |
드롭: Unsupported L3 protocol (수신) |
1,081,453 | 드롭의 압도적 다수 |
드롭: Unsupported L2 protocol |
수신 1,742, 송신 16,658 | |
드롭: Service backend not found (수신) |
159 | 백엔드 없는 서비스로 간 패킷 |
드롭: Policy denied (수신) |
1 | 정책 거절은 단 한 건 |
| BPF 맵 채움 | ct_any4_global 3.7%, lb4_services_v2 0.92%, ct4_global 0.75%, 그 외 0.5% 미만 |
여유가 매우 큼 |
| 엔드포인트 | 모두 ready |
|
| 컨트롤러 | 실패 0 | |
| 도달 불가 노드 | 0 | |
| 연결 추적 정리 | 간격 525초, TCP 살아 있는 항목 960, non-TCP 2,412 | |
| 에러 로그 수 | ERROR(서브시스템 미지정) 1건 |
Unsupported L3 protocol이 드롭의 거의 전부입니다. IPv4 가 아닌 패킷(IPv6 등)일 가능성을 의심하지만 패킷을 열어 확인하지 못했습니다(미확인). 이 사유는 정책 거절이 아니므로 침입의 신호로 읽으면 안 되고, 알림을 만들 때는 이 사유를 따로 걸러야 노이즈가 줄 것으로 보입니다.- BPF 맵 채움 비율이 모두 낮습니다. 서비스 수가 늘어도 한동안 여유가 있다는 뜻입니다.
Service backend not found159건 은 엔드포인트가 사라진 서비스로 간 패킷입니다. 롤링 배포의 짧은 틈에서 생기는 정상적인 값일 수 있지만, 지속적으로 늘면 점검 대상입니다.
6. Hubble 지표의 카디널리티 문제
예를 들어 한 노드에서 Hubble 은 지표 계열이 14개뿐인데 시계열이 약 8만 개였습니다. 주범은 세 계열입니다.
| 계열 | 시계열 수 |
|---|---|
hubble_http_request_duration_seconds (히스토그램 버킷 포함) |
53,956 |
hubble_port_distribution_total |
22,607 |
hubble_http_requests_total |
4,001 |
| 나머지 11개 계열 | 약 300 |
원인은 설정의 labelsContext 입니다. 이 설정이 source_ip 와 destination_ip 를 레이블로 쓰라고 지시하기 때문에, 요청이 들어오는 클라이언트 IP 하나하나가 별도의 시계열이 됩니다. 가장 큰 계열에서 source_ip 의 서로 다른 값이 수천 개였고, 출발지 네임스페이스와 워크로드가 비어 있는 항목이 많아 클러스터 밖에서 들어오는 요청으로 보이며, 이 값은 방문자가 늘수록 계속 늘어납니다(출처 구분은 확인하지 않았습니다).
이 구성에는 두 가지 문제가 있습니다.
- Prometheus 의 메모리와 저장 비용이 커집니다. 노드 한 곳에서만 8만 시계열이고, 외부 요청을 받는 노드가 늘면 비용도 늘어납니다.
- 방문자의 IP 주소가 지표 저장소에 그대로 남습니다. 개인정보 관점에서도 점검이 필요한 부분입니다.
개선 방향은 labelsContext 에서 source_ip 와 destination_ip 를 빼고 네임스페이스와 워크로드만 남기는 것으로 보입니다. 다만 이것은 제안일 뿐 실제로 바꾸어 시계열이 줄어드는 것은 확인하지 않았습니다(미시험).
설정에는 dns 가 있지만 hubble_dns_* 지표는 출력에 없었습니다. 14개 계열은 HTTP, 포트 분포, 흐름, 드롭, TCP 플래그, ICMP, 잃어버린 이벤트, 메트릭 핸들러, gRPC 입니다. DNS 지표는 DNS 가시성 설정이 따로 필요하다고 알려져 있지만 이 실험 환경에서 확인한 것은 아니며, 원인은 모릅니다(미확인).
7. 알림과 대시보드 후보 (미실행)
실행하지 않은 예시입니다. 지표 이름은 위 실측과 맞췄습니다.
# 연결할 수 없는 노드, 실패한 컨트롤러
cilium_unreachable_nodes > 0
cilium_controllers_failing > 0
# BPF 맵이 가득 차기 전에
cilium_bpf_map_pressure > 0.9
# 정책 거절과 서비스 백엔드 없음: 노이즈인 L2/L3 프로토콜 사유는 제외한다
sum by (reason) (rate(cilium_drop_count_total{reason!~"Unsupported.*"}[5m])) > 0
# 준비되지 않은 엔드포인트
cilium_endpoint_state{endpoint_state!="ready"} > 0
# 쿠버네티스 API 오류
sum by (return_code) (rate(cilium_k8s_client_api_calls_total{return_code=~"5.."}[5m])) > 0
8. 면접에서 나올 만한 질문
- kube-proxy 를 대체했을 때 서비스 로드밸런싱 상태는 어떤 지표로 보는가?
cilium_bpf_map_pressure의lb4_*맵 채움과, 드롭 사유Service backend not found입니다. - 정책 때문에 막힌 트래픽은 어디서 보는가? 에이전트의
cilium_drop_count_total{reason="Policy denied"}와 Hubble 의hubble_drop_total입니다. - Hubble 지표를 켰더니 Prometheus 가 느려졌다면?
labelsContext를 먼저 의심합니다. IP 같은 값이 많은 레이블은 시계열을 폭증시킵니다. - Cilium 상태가 정상인지 한눈에 보려면? 컨트롤러 실패 수, 도달 불가 노드 수, 엔드포인트 상태, 맵 압력입니다.
9. 흔한 오해
- 「드롭이 있으면 공격이다」: 이 실험 환경의 드롭 대부분은 정책 거절이 아니라 지원하지 않는 프로토콜이었습니다.
- 「지표 계열이 적으면 시계열도 적다」: Hubble 은 14개 계열에서 약 8만 시계열이 나왔습니다. 레이블의 값 종류가 결정합니다.
- 「Hubble 에서
dns만 적으면 DNS 지표가 나온다」: 이 실험 환경에서는 나오지 않았습니다.
확인하지 못한 것
- 시간에 따른 변화. 모든 값은 한 시점의 스냅샷이고, 속도(rate)나 추세를 계산하지 않았습니다.
- 측정한 노드 외 다른 노드의 에이전트와 Envoy, 그리고 다른 오퍼레이터 파드가 있다면 그 값.
Unsupported L3 protocol드롭의 실제 프로토콜.- Hubble
source_ip를 뺐을 때 시계열이 얼마나 줄어드는지. - DNS 지표가 나오지 않는 이유.
- 지표 의미의 보충 설명이 인용하는 Cilium 문서를 이번에 다시 열어 대조하지 않았습니다.
참고 자료
- https://docs.cilium.io/en/stable/observability/metrics/
- https://docs.cilium.io/en/stable/observability/hubble/
확인한 버전과 날짜
2026-10-05 기준. Cilium 1.20.1, 가동 약 11.8일(에이전트 시작 시각 기준).