otel-k8s-graph

mcp
Guvenlik Denetimi
Uyari
Health Uyari
  • License — License: Apache-2.0
  • Description — Repository has a description
  • Active repo — Last push 0 days ago
  • Low visibility — Only 9 GitHub stars
Code Gecti
  • Code scan — Scanned 9 files during light audit, no dangerous patterns found
Permissions Gecti
  • Permissions — No dangerous permissions requested

Bu listing icin henuz AI raporu yok.

SUMMARY

A service graph that overlays structure derived from opentelemetry spanmetrics onto kubernetes entities for a more detailed service graph and exposes apis and an mcp server on top of it

README.md

otel-k8s-graph

A live Kubernetes service dependency graph (service map) built from OpenTelemetry traces. See what runs where and which service calls what — then query it over REST or from any LLM / MCP client (Claude, etc.).

License: Apache 2.0
Go 1.25+
Go Report Card

Keywords: Kubernetes service map · service dependency graph · service topology · OpenTelemetry · distributed tracing · observability · trace-based service map · MCP server for Kubernetes.

A live relationship graph — a service map / service topology — of a Kubernetes
cluster: what runs where, and which service talks to what. Built from two sources,
queryable by humans, scripts, and LLM agents.

  • Cluster structure — namespaces, nodes, zones, regions, workloads
    (deployments, statefulsets, daemonsets, jobs, rollouts, …), autoscalers
    (HPA, KEDA), pods and containers, and how they contain/manage/scale each
    other — from the Kubernetes API.
  • Service relationships — which service calls which HTTP endpoint, queries
    which database, publishes to which topic — derived from OpenTelemetry (OTel)
    trace spans
    , with no spanmetrics connector or metrics pipeline required.

What you can ask

One graph answers questions that normally need a service mesh, a tracing UI, and a
cluster inspector at once — over REST or from Claude / any MCP client:

  • Safe deprecation"what pods call /v1/checkout vs /v2/checkout — can I safely retire v1?"
  • Blast radius"how many upstream dependencies does this deployment have — what's impacted if it changes?"
  • Dead-code / unused APIs"which exposed endpoints have no callers?"
  • Data-store reach"which services talk to the mysql database at 10.0.0.0?"
  • Cross-zone traffic"which services call auth-service from another zone?"

How it compares

Unlike a service mesh (Istio/Linkerd) or eBPF agent, otel-k8s-graph needs no
sidecars and no kernel access
— it derives the service map straight from the
OpenTelemetry spans your apps already emit. Unlike a tracing UI (Jaeger, Tempo,
Kiali) it stores the distilled relationship graph, not raw traces, so it stays
small and is directly queryable by scripts and LLMs.

Architecture

  Kubernetes API ──watch──────>  graph-k8s ──┐
   (pods, nodes, ...)           (structure)  │
                                             ├──>  Redis  <──reads──  graph-read ──> REST API
  OTel Collector ──OTLP/gRPC──> graph-otel ──┘    (graph)                        └─> MCP server
   (trace spans)               (relationships)                                       (graph-read mcp)

Three small Go binaries, each with one job, coordinating only through Redis:

Component Source Role Docs
graph-k8s Kubernetes API Writes structural entities + containment/management edges. Single writer. cmd/graph-k8s
graph-otel OTel trace spans Writes relationship entities + CALLS/QUERIES/PUBLISHES/EXPOSES edges. cmd/graph-otel
graph-read Redis Serves the read/query HTTP API; also the MCP server (graph-read mcp). cmd/graph-read

Quickstart

The Helm chart bundles a single-replica Redis by default, so a fresh install
is self-contained:

# 1. Build + push the three images (versioned + latest) and install the chart:
REGISTRY=<your-registry> ./deploy.sh # add a registry here that your k8s cluster can access,
#                                      the script will build and push the image,
#                                      update the helm chart and run the helm install command 

# 2. Add an otlp exporter to your OTel Collector's traces pipeline, pointing at graph-otel:
#      endpoint: graph-otel-otlp:4317

Already have Redis? --set redis.internal.enabled=false --set redis.host=....
See the chart README for every value, including
existingSecret for credentials and persistence for the bundled Redis.

Sample values: self-contained install

The chart needs only a registry; everything else has working defaults
(bundled Redis included):

# graph-values.yaml
image:
  registry: <your-registry>   # e.g. ghcr.io/<you>

# Optional: keep the graph across Redis restarts (default: rebuilt from
# the K8s API and OTel metrics, so persistence is off).
# redis:
#   internal:
#     persistence:
#       enabled: true
#       size: 1Gi
helm upgrade --install graph helm/graph -f graph-values.yaml

Sample values: OTel Collector feeding trace spans

graph-otel consumes trace spans directly — no spanmetrics connector or
metrics pipeline required. Just fan the trace spans your apps already emit to
graph-otel alongside your existing trace backend. Sample values for the upstream
opentelemetry-collector chart:

