How to run the Open Telemetry .NET Agent without implementing scripts on an Alpine Linux image


To implement automatic instrumentation of the OpenTelemetry (OTEL) .NET Agent, the OTEL documentation says to:

### Download the Bash Script that creates the directory structure for OTEL
curl -sSfL https://github.com/open-telemetry/opentelemetry-dotnet-instrumentation/releases/latest/download/otel-dotnet-auto-install.sh -O

### Install the .NET OTEL files
sh ./otel-dotnet-auto-install.sh

### Give permissions to the script to instrument Open Telemetry
chmod +x $HOME/.otel-dotnet-auto/instrument.sh

### Run the Instrumentation Script at Startup
. $HOME/.otel-dotnet-auto/instrument.sh

For some organizations, it may not be convenient to add additional scripts into the Startup workflow for the Application. Or, the Open Telemetry scripts may throw errors because the scripts require dependencies that are not present on the Linux Image used for the Dotnet Services.


Workaround Steps

  1. Create Environment Variables or ConfigMap entries that are vFunction-specific
  • Find-and-replace https://$VF_SERVER_ADDRESS with the actual vFunction Server Address
  • Find-and-replace $VF_APP_ID with the App ID taken from the Installation Instruction in the vFunction UI
  • Find-and-replace $MY_SERVICE with the name of the Service that should appear in the vFunction UI
### Environment Variables
export OTEL_EXPORTER_OTLP_PROTOCOL=http/protobuf
export OTEL_EXPORTER_OTLP_ENDPOINT=https://$VF_SERVER_ADDRESS/api/unauth/otlp
export OTEL_TRACES_EXPORTER=otlp
export OTEL_METRICS_EXPORTER=none
export OTEL_LOGS_EXPORTER=none
export OTEL_EXPORTER_OTLP_HEADERS=X-VF-APP=$VF_APP_ID
export OTEL_SERVICE_NAME=$MY_SERVICE

### ConfigMap Entries
- name: OTEL_EXPORTER_OTLP_PROTOCOL
  value: 'http/protobuf'
- name: OTEL_EXPORTER_OTLP_ENDPOINT
  value: 'https://$VF_SERVER_ADDRESS/api/unauth/otlp'
- name: OTEL_TRACES_EXPORTER
  value: 'otlp'
- name: OTEL_METRICS_EXPORTER
  value: none
- name: OTEL_LOGS_EXPORTER
  value: none
- name: OTEL_EXPORTER_OTLP_HEADERS
  value: 'X-VF-APP=$VF_APP_ID'
- name: OTEL_SERVICE_NAME
  value: '$MY_SERVICE'
  1. Create Environment Variables or ConfigMap entries that are OpenTelemetry-specific
  • Find-and-replace /$DESIRED/$PATH with the location where you’ll install the OpenTelemetry DLLs
### Environment Variables
export CORECLR_ENABLE_PROFILING=1
export CORECLR_PROFILER='{918728DD-259F-4A6A-AC2B-B85E1B658318}'
export OTEL_DOTNET_AUTO_HOME="/$DESIRED/$PATH"
export CORECLR_PROFILER_PATH="$OTEL_DOTNET_AUTO_HOME/linux-musl-x64/OpenTelemetry.AutoInstrumentation.Native.so"
export DOTNET_ADDITIONAL_DEPS="$OTEL_DOTNET_AUTO_HOME/AdditionalDeps"
export DOTNET_SHARED_STORE="$OTEL_DOTNET_AUTO_HOME/store"
export DOTNET_STARTUP_HOOKS="$OTEL_DOTNET_AUTO_HOME/net/OpenTelemetry.AutoInstrumentation.StartupHook.dll"

### ConfigMap Entries
- name: CORECLR_ENABLE_PROFILING
  value: '1'
- name: CORECLR_PROFILER
  value: '{918728DD-259F-4A6A-AC2B-B85E1B658318}'
- name: OTEL_DOTNET_AUTO_HOME
  value: /$DESIRED/$PATH
- name: CORECLR_PROFILER_PATH
  value: "$OTEL_DOTNET_AUTO_HOME/linux-musl-x64/OpenTelemetry.AutoInstrumentation.Native.so"
- name: DOTNET_ADDITIONAL_DEPS
  value: "$OTEL_DOTNET_AUTO_HOME/AdditionalDeps"
- name: DOTNET_SHARED_STORE
  value: "$OTEL_DOTNET_AUTO_HOME/store"
- name: DOTNET_STARTUP_HOOKS
  value: "$OTEL_DOTNET_AUTO_HOME/net/OpenTelemetry.AutoInstrumentation.StartupHook.dll"
  1. Create an Init Container with the Dotnet Application that loads the Open Telemetry directory
  • Find-and-replace https://$VF_SERVER_ADDRESS with the actual vFunction Server Address
  • Find-and-replace $VF_APP_ID with the App ID taken from the Installation Instruction in the vFunction UI
  • Find-and-replace $MY_SERVICE with the name of the Service that should appear in the vFunction UI
apiVersion: apps/v1
kind: Deployment
metadata:
  labels:
    app: my-app
  name: my-app
spec:
  selector:
    matchLabels:
      app: my-app
  strategy:
    rollingUpdate:
      maxSurge: 1
      maxUnavailable: 0
    type: RollingUpdate
  template:
    metadata:
      labels:
        app: my-app
    spec:
      initContainers:
      - name: otel-installer
        command:
        - sh
        - -c
        - |
          cd /otel-home \
          && wget -q https://github.com/open-telemetry/opentelemetry-dotnet-instrumentation/releases/download/v1.7.0/opentelemetry-dotnet-instrumentation-linux-musl-x64.zip \
          && unzip "opentelemetry-dotnet-instrumentation-linux-musl-x64.zip" \
          && rm "opentelemetry-dotnet-instrumentation-linux-musl-x64.zip"
        image: alpine:latest
        imagePullPolicy: IfNotPresent
        resources: {}
        volumeMounts:
        - mountPath: /otel-home
          name: otel-home
      containers:
      - name: my-app
        env:
        - name: OTEL_EXPORTER_OTLP_PROTOCOL
          value: http/protobuf
        - name: OTEL_EXPORTER_OTLP_ENDPOINT
          value: http://$VF_SERVER_ADDRESS/api/unauth/otlp
        - name: OTEL_TRACES_EXPORTER
          value: otlp
        - name: OTEL_METRICS_EXPORTER
          value: none
        - name: OTEL_LOGS_EXPORTER
          value: none
        - name: OTEL_EXPORTER_OTLP_HEADERS
          value: X-VF-APP=$VF_APP_ID
        - name: OTEL_SERVICE_NAME
          value: $MY_SERVICE
        - name: OTEL_DOTNET_AUTO_HOME
          value: /otel-home
        - name: CORECLR_ENABLE_PROFILING
          value: "1"
        - name: CORECLR_PROFILER
          value: '{918728DD-259F-4A6A-AC2B-B85E1B658318}'
        - name: CORECLR_PROFILER_PATH
          value: $(OTEL_DOTNET_AUTO_HOME)/linux-musl-x64/OpenTelemetry.AutoInstrumentation.Native.so
        - name: DOTNET_ADDITIONAL_DEPS
          value: $(OTEL_DOTNET_AUTO_HOME)/AdditionalDeps
        - name: DOTNET_SHARED_STORE
          value: $(OTEL_DOTNET_AUTO_HOME)/store
        - name: DOTNET_STARTUP_HOOKS
          value: /otel-home/net/OpenTelemetry.AutoInstrumentation.StartupHook.dll
        image: my-image:latest
        ports:
        - containerPort: 8080
          name: web
          protocol: TCP
        resources:
          limits:
            cpu: 500m
            memory: 800Mi
          requests:
            cpu: 100m
            memory: 500Mi
        volumeMounts:
        - mountPath: /otel-home
          name: otel-home
          readOnly: true
      dnsPolicy: ClusterFirst
      restartPolicy: Always
      terminationGracePeriodSeconds: 30
      volumes:
      - emptyDir:
          sizeLimit: 500Mi
        name: otel-home
  1. Install the Open Telemetery Collector
  2. Build and Deploy the Application