Attach kubernetes attributes to traces blogpost (#1454)
* Attach kubernetes attributes to traces blogpost Signed-off-by: Ruben Vargas <ruben.vp8510@gmail.com> * Update content/en/blog/2022/k8sattributes.md Co-authored-by: Phillip Carter <pcarter@fastmail.com> * Run markdown prettifier and made some copyedits * address some comments Signed-off-by: Ruben Vargas <ruben.vp8510@gmail.com> * address comments about resources vs attributes Signed-off-by: Ruben Vargas <ruben.vp8510@gmail.com> * change to internal url Signed-off-by: Ruben Vargas <ruben.vp8510@gmail.com> * update date, title and linktitle Signed-off-by: Ruben Vargas <ruben.vp8510@gmail.com> * minor changes Signed-off-by: Ruben Vargas <ruben.vp8510@gmail.com> * Update content/en/blog/2022/k8sattributes.md Co-authored-by: Phillip Carter <pcarter@fastmail.com> * Update content/en/blog/2022/k8sattributes.md Co-authored-by: Phillip Carter <pcarter@fastmail.com> * Update content/en/blog/2022/k8sattributes.md Co-authored-by: Phillip Carter <pcarter@fastmail.com> * Update content/en/blog/2022/k8sattributes.md Co-authored-by: Phillip Carter <pcarter@fastmail.com> * Update content/en/blog/2022/k8sattributes.md Co-authored-by: Phillip Carter <pcarter@fastmail.com> * Update content/en/blog/2022/k8sattributes.md Co-authored-by: Phillip Carter <pcarter@fastmail.com> * Update content/en/blog/2022/k8sattributes.md Co-authored-by: Phillip Carter <pcarter@fastmail.com> * Update content/en/blog/2022/k8sattributes.md Co-authored-by: Phillip Carter <pcarter@fastmail.com> * Update content/en/blog/2022/k8sattributes.md Co-authored-by: Phillip Carter <pcarter@fastmail.com> * rephrase from attach spans to attach to resources Signed-off-by: Ruben Vargas <ruben.vp8510@gmail.com> * improvments to paragraphs Signed-off-by: Ruben Vargas <ruben.vp8510@gmail.com> * Update content/en/blog/2022/k8sattributes.md Co-authored-by: Phillip Carter <pcarter@fastmail.com> * Update content/en/blog/2022/k8sattributes.md Co-authored-by: Phillip Carter <pcarter@fastmail.com> * Update content/en/blog/2022/k8sattributes.md Co-authored-by: Phillip Carter <pcarter@fastmail.com> * Update content/en/blog/2022/k8sattributes.md Co-authored-by: Phillip Carter <pcarter@fastmail.com> * Update content/en/blog/2022/k8sattributes.md Co-authored-by: Phillip Carter <pcarter@fastmail.com> * Update content/en/blog/2022/k8sattributes.md Co-authored-by: Phillip Carter <pcarter@fastmail.com> * Update content/en/blog/2022/k8sattributes.md Co-authored-by: Phillip Carter <pcarter@fastmail.com> * Update content/en/blog/2022/k8sattributes.md Co-authored-by: Phillip Carter <pcarter@fastmail.com> * Update content/en/blog/2022/k8sattributes.md Co-authored-by: Phillip Carter <pcarter@fastmail.com> * Update content/en/blog/2022/k8sattributes.md Co-authored-by: Phillip Carter <pcarter@fastmail.com> * Update content/en/blog/2022/k8sattributes.md Co-authored-by: Phillip Carter <pcarter@fastmail.com> * Update content/en/blog/2022/k8sattributes.md Co-authored-by: Phillip Carter <pcarter@fastmail.com> * Update content/en/blog/2022/k8sattributes.md Co-authored-by: Phillip Carter <pcarter@fastmail.com> * improve conclusions Signed-off-by: Ruben Vargas <ruben.vp8510@gmail.com> * Copyedits * Run prettifier * Add link definition * Fix app spelling * address comments Signed-off-by: Ruben Vargas <ruben.vp8510@gmail.com> * address more comments Signed-off-by: Ruben Vargas <ruben.vp8510@gmail.com> * Update content/en/blog/2022/k8sattributes.md Co-authored-by: Patrice Chalin <chalin@users.noreply.github.com> * More comments Signed-off-by: Ruben Vargas <ruben.vp8510@gmail.com> * Copyedits - fix use of link def and vert.x app name * change diagram Signed-off-by: Ruben Vargas <ruben.vp8510@gmail.com> * change name of files Signed-off-by: Ruben Vargas <ruben.vp8510@gmail.com> * Use today's date Co-authored-by: Patrice Chalin <chalin@users.noreply.github.com>
This commit is contained in:
parent
ae690a7e5e
commit
3a417e1cfb
|
@ -0,0 +1,260 @@
|
||||||
|
---
|
||||||
|
title: Improved troubleshooting using k8s metadata
|
||||||
|
linkTitle: Kubernetes metadata
|
||||||
|
date: 2022-06-29
|
||||||
|
author: Ruben Vargas
|
||||||
|
spelling:
|
||||||
|
cSpell:ignore k8sattributes k8sattributesprocessor K8sattributes k8sprocessor
|
||||||
|
cSpell:ignore K8sprocessor KUBE
|
||||||
|
---
|
||||||
|
|
||||||
|
Attaching Kubernetes resource metadata to OpenTelemetry traces is useful to
|
||||||
|
identify which resource (such as a pod) is failing or having performance
|
||||||
|
problems. It is also useful for correlating across other signals, for example:
|
||||||
|
you can correlated logs and spans that were generated by the same pod.
|
||||||
|
|
||||||
|
In this article, you'll learn how to configure the OpenTelemetry collector to
|
||||||
|
use the [k8sattributesprocessor][] in different scenarios.
|
||||||
|
|
||||||
|
Details of the OpenTelemetry collector pipeline won't be covered in this post.
|
||||||
|
For those details, refer to the [collector documentation](/docs/collector/).
|
||||||
|
|
||||||
|
## How k8s attributes are attached
|
||||||
|
|
||||||
|
At a high level, k8s attributes are attached to traces as
|
||||||
|
[resources](/docs/concepts/glossary/#resource). This is for two reasons:
|
||||||
|
|
||||||
|
1. K8s attributes fit the definition of what a resource is: an entity for which
|
||||||
|
telemetry is recorded
|
||||||
|
2. It centralizes this metadata, which is relevant for any generated span.
|
||||||
|
|
||||||
|
Let's dive in and see how to do it!
|
||||||
|
|
||||||
|
## Using k8sattributes processor
|
||||||
|
|
||||||
|
This is an OpenTelemetry processor that automatically discovers pod metadata and
|
||||||
|
attaches it to a resource associated with the spans generated by that pod. If
|
||||||
|
the pod belongs to a `Deployment` or a `ReplicaSet`, it will also discover it's
|
||||||
|
attributes.
|
||||||
|
|
||||||
|
Some attributes we can attach to the resource are:
|
||||||
|
|
||||||
|
- Node name `k8s.node.name`
|
||||||
|
- Pod name `k8s.pod.name`
|
||||||
|
- Pod UID `k8s.pod.uid`
|
||||||
|
- Namespace `k8s.namespace.name`
|
||||||
|
- Deployment name, `k8s.deployment.name` if the pod was created by a deployment
|
||||||
|
|
||||||
|
Such attributes adhere to OpenTelemetry semantic conventions. For details, see
|
||||||
|
the [Kubernetes resource semantic conventions][].
|
||||||
|
|
||||||
|
The processor internally maintains a list of pods and an associated attribute,
|
||||||
|
usually the IP address of the pod, and uses this attribute to know which pod
|
||||||
|
generates a certain span.
|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
|
In the figure above you can see how the data flows: The table of pods is fetched
|
||||||
|
using Kubernetes API, while the pod IP is extracted from the connection context
|
||||||
|
between the pod and the collector.
|
||||||
|
|
||||||
|
The `k8sattributesprocessor` can work in different modes depending on how the
|
||||||
|
collector is configured. Let's explore one common scenario, when the collector
|
||||||
|
is deployed as daemonset.
|
||||||
|
|
||||||
|
### Daemonset mode
|
||||||
|
|
||||||
|
Let’s take a look at how we can configure the collector in daemonset mode, also
|
||||||
|
known as an agent mode in the k8sattributes documentation.
|
||||||
|
|
||||||
|
When we deploy the collector in daemonset mode, we have one collector pod per
|
||||||
|
node. We need to configure the collector service account to have permissions to
|
||||||
|
fetch all pod information. In order to do that, we will create a `ClusterRole`
|
||||||
|
with the necessary permissions.
|
||||||
|
|
||||||
|
Here are the minimum permissions required to make the `k8sattributesprocessor`
|
||||||
|
work:
|
||||||
|
|
||||||
|
```yaml
|
||||||
|
apiVersion: rbac.authorization.k8s.io/v1
|
||||||
|
kind: ClusterRole
|
||||||
|
metadata:
|
||||||
|
name: otel-collector
|
||||||
|
rules:
|
||||||
|
- apiGroups: [""]
|
||||||
|
resources: ["pods", "namespaces"]
|
||||||
|
verbs: ["get", "watch", "list"]
|
||||||
|
```
|
||||||
|
|
||||||
|
Next, deploy the collector in daemonset mode. We recommend that you set a filter
|
||||||
|
to only fetch the pods that belong to the node in which the collector is
|
||||||
|
deployed. This is because if you have a large cluster, you don’t want to
|
||||||
|
maintain a huge list of pods.
|
||||||
|
|
||||||
|
This is the manifest used in this blog to show how the processor works:
|
||||||
|
|
||||||
|
```yaml
|
||||||
|
apiVersion: opentelemetry.io/v1alpha1
|
||||||
|
kind: OpenTelemetryCollector
|
||||||
|
metadata:
|
||||||
|
name: otel-collector-daemonset
|
||||||
|
spec:
|
||||||
|
mode: daemonset
|
||||||
|
image: ghcr.io/open-telemetry/opentelemetry-collector-releases/opentelemetry-collector-contrib:0.47.0
|
||||||
|
serviceAccount: attributes-account
|
||||||
|
env:
|
||||||
|
- name: KUBE_NODE_NAME
|
||||||
|
valueFrom:
|
||||||
|
fieldRef:
|
||||||
|
apiVersion: v1
|
||||||
|
fieldPath: spec.nodeName
|
||||||
|
config: |
|
||||||
|
receivers:
|
||||||
|
jaeger:
|
||||||
|
protocols:
|
||||||
|
grpc:
|
||||||
|
thrift_binary:
|
||||||
|
thrift_compact:
|
||||||
|
thrift_http:
|
||||||
|
otlp:
|
||||||
|
protocols:
|
||||||
|
grpc:
|
||||||
|
http:
|
||||||
|
|
||||||
|
processors:
|
||||||
|
k8sattributes:
|
||||||
|
filter:
|
||||||
|
node_from_env_var: KUBE_NODE_NAME
|
||||||
|
exporters:
|
||||||
|
jaeger:
|
||||||
|
endpoint: jaeger-all-in-one-collector:14250
|
||||||
|
tls:
|
||||||
|
insecure: true
|
||||||
|
|
||||||
|
service:
|
||||||
|
pipelines:
|
||||||
|
traces:
|
||||||
|
receivers: [otlp, jaeger]
|
||||||
|
processors: [k8sattributes]
|
||||||
|
exporters: [jaeger]
|
||||||
|
```
|
||||||
|
|
||||||
|
The main parts to note are that it uses the contrib collector image. The
|
||||||
|
`k8sattributesprocessor` is not part of the OpenTelemetry collector core, but
|
||||||
|
the contrib distribution has it. Other things to notice are the filter mentioned
|
||||||
|
above, and the use of a previously-created specific service account, which
|
||||||
|
contains the permissions to fetch the pod list.
|
||||||
|
|
||||||
|
Next, deploy the manifest and the [vert.x example app][] to generate some
|
||||||
|
traces.
|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
|
As you can see, each span of the trace now has the corresponding pod attributes
|
||||||
|
attached to it.
|
||||||
|
|
||||||
|
You can restrict the configuration above to a certain namespace if you add the
|
||||||
|
namespace on the `k8sattributesprocessor` filter like this:
|
||||||
|
|
||||||
|
```yaml
|
||||||
|
processors:
|
||||||
|
k8sattributes:
|
||||||
|
filter:
|
||||||
|
namespace: my_namespace
|
||||||
|
```
|
||||||
|
|
||||||
|
In this way, you can create a `Role` and don’t need to create a `ClusterRole`,
|
||||||
|
reducing the scope of the collector service account to a single namespace.
|
||||||
|
|
||||||
|
## Using Resource detector processor
|
||||||
|
|
||||||
|
As of [recently][pr#832], the [OpenTelemetry operator][] sets the
|
||||||
|
`OTEL_RESOURCE_ATTRIBUTES` environment variable on the collector container with
|
||||||
|
the k8s pod attributes. This lets you to use the resource detector processor,
|
||||||
|
which attaches the environment variable values to the spans. This only works
|
||||||
|
when the collector is deployed in sidecar mode.
|
||||||
|
|
||||||
|
For example, if you deploy the following manifest:
|
||||||
|
|
||||||
|
```yaml
|
||||||
|
apiVersion: opentelemetry.io/v1alpha1
|
||||||
|
kind: OpenTelemetryCollector
|
||||||
|
metadata:
|
||||||
|
name: sidecar-for-my-app
|
||||||
|
spec:
|
||||||
|
mode: sidecar
|
||||||
|
image: ghcr.io/open-telemetry/opentelemetry-collector-releases/opentelemetry-collector-contrib:0.47.0
|
||||||
|
config: |
|
||||||
|
receivers:
|
||||||
|
jaeger:
|
||||||
|
protocols:
|
||||||
|
grpc:
|
||||||
|
thrift_binary:
|
||||||
|
thrift_compact:
|
||||||
|
thrift_http:
|
||||||
|
otlp:
|
||||||
|
protocols:
|
||||||
|
grpc:
|
||||||
|
http:
|
||||||
|
|
||||||
|
processors:
|
||||||
|
resourcedetection:
|
||||||
|
detectors: [env]
|
||||||
|
timeout: 2s
|
||||||
|
override: false
|
||||||
|
|
||||||
|
exporters:
|
||||||
|
jaeger:
|
||||||
|
endpoint: jaeger-all-in-one-collector:14250
|
||||||
|
tls:
|
||||||
|
insecure: true
|
||||||
|
|
||||||
|
service:
|
||||||
|
pipelines:
|
||||||
|
traces:
|
||||||
|
receivers: [otlp, jaeger]
|
||||||
|
processors: [resourcedetection]
|
||||||
|
exporters: [jaeger]
|
||||||
|
```
|
||||||
|
|
||||||
|
And then deploy the [vert.x app example][], you can see the
|
||||||
|
`OTEL_RESOURCE_ATTRIBUTES` environment variable gets injected with some values
|
||||||
|
in the sidecar container. Some of them use the Kubernetes downward API to get
|
||||||
|
the attribute values.
|
||||||
|
|
||||||
|
Here's an example of the value of the environment variable:
|
||||||
|
|
||||||
|
```yaml
|
||||||
|
- name: OTEL_RESOURCE_ATTRIBUTES
|
||||||
|
value: k8s.deployment.name=dep-vert-x,k8s.deployment.uid=ef3fe26b-a690-4746-9119-d2dbd94b469f,
|
||||||
|
k8s.namespace.name=default,k8s.node.name=$(OTEL_RESOURCE_ATTRIBUTES_NODE_NAME),k8s.pod.name=
|
||||||
|
(OTEL_RESOURCE_ATTRIBUTES_POD_NAME),k8s.pod.uid=$(OTEL_RESOURCE_ATTRIBUTES_POD_UID),k8s.replicaset
|
||||||
|
name=dep-vert-x-59b6f76585,k8s.replicaset.uid=5127bc38-e298-40e1-95df-f4a777e3176c
|
||||||
|
```
|
||||||
|
|
||||||
|
## Learn more
|
||||||
|
|
||||||
|
This post covers how to configure the OpenTelemetry collector to attach
|
||||||
|
Kubernetes resource metadata as resource attributes to OpenTelemetry traces. The
|
||||||
|
scenarios covered, although basic, illustrate how to add this kind of metadata
|
||||||
|
to traces so that you can incorporate the technique into other more
|
||||||
|
sophisticated scenarios. If you want to learn more about different scenarios or
|
||||||
|
options for configure the processors you can see the [K8sattributes processor
|
||||||
|
documentation][k8sattributesprocessor] where you can find more scenarios like
|
||||||
|
sidecar, or when one collector as an agent report to another collector.
|
||||||
|
|
||||||
|
## References
|
||||||
|
|
||||||
|
- [K8sattributes processor documentation][k8sattributesprocessor]
|
||||||
|
- [K8sattributes processor RBAC](https://pkg.go.dev/github.com/open-telemetry/opentelemetry-collector-contrib/processor/k8sattributesprocessor#hdr-RBAC)
|
||||||
|
- [OpenTelemetry Kubernetes attributes](/docs/reference/specification/resource/semantic_conventions/k8s)
|
||||||
|
- [Resource detector processor](https://github.com/open-telemetry/opentelemetry-collector-contrib/blob/main/processor/resourcedetectionprocessor/README.md)
|
||||||
|
|
||||||
|
[pr#832]: https://github.com/open-telemetry/opentelemetry-operator/pull/832
|
||||||
|
[opentelemetry operator]:
|
||||||
|
https://github.com/open-telemetry/opentelemetry-operator
|
||||||
|
[k8sattributesprocessor]:
|
||||||
|
https://pkg.go.dev/github.com/open-telemetry/opentelemetry-collector-contrib/processor/k8sattributesprocessor
|
||||||
|
[kubernetes resource semantic conventions]:
|
||||||
|
/docs/reference/specification/resource/semantic_conventions/k8s
|
||||||
|
[vert.x example app]: https://github.com/jaegertracing/vertx-create-span
|
Binary file not shown.
After Width: | Height: | Size: 154 KiB |
Binary file not shown.
After Width: | Height: | Size: 49 KiB |
Loading…
Reference in New Issue