# otel-collector-values.yaml
mode: deployment

image:
  repository: ghcr.io/open-telemetry/opentelemetry-collector-releases/opentelemetry-collector-contrib

# Adds the k8sattributes processor (+ RBAC) to every pipeline, so spans carry
# k8s.namespace.name / k8s.pod.name / k8s.container.name. graph-otel needs
# these to attach relationships to the right container.
presets:
  kubernetesAttributes:
    enabled: true

config:
  exporters:
    otlp/graph:
      # <service>.<namespace>: adjust if you installed the chart elsewhere
      endpoint: graph-otel-otlp.default.svc.cluster.local:4317
      tls:
        insecure: true

  service:
    pipelines:
      # Trace spans in (apps send OTLP to this collector) -> fanned out to
      # graph-otel, which derives the relationship graph from span.kind,
      # span.name and the span attributes (http.route, db.system,
      # server.address, peer.service, ...). Add your own trace backend to the
      # exporters list alongside otlp/graph.
      traces:
        receivers: [otlp]
        processors: [memory_limiter, batch]
        exporters: [otlp/graph]
helm repo add open-telemetry https://open-telemetry.github.io/opentelemetry-helm-charts
helm upgrade --install otel-collector open-telemetry/opentelemetry-collector \
  -f otel-collector-values.yaml

Already exporting traces from a collector? Just add the otlp/graph exporter
to your existing traces pipeline.

The graph

Entity kinds: namespace, node, zone, region, deployment, statefulset, daemonset, job, cronjob, rollout, pod, container, hpa, scaledobject (K8s derived); endpoint, topic, database (span derived).

Edge kinds: CONTAINS/RUNS_IN, MANAGES/MANAGED_BY, SCALES/SCALED_BY (K8s derived);
EXPOSES/EXPOSED_BY, CALLS/CALLED_BY, PUBLISHES/PUBLISHED_BY,
CONSUMES/CONSUMED_BY, QUERIES/QUERIED_BY (span derived). Edges
are single-directional but have a counterpart edge in the store, and QUERIES
edges carry an action (the SQL/command).

Entity IDs are namespace-qualified where applicable: pod:<ns>/<name>,
container:<ns>/<pod>/<name>, endpoint:<service>/<METHOD>/<route>,
database:<system>/<host>[:<port>], topic:<name>.

Zones & regions. Nodes carrying the well-known topology.kubernetes.io/zone / region labels (or their legacy failure-domain.beta.kubernetes.io forms) produce zone and region entities: region CONTAINS zone CONTAINS node. Cross-zone questions — "which services call auth-service from another zone?" — become short graph walks: pod → node → zone on each side of a CALLS edge.

Workloads & autoscalers. Beyond deployments, graph-k8s models statefulset, daemonset, job/cronjob, and Argo rollout (each MANAGES its pods), plus hpa and KEDA scaledobject autoscalers that SCALES a target workload. HPA replica bounds, KEDA triggers/scaling policy, and cron schedules are captured as metadata. The Argo and KEDA resources are CRDs — graph-k8s detects their absence and skips them, so it runs anywhere.

Redis schema (prefix configurable, default graph)

<prefix>:entity:<id>            HASH  id, kind, name, last_seen_at_ms
<prefix>:entity:<id>:metadata   HASH  arbitrary string key/values
<prefix>:entity:<id>:edges      SET   JSON-encoded Edge objects
<prefix>:by_kind:<kind>         SET   entity IDs of the given kind
<prefix>:ids                    SET   all entity IDs

Querying

  • REST (graph-read): GET /search, /entities, /entity/{id},
    /subgraph/{id}, POST /prune, GET /healthz.
  • MCP (graph-read mcp): the tools search, get_entity,
    list_entities, get_subgraph for LLM clients (Claude Code, Claude
    Desktop, …). See cmd/graph-read.

Repository layout

cmd/graph-k8s/       K8s watcher binary
cmd/graph-otel/      OTLP ingest binary
cmd/graph-read/      read API + MCP binary
internal/k8swatch/   informer wiring + object->entity mapping + diff/apply
internal/otlpreceiver/  OTLP TracesService server
internal/builder/    span record -> relationship entities/edges
internal/graph/      Redis read (RedisGraph) + write (RedisWriter, BatchWriteSet) + keys/schema
internal/api/        HTTP query handlers
internal/mcp/        MCP server + tools
helm/graph/          Helm chart (+ generated README)

Development

go build ./...
go test ./...
go test -race ./internal/graph/ ./internal/k8swatch/

Requires Go 1.25+. Tests use miniredis
and the client-go fake clientset, so no real Redis or cluster is needed.

See CONTRIBUTING.md for how to contribute.

License

Apache License 2.0 — see LICENSE.

Yorumlar (0)

Sonuc bulunamadi