aws-otel-lambda
aws-otel-lambda copied to clipboard
publish Docker images for multi-stage builds to use
i've had difficulty adding X-Ray tracing for a python application using OpenTelemetry with a container-based Lambda. The published extension isn't immediately applicable to that use case.
Ideally, there'd be images published to ECR which could be used in multi-stage builds something like this (maybe per python version?):
FROM public.ecr.aws/lambda/aws-otel-lambda:latest as otel-base
FROM public.ecr.aws/lambda/python:3.8
COPY src/ $LAMBDA_TASK_ROOT
COPY --from otel-base /opt/ /opt/
That may not work for all use cases, but could at least work for images based on public.ecr.aws/lambda/python.
i understand if that's outside the purpose of this project.
i've tried doing something like in a Dockerfile myself, and i'm getting Lambda timeouts whenever the xray exporter is included in the config (using logging exorter only works fine), with hardly any context to go on.
Maybe i could get a little help:
FROM public.ecr.aws/lambda/python:3.8 as python-base
# [... some ENV set up here]
FROM python-base as otel-base
RUN yum -y install git make
RUN wget https://go.dev/dl/go1.17.3.linux-amd64.tar.gz && rm -rf /usr/local/go && tar -C /usr/local -xzf go1.17.3.linux-amd64.tar.gz
ENV PATH=$PATH:/usr/local/go/bin
RUN git clone --recurse-submodules https://github.com/aws-observability/aws-otel-lambda.git
WORKDIR $LAMBDA_TASK_ROOT/aws-otel-lambda
# Patch ADOT
RUN ./patch-upstream.sh
# instead of running python/build.sh, which is creating zip archives, run the underlying build.sh scripts.
# opentelemetry-lambda/python/src/build.sh requires docker, so use Make instead. we also make an empty collector_build dir so the script doesn't fail; it's looking for the collector we are adding later
RUN cd opentelemetry-lambda/python/src/otel && \
mkdir build && \
mkdir collector_build && \
touch collector_build/tmp && \
ARTIFACTS_DIR=build make build-OTelLayer && \
mv build/python /opt/
# FIXME: /opt/otel-instrument is in /opt/python/otel-instrument?
# Build collector
RUN cd opentelemetry-lambda/collector && make build && cp -r build/extensions /opt
RUN mkdir /opt/collector-config && cp opentelemetry-lambda/collector/config* /opt/collector-config/
# use our defined collector configs
COPY "./applications/collector-config/" /opt/collector-config/
FROM python-base as application
# [... add and install python libs]
COPY --from=otel-base /opt/ /opt/
Does the instrumentor need to be installed in the same environment as the application's python libs? In my case, i've been using poetry to install to /var/lang/lib/python3.8/.
Hi @smcoll,
I think having container images for the Lambda layers is a perfectly valid feature request, so I can mark this as such.
Have you referenced the build script for our managed layer to see how to use otel-instrument
script? You can find it here: https://github.com/aws-observability/aws-otel-lambda/blob/main/python/build.sh
I feel like this similar issue I answered a few days ago is related, so just dropping the link here: https://github.com/aws-observability/aws-otel-community/issues/37#issuecomment-998284294
Regarding this in your code:
FIXME: /opt/otel-instrument is in /opt/python/otel-instrument?
The upstream opentelemetry-lambda
repo actually moves the python/otel-instrument
file to be at the otel-instrument path when it creates the zip containing the build so it _should_ be in
/opt/otel-instrument`: https://github.com/open-telemetry/opentelemetry-lambda/blob/8e77f5b6a4dbc2665bc15cf829cafa700456b1e9/python/src/otel/Dockerfile#L17
We run this Docker Image in this aws-otel-lambda
repo here:
https://github.com/aws-observability/aws-otel-lambda/blob/486911eb8e05f4512d4abafaca0b9430914394e5/python/build.sh#L9-L12
One last complexity is that we rename it and replace it with our own "otel-instrument
" because we want to add AWS X-Ray Python configuration values:
https://github.com/aws-observability/aws-otel-lambda/blob/486911eb8e05f4512d4abafaca0b9430914394e5/python/build.sh#L29-L31
If you just run ./python/build.sh
from this aws-otel-lambda
repo it would do all these steps, but if you are doing your own version of python/build.sh
these are things to keep in mind to make sure your final file directory looks like the same like the zip file the original buid.sh
generates 🙂
@smcoll wondering if you got this working with python lambdas deployed as containers. Currently struggling through the same issue.
Getting back around to this...
It does look like copying files from the published layer could do the trick (although that requires passing through AWS creds into the build), but i'm using Python 3.9 and there isn't a layer published for it yet: https://github.com/aws-observability/aws-otel-lambda/issues/222.
Next approach was to use the build scripts as-is in a container so i could use the layer artifacts with COPY FROM
, but this requires docker-in-docker, or equivalent. Using Amazon Linux 2022: docker run --rm -it public.ecr.aws/amazonlinux/amazonlinux:2022 bash
:
bash-5.1# cd /home
bash-5.1# yum -y install git wget tar zip unzip make docker pip
bash-5.1# wget https://go.dev/dl/go1.17.3.linux-amd64.tar.gz && rm -rf /usr/local/go && tar -C /usr/local -xzf go1.17.3.linux-amd64.tar.gz
bash-5.1# export PATH=$PATH:/usr/local/go/bin
bash-5.1# systemctl enable docker
bash-5.1# systemctl start docker
System has not been booted with systemd as init system (PID 1). Can't operate.
Failed to connect to bus: Host is down
bash-5.1#
bash-5.1# # at this point i realize i need docker-in-docker to do this... if that were configured, i'd do the following:
bash-5.1# git clone --recurse-submodules https://github.com/aws-observability/aws-otel-lambda.git
bash-5.1# cd aws-otel-lambda/python
bash-5.1# ./build.sh
In the end, i just want appropriate files to put in the /opt
dir in my Lambda container, based on the python:3.9
image. So i investigated the build script to better understand what is happening here. Maybe i can use a few different docker stages each with a different base image and COPY FROM
to the the result it need?
Is this explicitly building for 3.8, and if so, how can i adjust to build for 3.9?
Stepping through the build script, to validate my comprehension:
https://github.com/aws-observability/aws-otel-lambda/blob/33c85b38836b7d2715d087ed5c1af0324c74e422/python/build.sh#L3-L7
This section says it's building the collector, but it appears to me that it results in a no-op; i ran them inside a container (without || exit
) after checking out this source code, and i see it overlays a dir from the upstream submodule and creates python/build/
and contents, but then after popd
i don't see any remaining artifacts... are we looking for a collector binary here?
(Details)
bash-4.2# git clone --recurse-submodules https://github.com/aws-observability/aws-otel-lambda.git
Cloning into 'aws-otel-lambda'...
remote: Enumerating objects: 1794, done.
remote: Counting objects: 100% (180/180), done.
remote: Compressing objects: 100% (107/107), done.
remote: Total 1794 (delta 75), reused 99 (delta 34), pack-reused 1614
Receiving objects: 100% (1794/1794), 1.75 MiB | 9.85 MiB/s, done.
Resolving deltas: 100% (908/908), done.
Submodule 'opentelemetry-lambda' (https://github.com/open-telemetry/opentelemetry-lambda.git) registered for path 'opentelemetry-lambda'
Cloning into '/var/task/aws-otel-lambda/opentelemetry-lambda'...
remote: Enumerating objects: 1922, done.
remote: Counting objects: 100% (680/680), done.
remote: Compressing objects: 100% (238/238), done.
remote: Total 1922 (delta 495), reused 466 (delta 421), pack-reused 1242
Receiving objects: 100% (1922/1922), 591.42 KiB | 5.28 MiB/s, done.
Resolving deltas: 100% (857/857), done.
Submodule path 'opentelemetry-lambda': checked out 'e13a8ce7328e6739ed510d66bc5461427fee8eb2'
bash-4.2# cd aws-otel-lambda/
bash-4.2# ls -al
total 100
drwxr-xr-x 12 root root 4096 Mar 1 21:20 .
drwxr-xr-x 1 root root 4096 Mar 1 21:20 ..
drwxr-xr-x 5 root root 4096 Mar 1 21:20 adot
-rw-r--r-- 1 root root 7850 Mar 1 21:20 CHANGELOG.md
-rw-r--r-- 1 root root 309 Mar 1 21:20 CODE_OF_CONDUCT.md
-rw-r--r-- 1 root root 3160 Mar 1 21:20 CONTRIBUTING.md
drwxr-xr-x 4 root root 4096 Mar 1 21:20 dotnet
drwxr-xr-x 9 root root 4096 Mar 1 21:20 .git
-rw-r--r-- 1 root root 85 Mar 1 21:20 .gitattributes
drwxr-xr-x 4 root root 4096 Mar 1 21:20 .github
-rw-r--r-- 1 root root 127 Mar 1 21:20 .gitignore
-rw-r--r-- 1 root root 130 Mar 1 21:20 .gitmodules
drwxr-xr-x 4 root root 4096 Mar 1 21:20 go
drwxr-xr-x 7 root root 4096 Mar 1 21:20 java
-rw-r--r-- 1 root root 10142 Mar 1 21:20 LICENSE
drwxr-xr-x 6 root root 4096 Mar 1 21:20 nodejs
-rw-r--r-- 1 root root 67 Mar 1 21:20 NOTICE
drwxr-xr-x 11 root root 4096 Mar 1 21:20 opentelemetry-lambda
-rwxr-xr-x 1 root root 1626 Mar 1 21:20 patch-upstream.sh
drwxr-xr-x 5 root root 4096 Mar 1 21:20 python
-rw-r--r-- 1 root root 2467 Mar 1 21:20 README.md
drwxr-xr-x 3 root root 4096 Mar 1 21:20 sample-apps
bash-4.2# cd python/
bash-4.2# ls -al
total 24
drwxr-xr-x 5 root root 4096 Mar 1 21:20 .
drwxr-xr-x 12 root root 4096 Mar 1 21:20 ..
-rwxr-xr-x 1 root root 758 Mar 1 21:20 build.sh
drwxr-xr-x 3 root root 4096 Mar 1 21:20 integration-tests
drwxr-xr-x 3 root root 4096 Mar 1 21:20 sample-apps
drwxr-xr-x 2 root root 4096 Mar 1 21:20 scripts
bash-4.2# pushd ../opentelemetry-lambda/collector
/var/task/aws-otel-lambda/opentelemetry-lambda/collector /var/task/aws-otel-lambda/python
bash-4.2# ls -al
total 268
drwxr-xr-x 4 root root 4096 Mar 1 21:20 .
drwxr-xr-x 11 root root 4096 Mar 1 21:20 ..
-rw-r--r-- 1 root root 2736 Mar 1 21:20 collector.go
-rw-r--r-- 1 root root 251 Mar 1 21:20 config.yaml
drwxr-xr-x 2 root root 4096 Mar 1 21:20 extension
-rw-r--r-- 1 root root 4964 Mar 1 21:20 go.mod
-rw-r--r-- 1 root root 219786 Mar 1 21:20 go.sum
drwxr-xr-x 2 root root 4096 Mar 1 21:20 lambdacomponents
-rw-r--r-- 1 root root 2358 Mar 1 21:20 main.go
-rw-r--r-- 1 root root 1624 Mar 1 21:20 Makefile
-rw-r--r-- 1 root root 1042 Mar 1 21:20 print.go
-rw-r--r-- 1 root root 3222 Mar 1 21:20 README.md
-rw-r--r-- 1 root root 7 Mar 1 21:20 VERSION
bash-4.2# make package
rm -rf build/
Building otel collector extension
mkdir -p /var/task/aws-otel-lambda/opentelemetry-lambda/collector/build/extensions
GOOS=linux GO111MODULE=on CGO_ENABLED=0 installsuffix=cgo go build -trimpath -ldflags "-s -w -X main.GitHash=e13a8ce7328e6739ed510d66bc5461427fee8eb2 -X main.Version=v0.1.0 -X github.com/open-telemetry/opentelemetry-collector-contrib/exporter/awsxrayexporter.collectorDistribution=opentelemetry-collector-lambda" -o /var/task/aws-otel-lambda/opentelemetry-lambda/collector/build/extensions .
Package zip file for collector extension layer
mkdir -p /var/task/aws-otel-lambda/opentelemetry-lambda/collector/build/collector-config
cp config* /var/task/aws-otel-lambda/opentelemetry-lambda/collector/build/collector-config
cd /var/task/aws-otel-lambda/opentelemetry-lambda/collector/build && zip -r collector-extension.zip collector-config extensions
adding: collector-config/ (stored 0%)
adding: collector-config/config.yaml (deflated 54%)
adding: extensions/ (stored 0%)
adding: extensions/collector (deflated 65%)
bash-4.2# ls -al
total 272
drwxr-xr-x 5 root root 4096 Mar 1 21:20 .
drwxr-xr-x 11 root root 4096 Mar 1 21:20 ..
drwxr-xr-x 4 root root 4096 Mar 1 21:20 build
-rw-r--r-- 1 root root 2736 Mar 1 21:20 collector.go
-rw-r--r-- 1 root root 251 Mar 1 21:20 config.yaml
drwxr-xr-x 2 root root 4096 Mar 1 21:20 extension
-rw-r--r-- 1 root root 4964 Mar 1 21:20 go.mod
-rw-r--r-- 1 root root 219786 Mar 1 21:20 go.sum
drwxr-xr-x 2 root root 4096 Mar 1 21:20 lambdacomponents
-rw-r--r-- 1 root root 2358 Mar 1 21:20 main.go
-rw-r--r-- 1 root root 1624 Mar 1 21:20 Makefile
-rw-r--r-- 1 root root 1042 Mar 1 21:20 print.go
-rw-r--r-- 1 root root 3222 Mar 1 21:20 README.md
-rw-r--r-- 1 root root 7 Mar 1 21:20 VERSION
bash-4.2# popd
/var/task/aws-otel-lambda/python
bash-4.2# ls -al
total 24
drwxr-xr-x 5 root root 4096 Mar 1 21:20 .
drwxr-xr-x 12 root root 4096 Mar 1 21:20 ..
-rwxr-xr-x 1 root root 758 Mar 1 21:20 build.sh
drwxr-xr-x 3 root root 4096 Mar 1 21:20 integration-tests
drwxr-xr-x 3 root root 4096 Mar 1 21:20 sample-apps
drwxr-xr-x 2 root root 4096 Mar 1 21:20 scripts
bash-4.2# cd ..
bash-4.2# ls -al
total 100
drwxr-xr-x 12 root root 4096 Mar 1 21:20 .
drwxr-xr-x 1 root root 4096 Mar 1 21:20 ..
drwxr-xr-x 5 root root 4096 Mar 1 21:20 adot
-rw-r--r-- 1 root root 7850 Mar 1 21:20 CHANGELOG.md
-rw-r--r-- 1 root root 309 Mar 1 21:20 CODE_OF_CONDUCT.md
-rw-r--r-- 1 root root 3160 Mar 1 21:20 CONTRIBUTING.md
drwxr-xr-x 4 root root 4096 Mar 1 21:20 dotnet
drwxr-xr-x 9 root root 4096 Mar 1 21:20 .git
-rw-r--r-- 1 root root 85 Mar 1 21:20 .gitattributes
drwxr-xr-x 4 root root 4096 Mar 1 21:20 .github
-rw-r--r-- 1 root root 127 Mar 1 21:20 .gitignore
-rw-r--r-- 1 root root 130 Mar 1 21:20 .gitmodules
drwxr-xr-x 4 root root 4096 Mar 1 21:20 go
drwxr-xr-x 7 root root 4096 Mar 1 21:20 java
-rw-r--r-- 1 root root 10142 Mar 1 21:20 LICENSE
drwxr-xr-x 6 root root 4096 Mar 1 21:20 nodejs
-rw-r--r-- 1 root root 67 Mar 1 21:20 NOTICE
drwxr-xr-x 11 root root 4096 Mar 1 21:20 opentelemetry-lambda
-rwxr-xr-x 1 root root 1626 Mar 1 21:20 patch-upstream.sh
drwxr-xr-x 5 root root 4096 Mar 1 21:20 python
-rw-r--r-- 1 root root 2467 Mar 1 21:20 README.md
drwxr-xr-x 3 root root 4096 Mar 1 21:20 sample-apps
bash-4.2#
https://github.com/aws-observability/aws-otel-lambda/blob/33c85b38836b7d2715d087ed5c1af0324c74e422/python/build.sh#L9-L12
This looks like it builds the SDK layer, using Docker, with volume mapping to a local directory, then puts the resulting zip as build/layer.zip
. Is the opentelemetry-lambda
container published somewhere such that i could use ...
https://github.com/aws-observability/aws-otel-lambda/blob/33c85b38836b7d2715d087ed5c1af0324c74e422/python/build.sh#L14-L16
What does it need from the sample apps to complete this build?
https://github.com/aws-observability/aws-otel-lambda/blob/33c85b38836b7d2715d087ed5c1af0324c74e422/python/build.sh#L18-L22
Now it installs opentelemetry-sdk-extension-aws
into build/python
.
https://github.com/aws-observability/aws-otel-lambda/blob/33c85b38836b7d2715d087ed5c1af0324c74e422/python/build.sh#L24-L27
That seems to unzip the layers already created, and combine them.
https://github.com/aws-observability/aws-otel-lambda/blob/33c85b38836b7d2715d087ed5c1af0324c74e422/python/build.sh#L29-L31
@NathanielRN explained this:
One last complexity is that we rename it and replace it with our own "otel-instrument" because we want to add AWS X-Ray Python configuration values
https://github.com/aws-observability/aws-otel-lambda/blob/main/python/build.sh#L33-L35
And this creates the final layer as an archive (which i won't need).
At what point is patch-upstream.sh
invoked?
So after i get the build working (in an image), i just need to COPY FROM
all the files in the opentelemetry-lambda/python/src/build
dir into the /opt
dir of my lambda image?
+1, this would be very useful to have
Could we also have this added to the roadmap and some indication of timeline https://github.com/orgs/aws-observability/projects/4
@dknz2008 we will evaluate but can't commit to a prioritization yet.
@alolita any update if possible?
I also want this even for Docker Node.js environment to install otel in fewer steps
This would great, obviously for all language/environments.
@alolita In the shorter term, it might be helpful to provide some guidance on how one could achieve this themselves.
This issue is stale because it has been open 90 days with no activity. If you want to keep this issue open, please just leave a comment below and auto-close will be canceled
This issue was closed because it has been marked as stale for 30 days with no activity.
Yes, if publishing images is not on the roadmap, at least a user guide would be great. Should i open a separate issue?
It's been a long time since i gave this a shot, but i shared my progress and requests for context at https://github.com/aws-observability/aws-otel-lambda/issues/195#issuecomment-1061037790 - i was unable to get further at the time.
EDIT: oh, it looks like someone was able to figure it out - i can start from https://github.com/aws-observability/aws-otel-lambda/issues/209#issuecomment-1028393564
Having the layer packaged as a container would make building custom lambda runtimes much easier. Although there is a workaround (download and unzip the layer), that is rather cumbersome, while building a container image from scratch with the contents of the layers seems rather trivial. I would be happy to contribute a PR to build container images for the layer, if there is interest from the maintainers.