ArangoDB and Gremlin¶
Flink remains the graph lifecycle authority. The access layer consumes the
unchanged schema 2.0 topic graph.elements.events, projects current state to
ArangoDB, and exposes the named graph through read-only Gremlin Server.
Components¶
The deployment is split into three independent charts:
servicegraph-arangodbis a single-node, development-only ArangoDB3.12.9.4StatefulSet. Production environments should use an externally operated ArangoDB deployment instead.servicegraph-indexerruns an idempotent initializer Job and one Kafka indexer Deployment. It has no Service, PVC, Kubernetes API access, or RBAC.servicegraph-gremlinruns TinkerPop3.8.1with ArangoDB provider4.0.0on Java 17 and exposes an internal Service on port8182.
The generated schema is committed at
services/servicegraph-indexer/src/servicegraph_indexer/metadata/arangodb-graph-schema.json.
Normal code generation and --check own it. The same content is packaged in
the Gremlin chart so provider topology cannot drift from indexer routing.
ArangoDB preparation¶
The production database must exist unless arangodb.allowDatabaseCreation is
explicitly enabled. Give the initializer/indexer identity permission to create
and inspect collections, graphs, and indexes and to replace/delete documents in
the generated collections. The initializer is additive and idempotent. It
never drops collections or data and fails on incompatible collection types,
edge definitions, or named indexes.
Create one Secret for the writer:
apiVersion: v1
kind: Secret
metadata:
name: servicegraph-arangodb-writer
type: Opaque
stringData:
username: servicegraph-indexer
password: replace-me
Create a separate ArangoDB user with read-only database access. Provider
4.0.0 rewrites its version document whenever it opens a graph, so grant this
user rw only on the initializer-created TINKERPOP-GRAPH-VARIABLES
collection. All generated vertex and edge collections remain read-only.
Expose the user in a second Secret:
apiVersion: v1
kind: Secret
metadata:
name: servicegraph-arangodb-reader
type: Opaque
stringData:
username: servicegraph-reader
password: replace-me
Gremlin is protected twice: the traversal source applies ReadOnlyStrategy,
and its ArangoDB credentials cannot write graph elements. The narrow metadata
grant does not permit vertex or edge mutations.
Build images¶
docker build --file services/servicegraph-indexer/Dockerfile `
--tag registry.internal.example/extended-otel-servicegraph-indexer:0.1.0 .
docker build --file services/servicegraph-gremlin/Dockerfile `
--tag registry.internal.example/extended-otel-servicegraph-gremlin:0.1.0 `
services/servicegraph-gremlin
The Gremlin image is adapted from the validated sibling TinkerPop runtime. Set
TINKERPOP_SERVER_URL and MAVEN_REPOSITORY_URL build arguments when builds
must use internal artifact mirrors. An existing validated internal image can be
used directly through chart image values.
Install¶
For local development only:
helm upgrade --install arangodb deploy/helm/servicegraph-arangodb `
--namespace servicegraph-system --create-namespace
Install the indexer against local or external ArangoDB:
helm upgrade --install indexer deploy/helm/servicegraph-indexer `
--namespace servicegraph-system `
--set 'arangodb.urls[0]=http://arangodb-servicegraph-arangodb:8529' `
--set arangodb.allowDatabaseCreation=true `
--set 'streamContract.kafka.brokers[0]=kafka:9092' `
--set streamContract.kafka.security.protocol=PLAINTEXT
Then install Gremlin:
helm upgrade --install gremlin deploy/helm/servicegraph-gremlin `
--namespace servicegraph-system `
--set arangodb.host=arangodb-servicegraph-arangodb
Kafka security supports PLAINTEXT, SASL_PLAINTEXT, and SASL_SSL with
SCRAM-SHA-256. SASL credentials come from an existing Secret. No Kafka CA file
is mounted by this chart.
Query¶
Port-forward the internal endpoint for local use:
kubectl port-forward --namespace servicegraph-system `
service/gremlin-servicegraph-gremlin 8182:8182
Install and use the typed GraphBinary client:
from extended_otel_semconv.gremlin import SemanticGremlinClient
with SemanticGremlinClient("ws://127.0.0.1:8182/gremlin") as client:
checkout = client.query(
lambda g: g.V().has_label("service").has("service_name", "checkout")
)
dependencies = client.query(
lambda g: g.V()
.has_label("service")
.has("service_name", "checkout")
.out("calls")
)
The typed client accepts only element-producing traversals and returns
generated semantic entity or edge models. Use gremlin-python directly for
intentional scalar, aggregate, map, or path results.
Labels are generated from semantic types: service.instance becomes
service_instance, k8s.pod becomes k8s_pod, and relationship calls
remains calls. Canonical fields remain under attributes and metrics, while
scalar Gremlin properties use aliases such as service_name, k8s_pod_uid,
and service_graph_request_total.
Gremlin is a trusted internal interface. Evaluation timeout and JVM resources
bound individual requests, but clients can still issue expensive traversals.
Do not expose port 8182 as an unauthenticated public endpoint.
Replacement rollout¶
- Uninstall
servicegraph-access. - Leave Flink, its state, and
graph.elements.eventsrunning. - Prepare ArangoDB and writer/reader credentials.
- Install the indexer. Its new consumer group
servicegraph-arangodb-indexerreplays the compacted topic from earliest. - Install Gremlin Server and validate traversals.
- Remove externally managed Elasticsearch only after the new projection has caught up and consumers have moved.
No Flink checkpoint, savepoint, fixed job ID, source group, or output topic is reset by this replacement.