Kubernetes
Deploy the OpenTelemetry Collector on Kubernetes to send traces, logs, and metrics to Talaria.
What you're setting up
The OpenTelemetry Collector runs as a DaemonSet (logs, kubelet metrics, and trace relay) and optionally as a Deployment (cluster-wide metrics like pod phase and CronJob status). You'll install it with the upstream opentelemetry-collector Helm chart, pointing at Talaria's OTLP endpoint.
Why use this
- Logs: Automatically collect container stdout/stderr from all pods
- Metrics: Pod CPU, memory, restarts, and CronJob success/failure. Note: Gauge alerts use the latest value over 15 minutes. LogRate alerts count error-level logs only (severity ≥ 17), have no environment filter, and filter on service only. Logs and metrics cannot be filtered by environment.
- Traces: Relay OTLP traces from instrumented apps to Talaria. Note: OTLP export uses HTTP only (
otlp_http); gRPC is not supported. - Resource enrichment: Attach
k8s.namespace.name,k8s.deployment.name,k8s.pod.nameto every signal
Before you start
- Get a secret key from Project settings › API keys. It should start with
tal_sk_prod_nz1_…(production),tal_sk_stg_nz1_…(staging),tal_sk_test_nz1_…(test), ortal_sk_dev_nz1_…(development). - Decide your service name: This will appear in Runtime as the top-level grouping (e.g.,
checkout-api,background-jobs). - Have
kubectland Helm 3 ready.
Steps
1. Set the environment variables
Store the secret key so the Collector can reference it:
kubectl create secret generic talaria-ingest \
--from-literal=api-key=tal_sk_prod_nz1_… \
--namespace=opentelemetry-collectorReplace tal_sk_prod_nz1_… with your actual key.
If your application pods send telemetry directly (not just via the collector), they need the secret key too. Add it to their Deployment env::
env:
- name: TALARIA_API_KEY
valueFrom:
secretKeyRef:
name: talaria-ingest
key: api-key2. Pass the release to the runtime
Set the release on your application pods so events are tagged with the deployed version. Use service.version in OpenTelemetry resource attributes or the OTEL_RESOURCE_ATTRIBUTES environment variable:
env:
- name: OTEL_RESOURCE_ATTRIBUTES
value: "service.version=v1.2.3"This tags traces, logs, and errors with the release, making it easier to correlate issues with deployments.
3. Collect logs
Add the OpenTelemetry Helm repository:
helm repo add open-telemetry https://open-telemetry.github.io/opentelemetry-helm-charts
helm repo updateCreate a values.yaml file with the Talaria configuration:
# values.yaml for opentelemetry-collector
image:
repository: otel/opentelemetry-collector-contrib
tag: "0.164.0"
mode: daemonset
presets:
logsCollection:
enabled: true
kubernetesAttributes:
enabled: true
kubeletMetrics:
enabled: true
config:
exporters:
otlp_http:
endpoint: https://ingest-nz1.newtalaria.com/otlp
headers:
Authorization: Bearer ${env:TALARIA_API_KEY}
compression: gzip
processors:
resource:
attributes:
- key: service.name
from_attribute: k8s.deployment.name
action: insert
batch: {}
k8sattributes:
passthrough: false
service:
pipelines:
traces:
receivers: [otlp]
processors: [k8sattributes, resource, batch]
exporters: [otlp_http]
logs:
receivers: [otlp, filelog]
processors: [k8sattributes, resource, batch]
exporters: [otlp_http]
metrics:
receivers: [otlp, kubeletstats]
processors: [k8sattributes, resource, batch]
exporters: [otlp_http]
env:
- name: TALARIA_API_KEY
valueFrom:
secretKeyRef:
name: talaria-ingest
key: api-key
- name: OTEL_SERVICE_NAME
value: "k8s-collector"Install the chart:
helm install opentelemetry-collector open-telemetry/opentelemetry-collector \
--namespace opentelemetry-collector \
--create-namespace \
--values values.yamlOptional: Cluster-wide metrics
For cluster-wide metrics (pod phase, CronJob success/failure), add a second Collector in Deployment mode with the k8s_cluster receiver:
# values-cluster.yaml
image:
repository: otel/opentelemetry-collector-contrib
tag: "0.164.0"
mode: deployment
replicaCount: 1
config:
receivers:
k8s_cluster:
auth_type: serviceAccount
node_conditions_to_report: [Ready, MemoryPressure, DiskPressure]
allocatable_types_to_report: [cpu, memory, storage]
exporters:
otlp_http:
endpoint: https://ingest-nz1.newtalaria.com/otlp
headers:
Authorization: Bearer ${env:TALARIA_API_KEY}
compression: gzip
processors:
resource:
attributes:
- key: service.name
from_attribute: k8s.deployment.name
action: insert
batch: {}
service:
pipelines:
metrics:
receivers: [k8s_cluster]
processors: [resource, batch]
exporters: [otlp_http]
env:
- name: TALARIA_API_KEY
valueFrom:
secretKeyRef:
name: talaria-ingest
key: api-key
rbac:
create: true
rules:
- apiGroups: [""]
resources: [events, namespaces, namespaces/status, nodes, nodes/spec, pods, pods/status, replicationcontrollers, replicationcontrollers/status, resourcequotas, services]
verbs: [get, list, watch]
- apiGroups: [apps]
resources: [daemonsets, deployments, replicasets, statefulsets]
verbs: [get, list, watch]
- apiGroups: [batch]
resources: [jobs, cronjobs]
verbs: [get, list, watch]Install it:
helm install opentelemetry-cluster open-telemetry/opentelemetry-collector \
--namespace opentelemetry-collector \
--values values-cluster.yamlThis receiver emits k8s.job.failed_pods and k8s.cronjob.active_jobs, which you can alert on.
4. Check in from scheduled jobs
For explicit job health tracking beyond metrics, have your CronJob send check-ins to Talaria Monitors. Create a monitor token from the dashboard (Monitors › Create monitor), then add it as a Secret:
kubectl create secret generic talaria-import-monitor \
--from-literal=monitor-token=tal_mon_nz1_… \
--namespace=defaultUpdate your CronJob to call the check-in endpoint:
apiVersion: batch/v1
kind: CronJob
metadata:
name: nightly-import
spec:
schedule: "0 2 * * *"
jobTemplate:
spec:
template:
spec:
restartPolicy: Never
containers:
- name: import
image: example/import:1
env:
- name: TALARIA_MONITOR_TOKEN
valueFrom:
secretKeyRef:
name: talaria-import-monitor
key: monitor-token
command:
- /bin/sh
- -c
- |
# Send in_progress
curl -fsS -X POST "https://ingest-nz1.newtalaria.com/v1/check-ins" \
-H "Authorization: Bearer $TALARIA_MONITOR_TOKEN" \
-H "Content-Type: application/json" \
-d '{"status":"in_progress"}'
# Run the job
/app/import
status=$?
# Send ok or error
if [ "$status" -eq 0 ]; then
curl -fsS -X POST "https://ingest-nz1.newtalaria.com/v1/check-ins" \
-H "Authorization: Bearer $TALARIA_MONITOR_TOKEN" \
-H "Content-Type: application/json" \
-d '{"status":"ok"}'
else
curl -fsS -X POST "https://ingest-nz1.newtalaria.com/v1/check-ins" \
-H "Authorization: Bearer $TALARIA_MONITOR_TOKEN" \
-H "Content-Type: application/json" \
-d '{"status":"error"}'
fi
exit "$status"The monitor is created via the dashboard or by sending the first check-in with crontab, timezone, marginSeconds, and maxRuntimeSeconds in the body.
Check it worked
-
View logs in Runtime:
- Go to Projects › › Runtime
- You should see service rows for your cluster (grouped by
service.namewhich is set fromk8s.deployment.namevia the resource processor) - Click a service to see logs
-
Verify metrics:
- Check that
k8s.pod.cpu.utilization,k8s.container.memory.usage, andk8s.container.restartsmetrics appear - If you installed the cluster receiver, check for
k8s.job.failed_pods
- Check that
-
Verify traces (if your app is instrumented):
- Go to Performance
- Traces from your pods should appear with
k8s.pod.nameandk8s.deployment.nameattributes
Using MCP:
Tool: search_logs
Parameters: { service: "<your-deployment-name>", limit: 10 }
Expected: Log records with k8s.namespace.name and k8s.pod.name attributesReplace <your-deployment-name> with your actual deployment name. The service value comes from service.name, which the resource processor sets from k8s.deployment.name.
Troubleshooting
Logs aren't appearing
Cause: The Collector DaemonSet might not have permissions to read container logs, or logsCollection preset is disabled.
Fix:
- Check Collector logs:
bash
kubectl logs -n opentelemetry-collector -l app.kubernetes.io/name=opentelemetry-collector - Verify the
logsCollectionpreset isenabled: truein yourvalues.yaml. - Ensure the Collector has RBAC permissions to read pod logs.
Metrics show no k8s.* attributes
Cause: The k8sattributes processor isn't wired into the pipeline, or kubernetesAttributes preset is disabled.
Fix:
- Verify
presets.kubernetesAttributes.enabled: truein yourvalues.yaml. - Check that
k8sattributesappears in all three pipelineprocessorslists (traces, logs, metrics). - Restart the Collector:
bash
kubectl rollout restart deployment/opentelemetry-collector -n opentelemetry-collector
Exporter returns 500 errors
Cause: The endpoint is set to https://ingest-nz1.newtalaria.com (without /otlp), so the Collector posts to /v1/logs instead of /otlp/v1/logs.
Fix: Set endpoint: https://ingest-nz1.newtalaria.com/otlp in the exporter config. The OTLP spec requires the Collector to append /v1/{traces,logs,metrics} to the base URL.
CronJob check-ins aren't showing up in Monitors
Cause: The endpoint or header name is wrong, or the monitor token is invalid.
Fix:
- Check the CronJob logs for HTTP errors:
bash
kubectl logs -n default job/<job-name> - Verify the endpoint is
https://ingest-nz1.newtalaria.com/v1/check-ins. - Verify the header is
Authorization: Bearer. - Regenerate the monitor token from the dashboard if it was revoked.
Next steps
- Monitors — Track job health with check-ins
- Runtime health — Monitor app health and performance
For agents
This task includes MCP tool verification. Use search_logs with service: "<your-deployment-name>" (matching your actual deployment name) to confirm log ingestion from the Kubernetes collector. The service value comes from service.name, which is set from k8s.deployment.name by the resource processor.