-
Notifications
You must be signed in to change notification settings - Fork 579
Description
Component(s)
instrumentation
What happened?
Description
Python's import system is full of implicit behavior. Notably, modules can be imported from the current working directory. The best practice is for applications to be pip install-ed so that the import logic is more predictable and reliable. Nevertheless, it is valid (albeit discouraged) for a containerized Python application to work by importing modules from the current working directory.
Python imports are dynamic and procedural, and some applications/frameworks such as Django are sensitive to the order of module resolution. Thus, setting PYTHONPATH can break valid Python programs which would otherwise work with unset PYTHONPATH.
Steps to Reproduce
I am trying to run the chris chart from https://github.com/FNNDSC/charts. This is a Python application using celery, django, and gunicorn. It works (tested in GitHub Actions) without autoinstrumentation. However, when the annotation instrumentation.opentelemetry.io/inject-python: "true" is added to the pod, I get seemingly unrelated error messages about the Django configuration.
For debugging, I edited the command of my containers to sleep 100000 and then tried running the actual command interactively using kubectl exec ...
Expected Result
I expect the following commands to do nothing successfully:
# (A) pod is annotated, so PYTHONPATH is set to use autoinstrumentation
kubectl exec cacao-chris-heart-75666d5558-vw5gm -- python manage.py shell -c 'import core.storage.storagemanager'
# (B) same as above, but trying to import a module containing classes which extend django.db.models.Model
kubectl exec cacao-chris-heart-75666d5558-vw5gm -- python manage.py shell -c 'import feeds.models'
# (C) PYTHONPATH overridden with empty string to disable autoinstrumentation
kubectl exec cacao-chris-heart-75666d5558-vw5gm -- env PYTHONPATH= python manage.py shell -c 'import feeds.models'
# (D) Adding current working directory in front of the PYTHONPATH set by autoinstrumentation
kubectl exec cacao-chris-heart-75666d5558-vw5gm -- sh -c 'env PYTHONPATH="$PWD:$PYTHONPATH" python manage.py shell -c "import feeds.models"'Actual Result
All except for (B) work. (B) crashes with a Django-related message
Traceback (most recent call last):
File "/opt/app-root/src/manage.py", line 23, in <module>
main()
File "/opt/app-root/src/manage.py", line 19, in main
execute_from_command_line(sys.argv)
File "/opt/app-root/lib64/python3.11/site-packages/django/core/management/__init__.py", line 442, in execute_from_command_line
utility.execute()
File "/opt/app-root/lib64/python3.11/site-packages/django/core/management/__init__.py", line 436, in execute
self.fetch_command(subcommand).run_from_argv(self.argv)
File "/opt/app-root/lib64/python3.11/site-packages/django/core/management/base.py", line 412, in run_from_argv
self.execute(*args, **cmd_options)
File "/opt/app-root/lib64/python3.11/site-packages/django/core/management/base.py", line 458, in execute
output = self.handle(*args, **options)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/opt/app-root/lib64/python3.11/site-packages/django/core/management/commands/shell.py", line 117, in handle
exec(options["command"], globals())
File "<string>", line 1, in <module>
File "/opt/app-root/src/feeds/models.py", line 8, in <module>
class Feed(models.Model):
File "/opt/app-root/lib64/python3.11/site-packages/django/db/models/base.py", line 134, in __new__
raise RuntimeError(
RuntimeError: Model class feeds.models.Feed doesn't declare an explicit app_label and isn't in an application in INSTALLED_APPS.
Kubernetes Version
1.27.3
Operator version
0.87.0
Collector version
0.86.0
Environment information
No response
Log output
No response
Additional context
Somewhat related to #1884 (comment), however the container image I am using does not use a custom PYTHONPATH. The chris application is a fairly standard Django application, its container image is based on registry.access.redhat.com/ubi9/python-311:1-17.1692772360 and its dependencies are installed with pip. Nothing magical going on here.
I propose two solutions: either
- Prepend the container's working directory to the value of
PYTHONPATHadded by Instrumentation - Document Python packaging best practices and require that Python applications adhere to them when autoinstrumentation is used