Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Python autoinstrumentation for musl libc based application containers #2266

Open
wants to merge 1 commit into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
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
7 changes: 6 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -250,8 +250,13 @@ instrumentation.opentelemetry.io/inject-nodejs: "true"
```

Python:
Python auto-instrumentation also honors an annotation that will be used to set Python runtime C library implementation.
Currently, two C library implementations are supported: `linux-x64` and `linux-musl-x64`.
By default `linux-x64` is used.
```bash
instrumentation.opentelemetry.io/inject-python: "true"
instrumentation.opentelemetry.io/inject-: "true"
instrumentation.opentelemetry.io/otel-python-auto-runtime: "linux-x64" # for Linux glibc based images, this is default value and can be omitted
instrumentation.opentelemetry.io/otel-python-auto-runtime: "linux-musl-x64" # for Linux musl based images
```

.NET:
Expand Down
13 changes: 12 additions & 1 deletion autoinstrumentation/python/Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
# - Grant the necessary access to `/autoinstrumentation` directory. `chmod -R go+r /autoinstrumentation`
# - For auto-instrumentation by container injection, the Linux command cp is
# used and must be availabe in the image.
# - Please note that we build twice. First time for environments with libc and second time with musl C implementations
FROM python:3.11 AS build

WORKDIR /operator-build
Expand All @@ -17,8 +18,18 @@ ADD requirements.txt .

RUN mkdir workspace && pip install --target workspace -r requirements.txt

FROM python:3.11-alpine AS build-musl

WORKDIR /operator-build

ADD requirements.txt .

RUN apk add --update --no-cache gcc musl-dev linux-headers
RUN mkdir workspace && pip install --target workspace -r requirements.txt

FROM busybox

COPY --from=build /operator-build/workspace /autoinstrumentation
COPY --from=build /operator-build/workspace /autoinstrumentation/linux-x64
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I am not sure how in details looks release process for docker images, but if it release new version just after merge to main it can be breaking change for currently released version.

If the new image will be applicable only to the new operator release - then it LGTM.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

A very good concern! I will check

COPY --from=build-musl /operator-build/workspace /autoinstrumentation/linux-musl-x64

RUN chmod -R go+r /autoinstrumentation
1 change: 1 addition & 0 deletions pkg/instrumentation/annotation.go
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ const (
annotationInjectNodeJS = "instrumentation.opentelemetry.io/inject-nodejs"
annotationInjectNodeJSContainersName = "instrumentation.opentelemetry.io/nodejs-container-names"
annotationInjectPython = "instrumentation.opentelemetry.io/inject-python"
annotationPythonRuntime = "instrumentation.opentelemetry.io/otel-python-auto-runtime"
annotationInjectPythonContainersName = "instrumentation.opentelemetry.io/python-container-names"
annotationInjectDotNet = "instrumentation.opentelemetry.io/inject-dotnet"
annotationDotNetRuntime = "instrumentation.opentelemetry.io/otel-dotnet-auto-runtime"
Expand Down
1 change: 1 addition & 0 deletions pkg/instrumentation/podmutator.go
Original file line number Diff line number Diff line change
Expand Up @@ -252,6 +252,7 @@ func (pm *instPodMutator) Mutate(ctx context.Context, ns corev1.Namespace, pod c
}
if featuregate.EnablePythonAutoInstrumentationSupport.IsEnabled() || inst == nil {
insts.Python.Instrumentation = inst
insts.Python.AdditionalAnnotations = map[string]string{annotationPythonRuntime: annotationValue(ns.ObjectMeta, pod.ObjectMeta, annotationPythonRuntime)}
} else {
logger.Error(nil, "support for Python auto instrumentation is not enabled")
pm.Recorder.Event(pod.DeepCopy(), "Warning", "InstrumentationRequestRejected", "support for Python auto instrumentation is not enabled")
Expand Down
14 changes: 7 additions & 7 deletions pkg/instrumentation/podmutator_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -1205,7 +1205,7 @@ func TestMutatePod(t *testing.T) {
},
{
Name: "PYTHONPATH",
Value: fmt.Sprintf("%s:%s", pythonPathPrefix, pythonPathSuffix),
Value: fmt.Sprintf("%s:%s", pythonPathGlibcPrefix, pythonPathGlibcSuffix),
},
{
Name: "OTEL_EXPORTER_OTLP_TRACES_PROTOCOL",
Expand Down Expand Up @@ -1393,7 +1393,7 @@ func TestMutatePod(t *testing.T) {
},
{
Name: "PYTHONPATH",
Value: fmt.Sprintf("%s:%s", pythonPathPrefix, pythonPathSuffix),
Value: fmt.Sprintf("%s:%s", pythonPathGlibcPrefix, pythonPathGlibcSuffix),
},
{
Name: "OTEL_EXPORTER_OTLP_TRACES_PROTOCOL",
Expand Down Expand Up @@ -1472,7 +1472,7 @@ func TestMutatePod(t *testing.T) {
},
{
Name: "PYTHONPATH",
Value: fmt.Sprintf("%s:%s", pythonPathPrefix, pythonPathSuffix),
Value: fmt.Sprintf("%s:%s", pythonPathGlibcPrefix, pythonPathGlibcSuffix),
},
{
Name: "OTEL_EXPORTER_OTLP_TRACES_PROTOCOL",
Expand Down Expand Up @@ -3743,7 +3743,7 @@ func TestMutatePod(t *testing.T) {
},
{
Name: "PYTHONPATH",
Value: fmt.Sprintf("%s:%s", pythonPathPrefix, pythonPathSuffix),
Value: fmt.Sprintf("%s:%s", pythonPathGlibcPrefix, pythonPathGlibcSuffix),
},
{
Name: "OTEL_TRACES_EXPORTER",
Expand Down Expand Up @@ -3806,7 +3806,7 @@ func TestMutatePod(t *testing.T) {
},
{
Name: "PYTHONPATH",
Value: fmt.Sprintf("%s:%s", pythonPathPrefix, pythonPathSuffix),
Value: fmt.Sprintf("%s:%s", pythonPathGlibcPrefix, pythonPathGlibcSuffix),
},
{
Name: "OTEL_TRACES_EXPORTER",
Expand Down Expand Up @@ -4401,7 +4401,7 @@ func TestMutatePod(t *testing.T) {
},
{
Name: "PYTHONPATH",
Value: fmt.Sprintf("%s:%s", pythonPathPrefix, pythonPathSuffix),
Value: fmt.Sprintf("%s:%s", pythonPathGlibcPrefix, pythonPathGlibcSuffix),
},
{
Name: "OTEL_TRACES_EXPORTER",
Expand Down Expand Up @@ -4464,7 +4464,7 @@ func TestMutatePod(t *testing.T) {
},
{
Name: "PYTHONPATH",
Value: fmt.Sprintf("%s:%s", pythonPathPrefix, pythonPathSuffix),
Value: fmt.Sprintf("%s:%s", pythonPathGlibcPrefix, pythonPathGlibcSuffix),
},
{
Name: "OTEL_TRACES_EXPORTER",
Expand Down
26 changes: 23 additions & 3 deletions pkg/instrumentation/python.go
Original file line number Diff line number Diff line change
Expand Up @@ -28,14 +28,21 @@ const (
envOtelMetricsExporter = "OTEL_METRICS_EXPORTER"
envOtelExporterOTLPTracesProtocol = "OTEL_EXPORTER_OTLP_TRACES_PROTOCOL"
envOtelExporterOTLPMetricsProtocol = "OTEL_EXPORTER_OTLP_METRICS_PROTOCOL"
pythonPathPrefix = "/otel-auto-instrumentation-python/opentelemetry/instrumentation/auto_instrumentation"
pythonPathSuffix = "/otel-auto-instrumentation-python"
pythonPathGlibcPrefix = "/otel-auto-instrumentation-python/linux-x64/opentelemetry/instrumentation/auto_instrumentation"
pythonPathGlibcSuffix = "/otel-auto-instrumentation-python/linux-x64"
pythonPathMuslPrefix = "/otel-auto-instrumentation-python/linux-musl-x64/opentelemetry/instrumentation/auto_instrumentation"
pythonPathMuslSuffix = "/otel-auto-instrumentation-python/linux-musl-x64"
pythonInstrMountPath = "/otel-auto-instrumentation-python"
pythonVolumeName = volumeName + "-python"
pythonInitContainerName = initContainerName + "-python"
)

func injectPythonSDK(pythonSpec v1alpha1.Python, pod corev1.Pod, index int) (corev1.Pod, error) {
const (
pythonRuntimeLinuxGlibc = "linux-x64"
pythonRuntimeLinuxMusl = "linux-musl-x64"
)

func injectPythonSDK(pythonSpec v1alpha1.Python, pod corev1.Pod, index int, runtime string) (corev1.Pod, error) {
// caller checks if there is at least one container.
container := &pod.Spec.Containers[index]

Expand All @@ -44,6 +51,19 @@ func injectPythonSDK(pythonSpec v1alpha1.Python, pod corev1.Pod, index int) (cor
return pod, err
}

pythonPathPrefix := ""
pythonPathSuffix := ""
switch runtime {
case "", pythonRuntimeLinuxGlibc:
pythonPathPrefix = pythonPathGlibcPrefix
pythonPathSuffix = pythonPathGlibcSuffix
case pythonRuntimeLinuxMusl:
pythonPathPrefix = pythonPathMuslPrefix
pythonPathSuffix = pythonPathMuslSuffix
default:
return pod, fmt.Errorf("provided instrumentation.opentelemetry.io/otel-python-auto-runtime annotation value '%s' is not supported", runtime)
}

// inject Python instrumentation spec env vars.
for _, env := range pythonSpec.Env {
idx := getIndexOfEnv(container.Env, env.Name)
Expand Down
Loading
Loading