Skip to content
Merged
Show file tree
Hide file tree
Changes from 11 commits
Commits
Show all changes
23 commits
Select commit Hold shift + click to select a range
03f6d51
instrumenting-nodejs.md draft added
eedugon Nov 25, 2024
930a908
commented section made visible
eedugon Nov 25, 2024
933a774
getting started guide link updated
eedugon Nov 25, 2024
df8b32c
example removed
eedugon Nov 26, 2024
d2a8261
example removed
eedugon Nov 26, 2024
90f4db5
example removed
eedugon Nov 26, 2024
49f8239
example removed
eedugon Nov 26, 2024
c9da9b0
Merge branch 'main' into k8s_instrumenting_nodejs
eedugon Dec 3, 2024
4a15e4d
content aligned with other guides, indentation fixed, and Trent's sug…
eedugon Dec 3, 2024
890b8cb
pods made plural
eedugon Dec 3, 2024
366ee27
traffic generation tip added
eedugon Dec 3, 2024
b2be789
Update docs/kubernetes/operator/instrumenting-nodejs.md
eedugon Dec 4, 2024
dce176c
kubectl port-forward link added
eedugon Dec 4, 2024
4afebb4
Update docs/kubernetes/operator/instrumenting-nodejs.md
eedugon Dec 11, 2024
9c94031
Update docs/kubernetes/operator/instrumenting-nodejs.md
eedugon Dec 11, 2024
ccb8af5
Update docs/kubernetes/operator/instrumenting-nodejs.md
eedugon Dec 11, 2024
78a54d5
Update docs/kubernetes/operator/instrumenting-nodejs.md
eedugon Dec 11, 2024
5e0cfe1
indentation and minor fixes
eedugon Dec 11, 2024
543dd99
link to nodejs doc added in instrumenting_applications.md
eedugon Dec 11, 2024
2839fcc
link to nodejs doc added in instrumenting_applications.md
eedugon Dec 11, 2024
e5bbaae
removed port-forward hint because the user should know how to generat…
eedugon Dec 11, 2024
94b095e
Update docs/kubernetes/operator/instrumenting-nodejs.md
eedugon Dec 18, 2024
fbb486d
env var check sentence moved upwards
eedugon Dec 18, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 4 additions & 4 deletions docs/kubernetes/operator/instrumenting-applications.md
Original file line number Diff line number Diff line change
Expand Up @@ -170,13 +170,13 @@ Ensure that the `init container`, `volume`, and `environment variables` describe
The OpenTelemetry Operator automates the process of instrumenting applications by injecting the necessary libraries and configuration into the application Pods.
The process may vary slightly depending on the language, but it generally involves the following steps:

- **Adding an init container**:
- **Creating a shared volume**:

The operator adds an init container into the Pod. This container is responsible for copying the OpenTelemetry instrumentation library and make it accessible to the main application container.
The operator declares an `emptyDir` shared volume within the Pod, and mounts it the app container and a new init container. This volume serves as the medium for sharing the instrumentation library between the new init container and the application container.

- **Creating a shared volume**:
- **Adding an init container**:

The operator creates an `emptyDir` shared volume within the Pod, and mounts it in both containers. This volume serves as the medium for sharing the instrumentation library between the init container and the application container.
The operator adds an init container into the Pod. This container is responsible for copying the OpenTelemetry instrumentation library to the shared volume.

- **Configuring the main container**:

Expand Down
163 changes: 163 additions & 0 deletions docs/kubernetes/operator/instrumenting-nodejs.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,163 @@
# Instrumenting Node.js applications with EDOT SDKs on Kubernetes

This document focuses on instrumenting Node.js applications on Kubernetes, using the OpenTelemetry Operator, the Elastic Distribution of OpenTelemetry (EDOT) Collectors, and the [EDOT Node.js](https://github.com/elastic/elastic-otel-nodejs) SDK.

- For general knowledge about the EDOT Node.js SDK, refer to the [getting started guide](https://github.com/elastic/elastic-otel-node/blob/main/packages/opentelemetry-node/docs/get-started.md) and [configuration](https://github.com/elastic/elastic-otel-node/blob/main/packages/opentelemetry-node/docs/configure.md).
- For Node.js auto-instrumentation specifics, refer to [OpenTelemetry Operator Node.js auto-instrumentation](https://opentelemetry.io/docs/kubernetes/operator/automatic/#nodejs).
- For general information about instrumenting applications on kubernetes, refer to [instrumenting applications](./instrumenting-applications.md).

## Instrument a Node.js app with EDOT Node.js SDK on Kubernetes

<!--
Useful links:
- Example: https://github.com/elastic/elastic-otel-node/tree/main/examples/otel-operator/ documented at https://github.com/elastic/elastic-otel-node/blob/main/DEVELOPMENT.md#testing-k8s-auto-instrumentation-with-otel-operator
(not user friendly, but we could use it in the future if we want to add a proper example here)
-->

In this example, you'll learn how to:

- Enable auto-instrumentation of a Node.js application using one of the following supported methods:
- Adding an annotation to the deployment Pods.
- Adding an annotation to the namespace.
- Verify that auto-instrumentation libraries are injected and configured correctly.
- Confirm data is flowing to **Kibana Observability**.

For this example, we assume the application you're instrumenting is a deployment named `nodejs-app` running in the `nodejs-ns` namespace.

1. Ensure you have successfully [installed the OpenTelemetry Operator](./README.md), and confirm that the following `Instrumentation` object exists in the system:

```bash
$ kubectl get instrumentation -n opentelemetry-operator-system
NAME AGE ENDPOINT
elastic-instrumentation 107s http://opentelemetry-kube-stack-daemon-collector.opentelemetry-operator-system.svc.cluster.local:4318
```
> [!NOTE]
> If your `Instrumentation` object has a different name or is created in a different namespace, you will have to adapt the annotation value in the next step.

2. Enable auto-instrumentation of your Node.js application using one of the following methods:

- Edit your application workload definition and include the annotation under `spec.template.metadata.annotations`:

```yaml
kind: Deployment
metadata:
name: nodejs-app
namespace: nodejs-ns
spec:
...
template:
metadata:
...
annotations:
instrumentation.opentelemetry.io/inject-nodejs: opentelemetry-operator-system/elastic-instrumentation
...
```

- Alternatively, add the annotation at namespace level to apply auto-instrumentation in all Pods of the namespace:

```bash
kubectl annotate namespace nodejs-ns instrumentation.opentelemetry.io/inject-nodejs=opentelemetry-operator-system/elastic-instrumentation
```

3. Restart application

Once the annotation has been set, restart the application to create new Pods and inject the instrumentation libraries:

```bash
kubectl rollout restart deployment nodejs-app -n nodejs-ns
```

4. Verify the [auto-instrumentation resources](./instrumenting-applications.md#how-auto-instrumentation-works) are injected in the Pods:

Run a `kubectl describe` of one of your application Pods and check:

**REVIEW NEEDED HERE, it's a copy & paste from java SDK used as javaagent**
- There should be an init container named `opentelemetry-auto-instrumentation-nodejs` in the Pod:
```bash
$ kubectl describe pod nodejs-app-8d84c47b8-8h5z2 -n nodejs-ns
Name: nodejs-app-8d84c47b8-8h5z2
Namespace: nodejs-ns
...
...
Init Containers:
opentelemetry-auto-instrumentation-nodejs:
Container ID: containerd://cbf67d7ca1bd62c25614b905a11e81405bed6fd215f2df21f84b90fd0279230b
Image: docker.elastic.co/observability/elastic-otel-nodejs:1.0.0
Image ID: docker.elastic.co/observability/elastic-otel-nodejs@sha256:28d65d04a329c8d5545ed579d6c17f0d74800b7b1c5875e75e0efd29e210566a
Port: <none>
Host Port: <none>
Command:
cp
/nodejsagent.jar
/otel-auto-instrumentation-nodejs/nodejsagent.jar
State: Terminated
Reason: Completed
Exit Code: 0
Started: Wed, 13 Nov 2024 15:47:02 +0100
Finished: Wed, 13 Nov 2024 15:47:03 +0100
Ready: True
Restart Count: 0
Environment: <none>
Mounts:
/otel-auto-instrumentation-nodejs from opentelemetry-auto-instrumentation-nodejs (rw)
/var/run/secrets/kubernetes.io/serviceaccount from kube-api-access-swhn5 (ro)
```
- The main container of the deployment is using the SDK as `nodejsagent`:
```bash
...
Containers:
nodejs-app:
Environment:
...
JAVA_TOOL_OPTIONS: -nodejsagent:/otel-auto-instrumentation-nodejs/nodejsagent.jar
OTEL_SERVICE_NAME: nodejs-app
OTEL_EXPORTER_OTLP_ENDPOINT: http://opentelemetry-kube-stack-daemon-collector.opentelemetry-operator-system.svc.cluster.local:4318
...
```
- The Pod has an `EmptyDir` volume named `opentelemetry-auto-instrumentation-nodejs` mounted in both the main and the init containers in path `/otel-auto-instrumentation-nodejs`.
```bash
Init Containers:
opentelemetry-auto-instrumentation-nodejs:
...
Mounts:
/otel-auto-instrumentation-nodejs from opentelemetry-auto-instrumentation-nodejs (rw)
Containers:
nodejs-app:
...
Mounts:
/otel-auto-instrumentation-nodejs from opentelemetry-auto-instrumentation-nodejs (rw)
...
Volumes:
...
opentelemetry-auto-instrumentation-nodejs:
Type: EmptyDir (a temporary directory that shares a pod's lifetime)
```

Ensure the environment variable `OTEL_EXPORTER_OTLP_ENDPOINT` points to a valid endpoint and there's network communication between the Pod and the endpoint.
**END OF REVIEW NEEDED SECTION**
5. Confirm data is flowing to **Kibana**:
- Open **Observability** -> **Applications** -> **Service inventory**, and determine if:
- The application appears in the list of services (`nodejs-app` in the example).
- The application shows transactions and metrics.
> [!TIP]
> Generate some traffic to your application to ensure there are transactions and metrics to see. You can use `kubectl port-forward` for this purpose is your application is not exposed externally.
- For application container logs, open **Kibana Discover** and filter for your Pods' logs. In the provided example, we could filter for them with either of the following:
- `k8s.deployment.name: "nodejs-app"` (**adapt the query filter to your use case**)
- `k8s.pod.name: nodejs-app*` (**adapt the query filter to your use case**)

Note that the container logs are not provided by the instrumentation library, but by the DaemonSet collector deployed as part of the [operator installation](./README.md).

## Troubleshooting

- Refer to [troubleshoot auto-instrumentation](./troubleshoot-auto-instrumentation.md) for further analysis.