Вопрос или проблема
Я пытаюсь использовать Grafana Alloy с включенным Grafana Beyla и надеюсь, что он может отправить некоторые трассы в Grafana Tempo.
С этой настройкой Alloy успешно отправляет логи в Loki. Однако для трасс я не могу видеть никаких трасс в Grafana и также нет Service Graph.
Helm Charts:
Grafana
---
apiVersion: argoproj.io/v1alpha1
kind: Application
metadata:
name: production-hm-grafana
namespace: production-hm-argo-cd
labels:
app.kubernetes.io/name: hm-grafana
spec:
project: production-hm
sources:
- repoURL: https://grafana.github.io/helm-charts
# https://artifacthub.io/packages/helm/grafana/grafana
targetRevision: 8.8.5
chart: grafana
helm:
releaseName: hm-grafana
values: |
# https://github.com/grafana/helm-charts/blob/main/charts/grafana/values.yaml
---
sidecar:
dashboards:
enabled: true
searchNamespace: ALL
datasources:
datasources.yaml:
apiVersion: 1
datasources:
- name: hm-prometheus
type: prometheus
isDefault: true
url: http://hm-prometheus-kube-pr-prometheus.production-hm-prometheus:9090
access: proxy
- name: hm-loki
type: loki
isDefault: false
url: http://hm-loki-gateway.production-hm-loki:80
access: proxy
- name: hm-tempo
type: tempo
isDefault: false
url: http://hm-tempo-query-frontend.production-hm-tempo:3100
access: proxy
# https://grafana.com/docs/grafana/next/datasources/tempo/configure-tempo-data-source/#example-file
jsonData:
tracesToLogsV2:
datasourceUid: 'hm-loki'
spanStartTimeShift: '-1h'
spanEndTimeShift: '1h'
tags: ['job', 'instance', 'pod', 'namespace']
filterByTraceID: false
filterBySpanID: false
customQuery: true
query: 'method="$${__span.tags.method}"'
tracesToMetrics:
datasourceUid: 'hm-prometheus'
spanStartTimeShift: '-1h'
spanEndTimeShift: '1h'
tags: [{ key: 'service.name', value: 'service' }, { key: 'job' }]
queries:
- name: 'Sample query'
query: 'sum(rate(traces_spanmetrics_latency_bucket{$$__tags}[5m]))'
serviceMap:
datasourceUid: 'hm-prometheus'
nodeGraph:
enabled: true
search:
hide: false
traceQuery:
timeShiftEnabled: true
spanStartTimeShift: '-1h'
spanEndTimeShift: '1h'
spanBar:
type: 'Tag'
tag: 'http.path'
streamingEnabled:
search: true
- repoURL: [email protected]:hongbo-miao/hongbomiao.com.git
targetRevision: main
path: kubernetes/argo-cd/applications/production-hm/grafana/kubernetes-manifests
destination:
namespace: production-hm-grafana
server: https://kubernetes.default.svc
syncPolicy:
syncOptions:
- ServerSideApply=true
automated:
prune: true
Tempo
---
apiVersion: argoproj.io/v1alpha1
kind: Application
metadata:
name: production-hm-tempo
namespace: production-hm-argo-cd
labels:
app.kubernetes.io/name: hm-tempo
spec:
project: production-hm
source:
repoURL: https://grafana.github.io/helm-charts
# https://artifacthub.io/packages/helm/grafana/tempo-distributed
targetRevision: 1.31.0
chart: tempo-distributed
helm:
releaseName: hm-tempo
values: |
# https://github.com/grafana/helm-charts/blob/main/charts/tempo-distributed/values.yaml
# https://grafana.com/docs/tempo/latest/setup/operator/object-storage/
---
tempo:
structuredConfig:
# https://grafana.com/docs/tempo/latest/traceql/#stream-query-results
stream_over_http_enabled: true
gateway:
enabled: false
serviceAccount:
create: true
name: hm-tempo
annotations:
eks.amazonaws.com/role-arn: arn:aws:iam::272394222652:role/TempoRole-hm-tempo
storage:
admin:
backend: s3
s3:
endpoint: s3.amazonaws.com
region: us-west-2
bucket: production-hm-tempo-admin-bucket
trace:
backend: s3
s3:
endpoint: s3.amazonaws.com
region: us-west-2
bucket: production-hm-tempo-trace-bucket
traces:
otlp:
http:
enabled: true
grpc:
enabled: true
metricsGenerator:
enabled: true
config:
processor:
# https://grafana.com/docs/tempo/latest/operations/traceql-metrics/
local_blocks:
filter_server_spans: false
storage:
remote_write:
- url: http://hm-prometheus-kube-pr-prometheus.production-hm-prometheus:9090/api/v1/write
global_overrides:
metrics_generator_processors:
- local-blocks
- service-graphs
- span-metrics
destination:
namespace: production-hm-tempo
server: https://kubernetes.default.svc
syncPolicy:
syncOptions:
- ServerSideApply=true
automated:
prune: true
Alloy
---
apiVersion: argoproj.io/v1alpha1
kind: Application
metadata:
name: production-hm-alloy
namespace: production-hm-argo-cd
labels:
app.kubernetes.io/name: hm-alloy
spec:
project: production-hm
source:
repoURL: https://grafana.github.io/helm-charts
# https://artifacthub.io/packages/helm/grafana/alloy
targetRevision: 0.11.0
chart: alloy
helm:
releaseName: hm-alloy
values: |
# https://github.com/grafana/alloy/blob/main/operations/helm/charts/alloy/values.yaml
---
alloy:
# For "beyla.ebpf", see https://grafana.com/docs/grafana-cloud/send-data/alloy/reference/components/beyla/beyla.ebpf/
stabilityLevel: public-preview
extraEnv:
- name: LOKI_URL
value: http://hm-loki-gateway.production-hm-loki:80/loki/api/v1/push
- name: TEMPO_ENDPOINT
value: hm-tempo-distributor.production-hm-tempo:4317
configMap:
content: |-
// https://grafana.com/docs/alloy/latest/configure/kubernetes/
// https://grafana.com/docs/alloy/latest/collect/logs-in-kubernetes/
logging {
level = "info"
format = "logfmt"
}
// Loki related config
// ...
// https://grafana.com/docs/tempo/latest/configuration/grafana-alloy/automatic-logging/
// https://grafana.com/docs/tempo/latest/configuration/grafana-alloy/service-graphs/
// https://grafana.com/docs/tempo/latest/configuration/grafana-alloy/span-metrics/
// https://grafana.com/blog/2024/05/21/how-to-use-grafana-beyla-in-grafana-alloy-for-ebpf-based-auto-instrumentation/
beyla.ebpf "default" {
attributes {
kubernetes {
enable = "true"
}
}
discovery {
services {
exe_path = "http"
open_ports = "80"
}
}
output {
traces = [otelcol.processor.batch.default.input]
}
}
otelcol.processor.batch "default" {
output {
metrics = [otelcol.exporter.otlp.hm_tempo.input]
logs = [otelcol.exporter.otlp.hm_tempo.input]
traces = [otelcol.exporter.otlp.hm_tempo.input]
}
}
otelcol.exporter.otlp "hm_tempo" {
client {
endpoint = env("TEMPO_ENDPOINT")
tls {
insecure = true
insecure_skip_verify = true
}
}
}
destination:
namespace: production-hm-alloy
server: https://kubernetes.default.svc
syncPolicy:
syncOptions:
- ServerSideApply=true
automated:
prune: true
График Alloy
Все в порядке:
Логи
Лог одного из pod’ов Alloy
Он длинный, я разместил его на https://gist.github.com/hongbo-miao/23bf9d16435098267184f090d5f45044
Я увидел строку
2025/01/30 08:59:35 ERROR Unable to load eBPF watcher for process events component=discover.ProcessWatcher interval=5s error=”loading and assigning BPF objects: field BeylaKprobeSysBind: program beyla_kprobe_sys_bind: map watch_events: map create: operation not permitted (MEMLOCK may be too low, consider rlimit.RemoveMemlock)”
внутри, однако, я не уверен, как это решить. Я использую Amazon EKS.
Лог pod’а tempo-distributor
level=warn ts=2025-01-30T06:36:10.194320099Z caller=main.go:133 msg="-- CONFIGURATION WARNINGS --"
level=warn ts=2025-01-30T06:36:10.19437038Z caller=main.go:139 msg="Inline, unscoped overrides are deprecated. Please use the new overrides config format."
level=info ts=2025-01-30T06:36:10.197225405Z caller=main.go:121 msg="Starting Tempo" version="(version=v2.7.0, branch=HEAD, revision=b0da6b481)"
level=info ts=2025-01-30T06:36:10.197899194Z caller=server.go:248 msg="server listening on addresses" http=[::]:3100 grpc=[::]:9095
ts=2025-01-30T06:36:10Z level=info msg="OTel Shim Logger Initialized" component=tempo
level=info ts=2025-01-30T06:36:10.413004915Z caller=memberlist_client.go:446 msg="Using memberlist cluster label and node name" cluster_label=hm-tempo.production-hm-tempo node=hm-tempo-distributor-6f579f694c-665x8-51b758e5
level=info ts=2025-01-30T06:36:10.414030557Z caller=module_service.go:82 msg=starting module=internal-server
level=info ts=2025-01-30T06:36:10.414226259Z caller=module_service.go:82 msg=starting module=server
level=info ts=2025-01-30T06:36:10.414342161Z caller=module_service.go:82 msg=starting module=memberlist-kv
level=info ts=2025-01-30T06:36:10.414361461Z caller=module_service.go:82 msg=starting module=overrides
level=info ts=2025-01-30T06:36:10.414402831Z caller=module_service.go:82 msg=starting module=ring
level=info ts=2025-01-30T06:36:10.414436302Z caller=module_service.go:82 msg=starting module=metrics-generator-ring
level=info ts=2025-01-30T06:36:10.414457312Z caller=module_service.go:82 msg=starting module=usage-report
level=warn ts=2025-01-30T06:36:10.414641774Z caller=runtime_config_overrides.go:97 msg="Overrides config type mismatch" err="per-tenant overrides config type does not match static overrides config type" config_type=new static_config_type=legacy
level=error ts=2025-01-30T06:36:10.498151365Z caller=resolver.go:87 msg="failed to lookup IP addresses" host=hm-tempo-gossip-ring err="lookup hm-tempo-gossip-ring on 10.215.0.10:53: no such host"
level=warn ts=2025-01-30T06:36:10.498190246Z caller=resolver.go:134 msg="IP address lookup yielded no results. No host found or no addresses found" host=hm-tempo-gossip-ring
level=info ts=2025-01-30T06:36:10.498203496Z caller=memberlist_client.go:563 msg="memberlist fast-join starting" nodes_found=0 to_join=0
level=warn ts=2025-01-30T06:36:10.498217166Z caller=memberlist_client.go:583 msg="memberlist fast-join finished" joined_nodes=0 elapsed_time=83.858295ms
level=info ts=2025-01-30T06:36:10.498238626Z caller=memberlist_client.go:595 phase=startup msg="joining memberlist cluster" join_members=dns+hm-tempo-gossip-ring:7946
level=info ts=2025-01-30T06:36:10.498317557Z caller=ring.go:316 msg="ring doesn't exist in KV store yet"
level=info ts=2025-01-30T06:36:10.498360498Z caller=ring.go:316 msg="ring doesn't exist in KV store yet"
level=info ts=2025-01-30T06:36:10.498495459Z caller=module_service.go:82 msg=starting module=distributor
ts=2025-01-30T06:36:10Z level=warn msg="Using the 0.0.0.0 address exposes this server to every network interface, which may facilitate Denial of Service attacks." component=tempo documentation=https://github.com/open-telemetry/opentelemetry-collector/blob/main/docs/security-best-practices.md#safeguards-against-denial-of-service-attacks
ts=2025-01-30T06:36:10Z level=info msg="Starting GRPC server" component=tempo endpoint=0.0.0.0:4317
ts=2025-01-30T06:36:10Z level=warn msg="Using the 0.0.0.0 address exposes this server to every network interface, which may facilitate Denial of Service attacks." component=tempo documentation=https://github.com/open-telemetry/opentelemetry-collector/blob/main/docs/security-best-practices.md#safeguards-against-denial-of-service-attacks
ts=2025-01-30T06:36:10Z level=info msg="Starting HTTP server" component=tempo endpoint=0.0.0.0:4318
level=info ts=2025-01-30T06:36:10.498914304Z caller=app.go:208 msg="Tempo started"
level=error ts=2025-01-30T06:36:10.509656008Z caller=resolver.go:87 msg="failed to lookup IP addresses" host=hm-tempo-gossip-ring err="lookup hm-tempo-gossip-ring on 10.215.0.10:53: no such host"
level=warn ts=2025-01-30T06:36:10.509682688Z caller=resolver.go:134 msg="IP address lookup yielded no results. No host found or no addresses found" host=hm-tempo-gossip-ring
level=warn ts=2025-01-30T06:36:10.509699598Z caller=memberlist_client.go:629 phase=startup msg="joining memberlist cluster" attempts=1 max_attempts=10 err="found no nodes to join"
level=error ts=2025-01-30T06:36:11.536326569Z caller=resolver.go:87 msg="failed to lookup IP addresses" host=hm-tempo-gossip-ring err="lookup hm-tempo-gossip-ring on 10.215.0.10:53: no such host"
level=warn ts=2025-01-30T06:36:11.536359541Z caller=resolver.go:134 msg="IP address lookup yielded no results. No host found or no addresses found" host=hm-tempo-gossip-ring
level=warn ts=2025-01-30T06:36:11.53637399Z caller=memberlist_client.go:629 phase=startup msg="joining memberlist cluster" attempts=2 max_attempts=10 err="found no nodes to join"
level=error ts=2025-01-30T06:36:15.080790386Z caller=resolver.go:87 msg="failed to lookup IP addresses" host=hm-tempo-gossip-ring err="lookup hm-tempo-gossip-ring on 10.215.0.10:53: no such host"
level=warn ts=2025-01-30T06:36:15.080823057Z caller=resolver.go:134 msg="IP address lookup yielded no results. No host found or no addresses found" host=hm-tempo-gossip-ring
level=warn ts=2025-01-30T06:36:15.080835127Z caller=memberlist_client.go:629 phase=startup msg="joining memberlist cluster" attempts=3 max_attempts=10 err="found no nodes to join"
level=info ts=2025-01-30T06:36:19.988200041Z caller=memberlist_client.go:602 phase=startup msg="joining memberlist cluster succeeded" reached_nodes=7 elapsed_time=9.489949855s
В S3 имеется только файл tempo_cluster_seed.json
, что означает, что Tempo может записывать в S3 успешно. Однако никаких других данных трасс нет:
Любые советы будут приветствоваться, спасибо!
Обновление 2/15/2025
Что касается
loading and assigning BPF objects: field BeylaKprobeSysBind: program beyla_kprobe_sys_bind: map watch_events: map create: operation not permitted (MEMLOCK may be too low, consider rlimit.RemoveMemlock)
В pod’е Alloy, я уже проверил, что ulimit -l
уже возвращает unlimited. В моем случае, фактической причиной, вызвавшей это, является отсутствие следующего раздела, основанного на https://grafana.com/docs/grafana-cloud/send-data/alloy/reference/components/beyla/beyla.ebpf/
alloy:
stabilityLevel: public-preview
securityContext:
appArmorProfile:
type: Unconfined
capabilities:
add:
- SYS_ADMIN
- SYS_PTRACE
После добавления вышеупомянутых частей, больше нет ошибок, связанных с Бейлой.
Я провел дальнейшее исследование, поскольку никакое внешнее приложение не отправляет трассы в Alloy, то никаких трасс нет. Однако, я ожидал, что Grafana Beyla будет генерировать трассы. Поэтому я удалил нерелевантные коды, сосредотачиваясь лишь на отладке этой части:
---
apiVersion: argoproj.io/v1alpha1
kind: Application
metadata:
name: production-hm-alloy
namespace: production-hm-argo-cd
labels:
app.kubernetes.io/name: hm-alloy
spec:
project: production-hm
source:
repoURL: https://grafana.github.io/helm-charts
# https://artifacthub.io/packages/helm/grafana/alloy
targetRevision: 0.11.0
chart: alloy
helm:
releaseName: hm-alloy
values: |
# https://github.com/grafana/alloy/blob/main/operations/helm/charts/alloy/values.yaml
---
alloy:
# https://grafana.com/docs/grafana-cloud/send-data/alloy/reference/components/beyla/beyla.ebpf/
stabilityLevel: public-preview
securityContext:
appArmorProfile:
type: Unconfined
capabilities:
add:
- SYS_ADMIN
- SYS_PTRACE
extraEnv:
- name: LOKI_URL
value: http://hm-loki-gateway.production-hm-loki:80/loki/api/v1/push
- name: TEMPO_ENDPOINT
value: hm-tempo-distributor.production-hm-tempo.svc:4317
- name: MIMIR_URL
value: http://hm-mimir-distributor-headless.production-hm-mimir.svc:8080/api/v1/push
configMap:
content: |-
// https://grafana.com/docs/alloy/latest/configure/kubernetes/
// https://grafana.com/docs/alloy/latest/collect/logs-in-kubernetes/
logging {
level = "info"
format = "logfmt"
}
// https://grafana.com/docs/alloy/latest/reference/config-blocks/livedebugging/
livedebugging {
enabled = true
}
// HM Beyla
// https://grafana.com/docs/grafana-cloud/send-data/alloy/reference/components/beyla/beyla.ebpf/
beyla.ebpf "hm_beyla" {
debug = true
open_port = 8080
attributes {
kubernetes {
enable = "true"
}
}
discovery {
services {}
}
metrics {
features = [
"application",
"application_service_graph",
"application_span",
"network",
]
instrumentations = ["*"]
network {
enable = true
}
}
output {
traces = [otelcol.processor.batch.hm_beyla.input]
}
}
// HM Beyla - Trace
otelcol.processor.batch "hm_beyla" {
output {
traces = [otelcol.exporter.otlp.hm_tempo_for_hm_beyla.input]
}
}
// https://grafana.com/docs/alloy/latest/reference/components/otelcol/otelcol.auth.headers/
otelcol.auth.headers "hm_tempo_for_hm_beyla" {
header {
key = "X-Scope-OrgID"
value = "hm"
}
}
otelcol.exporter.otlp "hm_tempo_for_hm_beyla" {
client {
endpoint = env("TEMPO_ENDPOINT")
compression = "zstd"
auth = otelcol.auth.headers.hm_tempo_for_hm_beyla.handler
tls {
insecure = true
insecure_skip_verify = true
}
}
}
// HM Beyla - Metrics
// https://grafana.com/docs/alloy/latest/reference/components/beyla/beyla.ebpf/
prometheus.scrape "hm_beyla" {
targets = beyla.ebpf.hm_beyla.targets
honor_labels = true
forward_to = [prometheus.remote_write.hm_mimir.receiver]
}
prometheus.remote_write "hm_mimir" {
endpoint {
url = env("MIMIR_URL")
headers = {
"X-Scope-OrgID" = "hm",
}
}
}
destination:
namespace: production-hm-alloy
server: https://kubernetes.default.svc
syncPolicy:
syncOptions:
- ServerSideApply=true
automated:
prune: true
Среди этих компонентов otelcol.processor.batch
поддерживает отладку в реальном времени. Однако входящих трасс нет. Так что, видимо, он не получает никаких данных от Grafana Beyla:
С другой стороны, pod Alloy действительно показывает логи, указывающие на соединения между Grafana Alloy и Grafana Tempo:
network_flow: transport=6 beyla.ip=172.31.179.149 iface= iface_direction=1 src.address=172.31.179.149 dst.address=10.215.206.123 src.name=hm-alloy-dvv7d dst.name=hm-tempo-distributor src.port=45582 dst.port=4317 k8s.src.namespace=production-hm-alloy k8s.src.name=hm-alloy-dvv7d k8s.src.type=Pod k8s.src.owner.name=hm-alloy k8s.src.owner.type=DaemonSet k8s.dst.name=hm-tempo-distributor k8s.dst.type=Service k8s.dst.owner.type=Service k8s.src.node.ip=172.31.178.125 k8s.src.node.name=ip-172-31-178-125.us-west-2.compute.internal k8s.dst.namespace=production-hm-tempo k8s.dst.owner.name=hm-tempo-distributor
network_flow: transport=6 beyla.ip=172.31.179.149 iface= iface_direction=1 src.address=172.31.179.149 dst.address=10.215.206.123 src.name=hm-alloy-dvv7d dst.name=hm-tempo-distributor src.port=45574 dst.port=4317 k8s.src.name=hm-alloy-dvv7d k8s.src.type=Pod k8s.src.owner.name=hm-alloy k8s.dst.namespace=production-hm-tempo k8s.dst.type=Service k8s.dst.owner.name=hm-tempo-distributor k8s.dst.owner.type=Service k8s.src.namespace=production-hm-alloy k8s.src.owner.type=DaemonSet k8s.src.node.ip=172.31.178.125 k8s.src.node.name=ip-172-31-178-125.us-west-2.compute.internal k8s.dst.name=hm-tempo-distributor
network_flow: transport=6 beyla.ip=172.31.179.149 iface= iface_direction=0 src.address=10.215.206.123 dst.address=172.31.179.149 src.name=hm-tempo-distributor dst.name=hm-alloy-dvv7d src.port=4317 dst.port=45590 k8s.dst.namespace=production-hm-alloy k8s.dst.type=Pod k8s.src.type=Service k8s.src.owner.name=hm-tempo-distributor k8s.src.owner.type=Service k8s.dst.name=hm-alloy-dvv7d k8s.dst.owner.name=hm-alloy k8s.dst.owner.type=DaemonSet k8s.dst.node.ip=172.31.178.125 k8s.dst.node.name=ip-172-31-178-125.us-west-2.compute.internal k8s.src.namespace=production-hm-tempo k8s.src.name=hm-tempo-distributor
Оказывается, не хватает некоторых разрешений. Официальная документация по Alloy не упоминает их. Исходя из этого файла конфигураций Beyla, который я нашел, после обновления securityContext
в Alloy, я могу видеть трассы.
securityContext:
# https://grafana.com/docs/grafana-cloud/send-data/alloy/reference/components/beyla/beyla.ebpf/
appArmorProfile:
type: Unconfined
# https://github.com/grafana/beyla/blob/main/examples/k8s/unprivileged.yaml
runAsUser: 0
capabilities:
drop:
- ALL
add:
- BPF
- CHECKPOINT_RESTORE
- DAC_READ_SEARCH
- NET_RAW
- PERFMON
- SYS_ADMIN
- SYS_PTRACE
Полный конфиг:
---
apiVersion: argoproj.io/v1alpha1
kind: Application
metadata:
name: production-hm-alloy
namespace: production-hm-argo-cd
labels:
app.kubernetes.io/name: hm-alloy
spec:
project: production-hm
source:
repoURL: https://grafana.github.io/helm-charts
# https://artifacthub.io/packages/helm/grafana/alloy
targetRevision: 0.11.0
chart: alloy
helm:
releaseName: hm-alloy
values: |
# https://github.com/grafana/alloy/blob/main/operations/helm/charts/alloy/values.yaml
---
controller:
# https://github.com/grafana/beyla/blob/main/examples/k8s/unprivileged.yaml
hostPID: true
alloy:
stabilityLevel: public-preview
securityContext:
# https://grafana.com/docs/grafana-cloud/send-data/alloy/reference/components/beyla/beyla.ebpf/
appArmorProfile:
type: Unconfined
# https://github.com/grafana/beyla/blob/main/examples/k8s/unprivileged.yaml
runAsUser: 0
capabilities:
drop:
- ALL
add:
- BPF
- CHECKPOINT_RESTORE
- DAC_READ_SEARCH
- NET_RAW
- PERFMON
- SYS_ADMIN
- SYS_PTRACE
extraEnv:
- name: LOKI_URL
value: http://hm-loki-gateway.production-hm-loki:80/loki/api/v1/push
- name: TEMPO_ENDPOINT
value: hm-tempo-distributor.production-hm-tempo.svc:4317
- name: MIMIR_URL
value: http://hm-mimir-distributor-headless.production-hm-mimir.svc:8080/api/v1/push
configMap:
content: |-
// https://grafana.com/docs/alloy/latest/configure/kubernetes/
// https://grafana.com/docs/alloy/latest/collect/logs-in-kubernetes/
logging {
level = "info"
format = "logfmt"
}
// https://grafana.com/docs/alloy/latest/reference/config-blocks/livedebugging/
livedebugging {
enabled = true
}
// Loki related config
// ...
// hm Beyla
// https://grafana.com/docs/grafana-cloud/send-data/alloy/reference/components/beyla/beyla.ebpf/
beyla.ebpf "hm_beyla" {
debug = true
open_port = "80,443,8000-8999"
attributes {
kubernetes {
enable = "true"
}
}
discovery {
services {
kubernetes {
namespace = "."
}
}
}
routes {
unmatched = "heuristic"
}
metrics {
features = [
"application",
"application_process",
"application_service_graph",
"application_span",
"network",
]
instrumentations = ["*"]
network {
enable = true
}
}
output {
traces = [otelcol.processor.batch.hm_beyla.input]
}
}
// hm Beyla - Trace
otelcol.processor.batch "hm_beyla" {
output {
traces = [otelcol.exporter.otlp.hm_tempo_for_hm_beyla.input]
}
}
// https://grafana.com/docs/alloy/latest/reference/components/otelcol/otelcol.auth.headers/
otelcol.auth.headers "hm_tempo_for_hm_beyla" {
header {
key = "X-Scope-OrgID"
value = "hm"
}
}
otelcol.exporter.otlp "hm_tempo_for_hm_beyla" {
client {
endpoint = env("TEMPO_ENDPOINT")
compression = "zstd"
auth = otelcol.auth.headers.hm_tempo_for_hm_beyla.handler
tls {
insecure = true
insecure_skip_verify = true
}
}
}
// hm Beyla - Metrics
// https://grafana.com/docs/alloy/latest/reference/components/beyla/beyla.ebpf/
prometheus.scrape "hm_beyla" {
targets = beyla.ebpf.hm_beyla.targets
honor_labels = true
forward_to = [prometheus.remote_write.hm_mimir.receiver]
}
prometheus.remote_write "hm_mimir" {
endpoint {
url = env("MIMIR_URL")
headers = {
"X-Scope-OrgID" = "hm",
}
}
}
destination:
namespace: production-hm-alloy
server: https://kubernetes.default.svc
syncPolicy:
syncOptions:
- ServerSideApply=true
automated:
prune: true
На данный момент я должен включить режим debug
, чтобы трассы работали
beyla.ebpf "hm_beyla" {
debug = true
Я открыл тикет на здесь, если будут обновления, я обновлю этот ответ.
Ответ или решение
Для многих специалистов в области информационных технологий использование инструментов мониторинга, таких как Grafana, стало стандартом. Grafana позволяет интегрировать различные источники данных и наблюдательные системы в единую удобную панель управления. Одним из востребованных сочетаний является использование Grafana Alloy совместно с Grafana Tempo для сбора и анализа трассировки, однако, как показывает ваш опыт, на этом пути может возникнуть несколько сложностей.
Теория
Основное назначение Grafana Alloy и Grafana Tempo — это управление и анализ данных, полученных в режиме реального времени. Grafana Alloy, работающий совместно с Grafana Beyla и другим программным обеспечением, служит для автоматического инструментирования процессов в кластере Kubernetes и передачи данных в такие системы, как Tempo или Loki.
Tempo — это распределенная система для поиска и визуализации трассировок, которая может обрабатывать миллионы данных о трассировках в секунду. Однако интеграция между Alloy и Tempo требует корректной настройки множества компонентов, включая eBPF для автоматического сбора данных на уровне ядра и их передачи в систему аналитики.
Пример
Вы столкнулись с проблемами в настройке Alloy для успешной передачи данных в Tempo. Проблема включала отсутствие трассировок и неподготовленность сервисного графа, что изначально может быть связано с несколькими факторами:
-
Неправильная конфигурация безопасности: Alloy требует расширенных прав доступа для использования eBPF-программ. Эти права, такие как
SYS_ADMIN
иSYS_PTRACE
, должны быть добавлены вsecurityContext
. -
Проблемы с конфигурацией eBPF: Ошибка, упомянутая в ваших логах об "operation not permitted (MEMLOCK may be too low)", указывает на потребность в корректной настройке лимитов памяти. Решение этой проблемы часто заключается в проверке и настройке параметров безопасности, таких как
AppArmor
и добавить необходимые параметры вsecurityContext
. -
Недостаточная видимость компонентов: Параметры конфигурации, такие как
debug = true
, часто помогают вскрыть скрытые проблемы на этапе интеграции и настройки.
Применение
Учитывая изложенные выше проблемы и решения, можно предложить следующие шаги для настройки:
-
Проверка прав доступа: Убедитесь, что ваш
securityContext
настроен правильно. Следует включить все необходимые составляющие, как это описано в примере кода:securityContext: appArmorProfile: type: Unconfined runAsUser: 0 capabilities: drop: - ALL add: - BPF - CHECKPOINT_RESTORE - DAC_READ_SEARCH - NET_RAW - PERFMON - SYS_ADMIN - SYS_PTRACE
-
Отладка и мониторинг: Для начальной стадии интеграции рекомендуется держать
debug = true
в конфигурации Alloy. Это позволит легче идентифицировать проблемы интеграции. -
Поддержание связи с сообществом: Поддерживайте контакт с соответствующими репозиториями и сообществами, такими как репозиторий Grafana на GitHub, чтобы получать последние обновления и лучшие практики.
-
Ползование документацией: Важно следовать официальной документации и не упускать из виду такие важные детали, как рекомендованные конфигурации и типичные ошибки. Документация Grafana и Alloy может предложить гораздо больше информации, особенно если у вас возникли проблемы уникального характера.
Заключение
Настройка решений, таких как Grafana Alloy и Tempo, требует аккуратности из-за зависимости от компонентов с открытым исходным кодом и сложных конфигураций безопасности. Вижу, что вам удалось найти путь к разрешению вашей первоначальной проблемы через корректировку securityContext
с использованием найденного конфига. Это является отличным примером того, как сочетание изучения документации и вовлеченности в сообщество может привести к успешному решению технических затруднений.