Phần 5 — Grafana, Pyroscope, Beyla: UI, profiling và auto-instrumentation
Ý kiến
0
Chưa có ý kiến nào. Hãy là người đầu tiên chia sẻ!
Chưa có ý kiến nào. Hãy là người đầu tiên chia sẻ!
Tổng quan series: Grafana LGTM (Loki, Tempo, Mimir) + Alloy collector + SeaweedFS object storage + Pyroscope/Beyla. Kiến trúc, hardware, thứ tự deploy.
Vì sao SeaweedFS phù hợp cho Loki/Mimir/Tempo hơn MinIO/Ceph. Kiến trúc 4 thành phần, cài đặt single-node và multi-node, replication, best practices.
Grafana Alloy thay Promtail + Node Exporter + OTEL Collector. Deploy global trên Docker Swarm, file config.alloy đầy đủ cho metrics/logs/traces, mẹo X-Scope-OrgID.
Series Observability với Grafana Stack — 6 phần:
Phần 1 — Tổng quan: Observability với Grafana LGTM, Alloy và SeaweedFS
Phần 2 — SeaweedFS: Object storage gọn nhẹ cho Loki, Mimir, Tempo
Phần 3 — Grafana Alloy: Collector duy nhất cho metrics, logs, traces
Phần 5 — Grafana, Pyroscope, Beyla: UI, profiling và auto-instrumentation ← bạn đang đọc
Phần 6 — Production checklist: Backup, alerting, troubleshooting
Storage đã sẵn. Giờ là phần "ra mặt": Grafana làm UI, Pyroscope cho continuous profiling, Beyla auto-instrument app mà không cần sửa code.
Compose service:
grafana:
image: grafana/grafana:11.3.0
environment:
GF_SECURITY_ADMIN_PASSWORD: changeme
GF_FEATURE_TOGGLES_ENABLE: "traceqlEditor flameGraph"
volumes:
- ./grafana/datasources:/etc/grafana/provisioning/datasources:ro
- ./grafana/dashboards:/etc/grafana/provisioning/dashboards:ro
- grafana_data:/var/lib/grafana
ports: ["3000:3000"]
networks: [observability-net]
grafana/datasources/datasources.yml:
apiVersion: 1
datasources:
- name: Mimir
type: prometheus
uid: mimir
url: http://mimir:8080/prometheus
jsonData:
httpHeaderName1: X-Scope-OrgID
exemplarTraceIdDestinations:
- name: trace_id
datasourceUid: tempo
secureJsonData:
httpHeaderValue1: primary_cluster
- name: Loki
type: loki
uid: loki
url: http://loki:3100
jsonData:
httpHeaderName1: X-Scope-OrgID
derivedFields:
- name: TraceID
matcherRegex: "trace_id=(\\w+)"
url: "$${__value.raw}"
datasourceUid: tempo
secureJsonData:
httpHeaderValue1: primary_cluster
- name: Tempo
type: tempo
uid: tempo
url: http://tempo:3200
jsonData:
tracesToLogsV2:
datasourceUid: loki
tags: [{ key: service.name, value: service }]
tracesToMetrics:
datasourceUid: mimir
serviceMap:
datasourceUid: mimir
- name: Pyroscope
type: grafana-pyroscope-datasource
uid: pyroscope
url: http://pyroscope:4040
Khoá ngọc trong config trên: correlation. Logs có trace_id → click ra Tempo. Trace có exemplar → quay về Mimir. Trace có service tag → ra logs Loki. Đó là điểm khác biệt lớn nhất so với stack rời rạc.
Grafana có dashboards có sẵn rất tốt — import nhanh:
| Mục đích | ID Grafana.com |
|---|---|
| Node Exporter Full | 1860 |
| Docker / cAdvisor | 14282 |
| Loki — logs throughput | 13407 |
| Mimir — overview | 21574 |
| Tempo — operations | 17969 |
Pyroscope ghi nhận CPU/heap profiles liên tục. Khi p99 latency tăng, bạn xem flamegraph để biết hàm nào đang ngốn CPU.
pyroscope/pyroscope-config.yaml:
server:
http_listen_port: 4040
storage:
backend: s3
s3:
endpoint: seaweed-s3:8333
bucket_name: pyroscope
access_key_id: test
secret_access_key: test
insecure: true
limits:
max_query_lookback: 30d
Compose service:
pyroscope:
image: grafana/pyroscope:1.10.0
command:
- -config.file=/etc/pyroscope/pyroscope-config.yaml
- -target=all
ports: ["4040:4040"]
volumes:
- ./pyroscope/pyroscope-config.yaml:/etc/pyroscope/pyroscope-config.yaml:ro
networks: [observability-net]
Ví dụ Go app dùng pyroscope-go SDK:
import "github.com/grafana/pyroscope-go"
pyroscope.Start(pyroscope.Config{
ApplicationName: "my-service",
ServerAddress: "http://pyroscope:4040",
Tags: map[string]string{ "env": "prod" },
ProfileTypes: []pyroscope.ProfileType{
pyroscope.ProfileCPU,
pyroscope.ProfileAllocObjects,
pyroscope.ProfileInuseSpace,
},
})
Hoặc — không sửa code — dùng Beyla bên dưới.
Beyla attach eBPF probes vào kernel để bắt HTTP/gRPC requests của bất kỳ app nào (Go, Java, Node, Python, Rust, .NET, Ruby) — không cần sửa code, không cần sidecar. Output: traces (OTLP) + RED metrics.
Compose service (cần privileged + host PID):
beyla:
image: grafana/beyla:1.9.0
pid: "host"
privileged: true
cap_add: [SYS_ADMIN]
environment:
BEYLA_OPEN_PORT: "8000-9000"
OTEL_EXPORTER_OTLP_ENDPOINT: "http://alloy:4318"
OTEL_SERVICE_NAME: "auto-instrumented"
BEYLA_KUBE_METADATA_ENABLE: "false"
volumes:
- /sys/kernel/debug:/sys/kernel/debug
networks: [observability-net]
deploy:
mode: global
Beyla discovery theo cổng (BEYLA_OPEN_PORT) — chỉ instrument process nào đang listen ở range đó. Có thể đổi sang discovery theo executable name nếu muốn:
BEYLA_DISCOVERY_PROCESSES: "myservice,api-gateway"
App gọi 1 HTTP request.
Beyla bắt request → gửi trace tới Alloy (OTLP) → Tempo.
App log structured có trace_id → Loki.
Mở Grafana → Tempo → search trace → click vào span → "Logs for this span" → ra Loki đúng dòng log.
Trong Mimir thấy exemplar bóng mờ trên panel latency → click → quay lại Tempo trace.
Đây là three pillars correlation — chỉ cần đặt đúng trace_id trong logs là toàn bộ flow tự nối.
Grafana password: đổi ngay sau lần login đầu, không dùng changeme cho production.
Beyla overhead: ~1–3% CPU/process. Tắt với app latency-critical.
Pyroscope retention 30d: nhỏ hơn metrics vì profile data nặng.
derivedFields trong Loki datasource: regex bắt trace_id trong log message — đây là "magic" tạo ra link Logs → Tempo.
← Phần 4: Loki, Mimir, Tempo: Triển khai 3 storage backends
Phần 6: Production checklist: Backup, alerting, troubleshooting →