Thanks to visit codestin.com
Credit goes to GitHub.com

Skip to content

Bug: OpenLIT Operator does not support ABI-matched auto-instrumentation for multiple Python versions #950

@BitKickerBHS

Description

@BitKickerBHS

Bug: OpenLIT Operator does not support ABI-matched auto-instrumentation for multiple Python versions

Component

OpenLIT Operator

What happened?

When the OpenLIT Operator injects the default auto-instrumentation image (built for Python 3.11) into workloads running other Python versions (e.g., 3.12, 3.13), any application using C-extensions (such as Pydantic, numpy, or other AI libraries) frequently fails with:

ModuleNotFoundError: No module named 'pydantic_core._pydantic_core'

The cause is that the instrumentation image installs .so files (binary extensions) built for Python 3.11, but the workload’s interpreter expects files for a different version (ABI mismatch). This is especially problematic in clusters with mixed Python versions, where some apps use Python 3.11 and others use newer versions.


Where the Default Instrumentation Image Uses Python 3.11

The official OpenLIT auto-instrumentation image is built using Python 3.11 as specified in its Dockerfile:

######### OpenLIT Instrumentation Image #########
FROM python:3.11-slim AS openlit-builder
...
# Create final OpenLIT image
FROM python:3.11-slim
...

All compiled packages inside this image are built for the Python 3.11 ABI. If the application workload in your pod runs a different Python version, binary imports will fail due to ABI incompatibility.


Steps to Reproduce

  1. Deploy a workload using Python 3.12 or 3.13 in a cluster with the OpenLIT Operator and the default OpenLIT instrumentation provider.
  2. Trigger any request or flow that uses C-extension libraries (such as Pydantic).
  3. Observe errors like:
    ModuleNotFoundError: No module named 'pydantic_core._pydantic_core'
    

Expected Behavior

  • The OpenLIT Operator should inject an ABI-compatible instrumentation image matching the Python version of each workload, avoiding these errors.
  • Users should not need to manually build or maintain custom instrumentation images for each Python release.

Current Workarounds

Manual: Build and publish a custom OpenLIT instrumentation image per Python version, then reference it in the CR with customInitImage:

apiVersion: openlit.io/v1alpha1
kind: AutoInstrumentation
spec:
  python:
    instrumentation:
      provider: openlit
      customInitImage: myrepo/openlit-auto-instrumentation:py312

However, this workaround does not scale for large clusters or organizations with mixed Python dependencies.


Proposed Solution

Option 1: Official ABI-Matched Images (User-Selected)

  • OpenLIT publishes openlit/auto-instrumentation:py311, :py312, :py313, :py314, etc.
  • Users select the appropriate image in their AutoInstrumentation CR:
apiVersion: openlit.io/v1alpha1
kind: AutoInstrumentation
spec:
  python:
    instrumentation:
      provider: openlit
      customInitImage: openlit/auto-instrumentation:py312

Option 2: Operator Autodetection (Recommended, Zero-Config for User)

  • Operator is enhanced to detect the Python version from:
    • The PYTHON_VERSION environment variable in the workload container, e.g.:
      containers:
        - name: my-app
          env:
            - name: PYTHON_VERSION
              value: "3.13"
    • Or, parse the Python version from the image tag, e.g.:
      containers:
        - name: my-app
          image: python:3.12-slim
  • It then automatically injects the matching ABI image:
    openlit/auto-instrumentation:py312 or py313 as appropriate.
Example (Go) Operator Logic
// detectPythonVersion returns the python version string ("3.12") based on env or image tag
func (i *OpenLitInjector) detectPythonVersion(container *corev1.Container) string {
    for _, env := range container.Env {
        if env.Name == "PYTHON_VERSION" && env.Value != "" {
            return env.Value
        }
    }
    if strings.HasPrefix(container.Image, "python:") {
        v := strings.Split(strings.TrimPrefix(container.Image, "python:"), "-")[0]
        if v != "" {
            return v
        }
    }
    return i.config.DefaultPythonVersion // fallback (e.g., "3.11")
}

// getPythonInitImage constructs the correct image tag for injection
func (i *OpenLitInjector) getPythonInitImage(container *corev1.Container) string {
    version := i.detectPythonVersion(container)
    tag := "py" + strings.ReplaceAll(version, ".", "")
    return "openlit/auto-instrumentation:" + tag
}
Example Unit Test
func TestDetectPythonVersion(t *testing.T) {
    injector := &OpenLitInjector{config: &InjectorConfig{DefaultPythonVersion: "3.11"}}

    // Using PYTHON_VERSION env
    cont := &corev1.Container{
        Env: []corev1.EnvVar{{Name: "PYTHON_VERSION", Value: "3.13"}},
    }
    assert.Equal(t, "3.13", injector.detectPythonVersion(cont))
    assert.Equal(t, "openlit/auto-instrumentation:py313", injector.getPythonInitImage(cont))

    // Using image tag
    cont = &corev1.Container{Image: "python:3.12-slim"}
    assert.Equal(t, "3.12", injector.detectPythonVersion(cont))
    assert.Equal(t, "openlit/auto-instrumentation:py312", injector.getPythonInitImage(cont))

    // Fallback default
    cont = &corev1.Container{}
    assert.Equal(t, "3.11", injector.detectPythonVersion(cont))
    assert.Equal(t, "openlit/auto-instrumentation:py311", injector.getPythonInitImage(cont))
}
Key Code Integration Points

Environment

  • OpenLIT Operator: latest
  • Python: 3.12, 3.13 (anything above 3.11)
  • Kubernetes: Any supported version

Additional context

  • This prevents "zero-config" auto-instrumentation for modern Python environments.
  • Blocks organizations with mixed Python stacks from simple OpenLIT adoption.
  • Many modern auto-instrumentation solutions (OpenTelemetry, Datadog, etc.) match the runtime ABI for this exact reason.

Pre-submission checklist

  • I searched existing issues and did not find a duplicate.
  • Environment details included.
  • Willing to provide more technical context or example manifests if requested.

Are you willing to submit a PR?

No, but I am happy to clarify requirements further and provide code/design feedback.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions