# Kubernetes

> Collector DaemonSet, or fan out from a collector you already run

## Already running a collector? Just fan out

If you already run an OpenTelemetry Collector, you do not need another one. Add
Rocketgraph as an **additional exporter**. Your current backend keeps receiving
everything and Rocketgraph gets a copy — no cutover, nothing to roll back.

```yaml
exporters:
  # ...your existing exporters unchanged...
  otlphttp/rocketgraph:
    endpoint: https://ingress.rocketlog.io
    headers:
      Authorization: "Bearer rg_live_xxxxxx"

service:
  pipelines:
    traces:  { exporters: [<your-existing-exporter>, otlphttp/rocketgraph] }
    metrics: { exporters: [<your-existing-exporter>, otlphttp/rocketgraph] }
    logs:    { exporters: [<your-existing-exporter>, otlphttp/rocketgraph] }
```

Each pipeline's `exporters` is a list, so Rocketgraph sits alongside your current backend.

## Fresh install with Helm

```bash
kubectl create secret generic rocketgraph \
  --from-literal=api-key='rg_live_xxxxxx' \
  -n observability

helm repo add open-telemetry https://open-telemetry.github.io/opentelemetry-helm-charts
helm repo update
helm install otel-collector open-telemetry/opentelemetry-collector \
  -n observability -f values.yaml
```

```yaml values.yaml
mode: daemonset

image:
  repository: otel/opentelemetry-collector-contrib

extraEnvs:
  - name: ROCKETGRAPH_API_KEY
    valueFrom:
      secretKeyRef: { name: rocketgraph, key: api-key }

presets:
  logsCollection:      { enabled: true }
  kubernetesAttributes: { enabled: true }
  hostMetrics:          { enabled: true }

config:
  exporters:
    otlphttp/rocketgraph:
      endpoint: https://ingress.rocketlog.io
      headers:
        Authorization: "Bearer ${ROCKETGRAPH_API_KEY}"
  service:
    pipelines:
      traces:  { exporters: [otlphttp/rocketgraph] }
      metrics: { exporters: [otlphttp/rocketgraph] }
      logs:    { exporters: [otlphttp/rocketgraph] }
```

> **Note:** `kubernetesAttributes` is what attaches pod, namespace, node and deployment names to
  every record. Without it you cannot tell which pod produced a log line.

## Point your apps at the collector

The DaemonSet listens on the node. Send to the host IP rather than a service name so
traffic stays on-node:

```yaml
env:
  - name: OTEL_EXPORTER_OTLP_ENDPOINT
    value: "http://$(HOST_IP):4318"
  - name: HOST_IP
    valueFrom:
      fieldRef: { fieldPath: status.hostIP }
  - name: OTEL_EXPORTER_OTLP_PROTOCOL
    value: "http/protobuf"
  - name: OTEL_SERVICE_NAME
    value: "my-service"
```

## Zero-code instrumentation with the Operator

The OpenTelemetry Operator injects language agents into pods via an annotation — no
Dockerfile changes.

```bash
kubectl apply -f https://github.com/open-telemetry/opentelemetry-operator/releases/latest/download/opentelemetry-operator.yaml
```

```yaml
apiVersion: opentelemetry.io/v1alpha1
kind: Instrumentation
metadata:
  name: rocketgraph
spec:
  exporter:
    endpoint: http://otel-collector.observability.svc.cluster.local:4318
  propagators: [tracecontext, baggage]
  sampler:
    type: parentbased_traceidratio
    argument: "1.0"
```

Then annotate a Deployment's **pod template**:

```yaml
spec:
  template:
    metadata:
      annotations:
        instrumentation.opentelemetry.io/inject-java: "rocketgraph"
        # or inject-nodejs / inject-python / inject-dotnet
```

> **Warning:** The annotation goes on the pod template (`spec.template.metadata`), not on the Deployment
  itself. Put it in the wrong place and nothing is injected and no error is raised.
