Switch it on
Run a Collector on the control-plane node, then add /etc/kubernetes/tracing.yaml there
and point the API server at it in its static pod manifest. Saving the manifest restarts the
API server, and every request after that becomes a trace that includes each admission
webhook it waited on. Needs Kubernetes 1.34 or newer.
Save this as otel-collector.yaml:
apiVersion: v1
kind: ConfigMap
metadata:
name: otel-collector
namespace: kube-system
data:
config.yaml: |
receivers:
otlp:
protocols:
grpc:
endpoint: localhost:4317
exporters:
otlp_http:
endpoint: https://ingestion.eu.bronto.io
headers:
x-bronto-api-key: ${env:BRONTO_API_KEY}
service:
pipelines:
traces:
receivers: [otlp]
exporters: [otlp_http]
---
apiVersion: apps/v1
kind: DaemonSet
metadata:
name: otel-collector
namespace: kube-system
spec:
selector:
matchLabels:
app: otel-collector
template:
metadata:
labels:
app: otel-collector
spec:
hostNetwork: true
nodeSelector:
node-role.kubernetes.io/control-plane: ""
tolerations:
- key: node-role.kubernetes.io/control-plane
effect: NoSchedule
containers:
- name: otel-collector
image: otel/opentelemetry-collector-contrib:0.158.0
args: [--config=/etc/otelcol/config.yaml]
envFrom:
- secretRef:
name: bronto
volumeMounts:
- name: config
mountPath: /etc/otelcol
volumes:
- name: config
configMap:
name: otel-collector
In a terminal:
kubectl -n kube-system create secret generic bronto \
--from-literal=BRONTO_API_KEY="$BRONTO_API_KEY"
kubectl apply -f otel-collector.yaml
On the node, /etc/kubernetes/tracing.yaml:
apiVersion: apiserver.config.k8s.io/v1
kind: TracingConfiguration
samplingRatePerMillion: 1000000
In /etc/kubernetes/manifests/kube-apiserver.yaml:
command:
- kube-apiserver
+ - --tracing-config-file=/etc/kubernetes/tracing.yaml
…
volumeMounts:
+ - mountPath: /etc/kubernetes/tracing.yaml
+ name: tracing
…
volumes:
+ - hostPath:
+ path: /etc/kubernetes/tracing.yaml
+ name: tracing
On the node, /etc/kubernetes/tracing.yaml:
apiVersion: apiserver.config.k8s.io/v1
kind: TracingConfiguration
samplingRatePerMillion: 1000000
In /etc/kubernetes/manifests/kube-apiserver.yaml:
command:
- kube-apiserver
+ - --tracing-config-file=/etc/kubernetes/tracing.yaml
…
volumeMounts:
+ - mountPath: /etc/kubernetes/tracing.yaml
+ name: tracing
…
volumes:
+ - hostPath:
+ path: /etc/kubernetes/tracing.yaml
+ name: tracing
This assumes the Local Collector running on the control-plane node,
with a grpc receiver on localhost:4317 in place of http.
This uses the endpoint and auth header you saved in the setup guide.
Save this as otel-collector.yaml:
apiVersion: v1
kind: ConfigMap
metadata:
name: otel-collector
namespace: kube-system
data:
config.yaml: |
receivers:
otlp:
protocols:
grpc:
endpoint: localhost:4317
exporters:
otlp_http:
endpoint: YOUR_OTLP_ENDPOINT
headers:
YOUR_AUTH_HEADER: YOUR_AUTH_VALUE
service:
pipelines:
traces:
receivers: [otlp]
exporters: [otlp_http]
---
apiVersion: apps/v1
kind: DaemonSet
metadata:
name: otel-collector
namespace: kube-system
spec:
selector:
matchLabels:
app: otel-collector
template:
metadata:
labels:
app: otel-collector
spec:
hostNetwork: true
nodeSelector:
node-role.kubernetes.io/control-plane: ""
tolerations:
- key: node-role.kubernetes.io/control-plane
effect: NoSchedule
containers:
- name: otel-collector
image: otel/opentelemetry-collector-contrib:0.158.0
args: [--config=/etc/otelcol/config.yaml]
volumeMounts:
- name: config
mountPath: /etc/otelcol
volumes:
- name: config
configMap:
name: otel-collector
In a terminal:
kubectl apply -f otel-collector.yaml
On the node, /etc/kubernetes/tracing.yaml:
apiVersion: apiserver.config.k8s.io/v1
kind: TracingConfiguration
samplingRatePerMillion: 1000000
In /etc/kubernetes/manifests/kube-apiserver.yaml:
command:
- kube-apiserver
+ - --tracing-config-file=/etc/kubernetes/tracing.yaml
…
volumeMounts:
+ - mountPath: /etc/kubernetes/tracing.yaml
+ name: tracing
…
volumes:
+ - hostPath:
+ path: /etc/kubernetes/tracing.yaml
+ name: tracing