Hubble Exporter
hubble observe ๋ช ๋ น์ CLI์์ ์ค์๊ฐ ํ๋ฆ์ ํ์ธํ ์ ์์ง๋ง, ์ฅ๊ธฐ ์ ์ฅ์ ์ํด์๋ Hubble Exporter๋ฅผ ์ฌ์ฉํด Flow Log๋ฅผ ์ธ๋ถ ์์คํ (ํ์ผ, Kafka, Loki ๋ฑ)์ผ๋ก ๋ด๋ณด๋ผ ์ ์๋ค.
Exporter๋ hubble-relay์ cilium-agent ๊ฐ gRPC ์คํธ๋ฆผ์ ํ์ฉํ์ฌ Flow๋ฅผ ๋ฐ์์จ๋ค.
Cilium Hubble → Promtail → Loki → Grafana๋ก ๋งคํธ๋ฆญ์ ๋ณผ ์ ์๋๋ก ๊ตฌ์ฑํด๋ณธ๋ค!
(โ|HomeLab:N/A) root@k8s-ctr:~# kubectl get cm -n kube-system cilium-config -o json | grep hubble-export
"hubble-export-allowlist": "",
"hubble-export-denylist": "",
"hubble-export-fieldmask": "",
"hubble-export-file-max-backups": "5",
"hubble-export-file-max-size-mb": "10",
"hubble-export-file-path": "/var/run/cilium/hubble/events.log",
helm upgrade
helm upgrade cilium cilium/cilium \
-n kube-system \
--reuse-values \
--set hubble.enabled=true \
--set hubble.export.dynamic.enabled=true \
--set hubble.export.dynamic.config.content[0].name=system \
--set hubble.export.dynamic.config.content[0].filePath=/var/run/cilium/hubble/events-system.log \
--set hubble.export.dynamic.config.content[0].includeFilters[0].source_pod[0]='kube_system/' \
--set hubble.export.dynamic.config.content[0].includeFilters[1].destination_pod[0]='kube_system/'
hubble flow ์ ์ฅ ์์น
(โ|HomeLab:N/A) root@k8s-ctr:~# kubectl -n kube-system get configmap cilium-config -o yaml | grep -A10 hubble-export
hubble-export-allowlist: ""
hubble-export-denylist: ""
hubble-export-fieldmask: ""
hubble-export-file-max-backups: "5"
hubble-export-file-max-size-mb: "10"
hubble-export-file-path: /var/run/cilium/hubble/events.log # ํ๋ธ ํ๋ก์ฐ ์ ์ฅ ์์น
hubble-flowlogs-config-path: /flowlog-config/flowlogs.yaml
hubble-listen-address: :4244
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-metrics-server: :9965
hubble-metrics-server-enable-tls: "false"
hubble-socket-path: /var/run/cilium/hubble.sock
hubble-tls-cert-file: /var/lib/cilium/tls/hubble/server.crt
hubble-tls-client-ca-files: /var/lib/cilium/tls/hubble/client-ca.crt
hubble-tls-key-file: /var/lib/cilium/tls/hubble/server.key
identity-allocation-mode: crd
(โ|HomeLab:N/A) root@k8s-ctr:~# kubectl exec -n kube-system ds/cilium -c cilium-agent -- tail -f /var/run/cilium/hubble/events.log

ํ์ฌ ์ ์ฅ๋๊ณ ์๋ ์ด๋ฒคํธ๋ฅผ ํ์ธํ ์ ์๋ค.
Loki ์ค์น
(โ|HomeLab:N/A) root@k8s-ctr:~# helm upgrade --install loki grafana/loki-stack \
--set grafana.enabled=true \
-n monitoring --create-namespace
Release "loki" does not exist. Installing it now.
NAME: loki
LAST DEPLOYED: Sat Jul 26 21:52:29 2025
NAMESPACE: monitoring
STATUS: deployed
REVISION: 1
NOTES:
The Loki stack has been deployed to your cluster. Loki can now be added as a datasource in Grafana.
See http://docs.grafana.org/features/datasources/loki/ for more detail.
promtail ์ค์น
(โ|HomeLab:N/A) root@k8s-ctr:~# helm upgrade --install promtail grafana/promtail \
-n monitoring \
--create-namespace \
--set "config.clients[0].url=http://loki.monitoring:3100/loki/api/v1/push" \
--set "extraVolumes[0].name=hubble-logs" \
--set "extraVolumes[0].hostPath.path=/var/run/cilium/hubble" \
--set "extraVolumeMounts[0].name=hubble-logs" \
--set "extraVolumeMounts[0].mountPath=/var/run/cilium/hubble" \
--set "config.scrape_configs[1].job_name=hubble" \
--set "config.scrape_configs[1].static_configs[0].targets[0]=localhost" \
--set "config.scrape_configs[1].static_configs[0].labels.job=hubble" \
--set "config.scrape_configs[1].static_configs[0].labels.__path__=/var/run/cilium/hubble/events*.log"
Release "promtail" does not exist. Installing it now.
NAME: promtail
LAST DEPLOYED: Sat Jul 26 23:30:38 2025
NAMESPACE: monitoring
STATUS: deployed
REVISION: 1
TEST SUITE: None
NOTES:
***********************************************************************
Welcome to Grafana Promtail
Chart version: 6.17.0
Promtail version: 3.5.1
***********************************************************************
Verify the application is working by running these commands:
* kubectl --namespace monitoring port-forward daemonset/promtail 3101
* curl http://127.0.0.1:3101/metrics
Promtail์ ์ฌ์ฉํด Hubble์ events.log ํ์ผ์ Loki์ ์ ์กํ๋ค.
(โ|HomeLab:N/A) root@k8s-ctr:~# kubectl -n monitoring describe pod -l app.kubernetes.io/name=promtail | grep -A5 "Mounts"
Mounts:
/etc/promtail from config (rw)
/run/promtail from run (rw)
/var/lib/docker/containers from containers (ro)
/var/log/pods from pods (ro)
/var/run/secrets/kubernetes.io/serviceaccount from kube-api-access-jvx7l (ro)
--
Mounts:
/etc/promtail from config (rw)
/run/promtail from run (rw)
/var/lib/docker/containers from containers (ro)
/var/log/pods from pods (ro)
/var/run/secrets/kubernetes.io/serviceaccount from kube-api-access-4t8m5 (ro)
--
Mounts:
/etc/promtail from config (rw)
/run/promtail from run (rw)
/var/lib/docker/containers from containers (ro)
/var/log/pods from pods (ro)
/var/run/secrets/kubernetes.io/serviceaccount from kube-api-access-fzgv5 (ro)
--
Mounts:
/etc/promtail from config (rw)
/run/promtail from run (rw)
/var/lib/docker/containers from containers (ro)
/var/log/pods from pods (ro)
/var/run/cilium/hubble from hubble-logs (rw)
--
Mounts:
/etc/promtail from config (rw)
/run/promtail from run (rw)
/var/lib/docker/containers from containers (ro)
/var/log/pods from pods (ro)
/var/run/cilium/hubble from hubble-logs (rw)
--
Mounts:
/etc/promtail from config (rw)
/run/promtail from run (rw)
/var/lib/docker/containers from containers (ro)
/var/log/pods from pods (ro)
/var/run/cilium/hubble from hubble-logs (rw)
Promtail์ด Kubernetes ๋ ธ๋์ Pod ๋ก๊ทธ๋ฅผ ์ฝ์ ์ ์๋๋ก ํ์ํ ๊ฒฝ๋ก๋ฅผ ์ปจํ ์ด๋ ๋ด๋ถ๋ก ๋ง์ดํธ๋ ์ค์ ์ ํ์ธํ ์ ์๋ค.
helm get values promtail -n monitoring > promtail-values.yaml
(โ|HomeLab:N/A) root@k8s-ctr:~# cat promtail-values.yaml
USER-SUPPLIED VALUES:
config:
clients:
- url: http://loki.monitoring:3100/loki/api/v1/push
scrape_configs:
- job_name: kubernetes-pods
kubernetes_sd_configs:
- role: pod
pipeline_stages:
- cri: {}
relabel_configs:
- action: replace
regex: ([0-9a-z-.]+?)(-[0-9a-f]{8,10})?
source_labels:
- __meta_kubernetes_pod_controller_name
target_label: __tmp_controller_name
- action: replace
regex: ^;*([^;]+)(;.*)?$
source_labels:
- __meta_kubernetes_pod_label_app_kubernetes_io_name
- __meta_kubernetes_pod_label_app
- __tmp_controller_name
- __meta_kubernetes_pod_name
target_label: app
- action: replace
regex: ^;*([^;]+)(;.*)?$
source_labels:
- __meta_kubernetes_pod_label_app_kubernetes_io_instance
- __meta_kubernetes_pod_label_instance
target_label: instance
- action: replace
regex: ^;*([^;]+)(;.*)?$
source_labels:
- __meta_kubernetes_pod_label_app_kubernetes_io_component
- __meta_kubernetes_pod_label_component
target_label: component
- action: replace
source_labels:
- __meta_kubernetes_pod_node_name
target_label: node_name
- action: replace
source_labels:
- __meta_kubernetes_namespace
target_label: namespace
- action: replace
replacement: $1
separator: /
source_labels:
- namespace
- app
target_label: job
- action: replace
source_labels:
- __meta_kubernetes_pod_name
target_label: pod
- action: replace
source_labels:
- __meta_kubernetes_pod_container_name
target_label: container
- action: replace
replacement: /var/log/pods/*$1/*.log
separator: /
source_labels:
- __meta_kubernetes_pod_uid
- __meta_kubernetes_pod_container_name
target_label: __path__
- action: replace
regex: true/(.*)
replacement: /var/log/pods/*$1/*.log
separator: /
source_labels:
- __meta_kubernetes_pod_annotationpresent_kubernetes_io_config_hash
- __meta_kubernetes_pod_annotation_kubernetes_io_config_hash
- __meta_kubernetes_pod_container_name
target_label: __path__
- job_name: hubble
static_configs:
- labels:
__path__: /var/run/cilium/hubble/events*.log
job: hubble
targets:
- localhost
extraVolumeMounts:
- mountPath: /var/run/cilium/hubble
name: hubble-logs
readOnly: true
extraVolumes:
- hostPath:
path: /var/run/cilium/hubble
type: DirectoryOrCreate
name: hubble-logs
ํ๋กฌํ ์ผ์ ์ ์ฉ๋ ๊ฐ์ด๋ค.
๊ทผ๋ฐ ๋ค์ ๊ถ๊ธํ์ ์.. ํ๋กฌํ ์ผ ํ๋ ๋ด๋ถ ํ๋กฌํ ์ผ ์ผ๋ฏ ์ค์ ํ์ผ ๋ด์ ๋ด๊ฐ ์์ฑํ ์ปจํผ๊ทธ๊ฐ ์๋ค๋ ๊ฒ... (/var/run/cilium/hubble/events*.log)
์๊ฑด ๋ด๊ฐ ๋ณ๋๋ก ์ ์ธํด์ ํ๋ ๋ด๋ถ ์ปจํผ๊ทธ์ ๋ฎ์ด์์์ง์ง ์๊ณ ๊ด๋ฆฌ๋๋ ๊ฒ์ผ๊น..?
๊ทธ๋ผํ๋ ๋ ธ๋ ํฌํธ ์ค์
(โ|HomeLab:N/A) root@k8s-ctr:~# k get po -A | grep grafana
monitoring loki-grafana-664849db4c-gwf4r 2/2 Running 0 71s
(โ|HomeLab:N/A) root@k8s-ctr:~kubectl patch svc loki-grafana -n monitoring -p '{"spec": {"type": "NodePort"}}'}'
kubectl get svc loki-grafana -n monitoring
service/loki-grafana patched
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
loki-grafana NodePort 10.96.103.176 <none> 80:30723/TCP 5m50s
๋ ธ๋ ํฌํธ๋ฅผ ์ค์ ํ์ฌ ๋ก์ปฌ์์ ์ ์ํ์ธํด๋ณธ๋ค.
(โ|HomeLab:N/A) root@k8s-ctr:~# kubectl get secret loki-grafana -n monitoring -o jsonpath="{.data.admin-password}" | base64 --decode; echo
ํฌ๋ฆ์ผ๋ก ์ค์นํ ๊ฒฝ์ฐ ์ฟ ๋ฒ๋คํฐ์ค ์ํฌ๋ฆฟ์ ์ ์ฅ๋ผ์์ผ๋ฏ๋ก ๊ฐ์ ์ถ์ถํ๋ค. ์์ ๋์จ ๊ฐ์ admin ์ฌ์ฉ์์ ํจ์ค์๋๋ก ์ ๋ ฅํ์ฌ ๋ก๊ทธ์ธํ๋ค.
๊ทธ๋ผํ๋์์ Unable to connect with Loki ์๋ฌ ๋ฐ์ํ ๋

Helm์ผ๋ก loki-stack์ ๋ฐฐํฌํ์ง๋ง Grafana์์ Loki Data Source๋ฅผ ์ถ๊ฐ ์ ๊ทธ๋ผํ๋์์ ์์ ๊ฐ์ ์๋ฌ๊ฐ ๋จ๊ณ ๊ทธ๋ผํ๋ ํ๋์ ์๋์ ๊ฐ์ด ๋ก๊ทธ๊ฐ ๋จ์๋ค.
parse error at line 1, col 1: syntax error: unexpected IDENTIFIER
๊ทธ๋ฐ๋ฐ ํ๋ ๋ด๋ถ์์ ์ง์ ์ ์ผ๋ก ๋กํค์๋ ํต์ ์ด ๋์๋ค.
(โ|HomeLab:N/A) root@k8s-ctr:~# kubectl exec -it -n monitoring deploy/loki-grafana -c grafana -- sh
/usr/share/grafana $ curl http://loki.monitoring:3100/ready
ready
/usr/share/grafana $ curl http://loki.monitoring:3100/loki/api/v1/labels
{"status":"success","data":["app","component","container","filename","instance","job","namespace","node_name","pod","stream"]}
https://github.com/grafana/grafana/issues/79846
Grafana Loki Integration: Health check fails when Loki is up and functional · Issue #79846 · grafana/grafana
What happened? When attempting to add a new loki datasource via grafana, I get this error in the console, and a 'failed to connect' on the webUI. logger=tsdb.loki endpoint=checkHealth pluginId=loki...
github.com
๋น์ทํ ์ฌ๋ก๋ฅผ ๊น์์ ์ฐพ์๋ณด๋ ์์๋๋ฐ ๋ฒ์ ์ข ์์ฑ์ด ๋ฌธ์ ์๋ค..!
loki-stack ์ฐจํธ๊ฐ ์ค์นํ Grafana ๋ฒ์ (10.x)์ด Loki 2.9.x์ ํธํ์ฑ์ด ์ข์ง ์์ Health Check๊ฐ ์ ์์ ์ผ๋ก ๋์ํ์ง ์์๋ ๊ฒ์ด๋ค.
helm upgrade --install loki grafana/loki-stack \
-n monitoring \
--set grafana.enabled=true \
--set grafana.image.tag=9.2.3
(โ|HomeLab:N/A) root@k8s-ctr:~# kubectl get pods -n monitoring | grep grafana
loki-grafana-c9748bdd-wmxkk 2/2 Running 0 59s
๊ทธ๋์ ๋กํค์ ํธํ๋๋ ๋ฒ์ ์ ๊ทธ๋ผํ๋๋ก ๋ค์ด๊ทธ๋ ์ด๋ํ์ฌ ๋ค์ ์ค์นํด์ฃผ๊ณ ,
(โ|HomeLab:N/A) root@k8s-ctr:~# kubectl patch svc loki-grafana -n monitoring -p '{"spec": {"type": "NodePort"}}'
service/loki-grafana patched
(โ|HomeLab:N/A) root@k8s-ctr:~# kubectl patch svc loki -n monitoring -p '{"spec": {"type": "NodePort"}}'
service/loki patched
(โ|HomeLab:N/A) root@k8s-ctr:~# kubectl get svc -n monitoring
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
loki NodePort 10.96.171.35 <none> 3100:30642/TCP 51m
loki-grafana NodePort 10.96.107.66 <none> 80:32576/TCP 118s
loki-headless ClusterIP None <none> 3100/TCP 51m
loki-memberlist ClusterIP None <none> 7946/TCP 51m
๋ ธ๋ํฌํธ๋ ๋ค์ ์ธํ ํ๋ค.

์ ๋๋ก ์ฐ๊ฒฐ์ด ๋์๋ค.
๊ทธ๋ผํ๋์์ ์ฟผ๋ฆฌํ๊ธฐ
(โ|HomeLab:N/A) root@k8s-ctr:~# curl "http://192.168.10.101:30642/loki/api/v1/labels"
{"status":"success","data":["app","component","container","filename","instance","job","namespace","node_name","pod","stream"]}
(โ|HomeLab:N/A) root@k8s-ctr:~# curl "http://192.168.10.101:30642/loki/api/v1/label/job/values"
{"status":"success","data":["hubble","kube-system/cilium-agent","kube-system/cilium-operator","kube-system/coredns","kube-system/hubble-relay","kube-system/hubble-ui","kube-system/k8s-ctr","kube-system/promtail","monitoring/grafana","monitoring/loki","monitoring/promtail"]}
์ฐ์ ๋กํค์์ ์ถ์ถํ ์ ์๋ ๋งคํธ๋ฆญ์ ๋จผ์ ์ปฌํด์ ํ์ ํด๋ณธ๋ค.

{job="hubble"}๋ก ์ฟผ๋ฆฌํ๋ฉด ๊ฒฐ๊ณผ๊ฐ์ด ์ ๋์ค๋ ๊ฒ์ ๋ณผ ์ ์๋ค.
'Infra > ์ฟ ๋ฒ๋คํฐ์ค' ์นดํ ๊ณ ๋ฆฌ์ ๋ค๋ฅธ ๊ธ
| [Cilium] #3์ฃผ์ฐจ (2) eBPF ๊ธฐ๋ฐ Cilium์์ SNAT ์์ธ ์ค์ (ip-masq-agent) (3) | 2025.08.01 |
|---|---|
| [Cilium] #3์ฃผ์ฐจ (1) Routing, Masquerading (3) | 2025.07.30 |
| [Cilium] #2์ฃผ์ฐจ (3) ์คํ์์ฆ ์ฑ ๋ฐฐํฌ (L7 ์ ์ฑ ) (3) | 2025.07.26 |
| [Cilium] #2์ฃผ์ฐจ (2) ์คํ์์ฆ ์ฑ ๋ฐฐํฌ (L3, L4 ์ ์ฑ ) (2) | 2025.07.26 |
| [Cilium] #2์ฃผ์ฐจ (1) Hubble (2) | 2025.07.26 |