Download PDF
Download page Install the Python Agent in Containers.
Install the Python Agent in Containers
This page explains your options to install the Python Agent in a containerized application.
When deploying the Python Agent in a containerized application, you need to deploy both the Dynamic Languages Proxy and the Python Agent:
Deploy the Dynamic Languages Proxy
The Dynamic Languages Proxy acts as a communication gateway between the Python Agent running in the application process and the AppDynamics Controller.
You can use one of two available options to deploy the Dynamic Languages Proxy, either the:
- Sidecar Container (recommended): This option follows the best practice of one process per container. The Dynamic Language Proxy runs in a sidecar container separate from the application container, or
- Application Container: This option uses the default configuration to run the proxy in the same container as the application.
Deploy Dynamic Languages Proxy in a Sidecar Container (recommended)
AppDynamics recommends following the best practice of maintaining one process per container.
To use a sidecar container to run the Dynamic Languages Proxy, add the
--use-manual-proxy
parameter when starting the Python application.pyagent run --use-manual-proxy python ./app.py
BASHThe
--use-manual-proxy
parameter prevents the Python Agent agent from starting the Dynamic Languages Proxy as a separate process in the same application container, which is the default behavior.Configure the deployed sidecar container to run the proxy. This Kubernetes deployment spec snippet shows how to define a second container named
proxy
that uses the dl-proxy image published on Docker Hub.apiVersion: apps/v1 kind: Deployment metadata: name: mypython-app spec: <...> spec: containers: - name: mypython-app image: myrepo/python-app-with-appd:v1 <...> - name: proxy image: docker.io/appdynamics/dl-proxy:latest imagePullPolicy: Always env: - name: APPDYNAMICS_DEBUG_LOG value: "on" - name: APPDYNAMICS_LOGGING_LEVEL value: "debug" - name: APPDYNAMICS_TCP_COMM_HOST value: "0.0.0.0" - name: APPDYNAMICS_TCP_COMM_PORT value: "9091" - name: APPDYNAMICS_TCP_PORT_RANGE value: "10000-10100" ports: - containerPort: 9091 protocol: TCP resources: ...
YML
Deploy Dynamic Languages Proxy in the Application Container
If you prefer to run the proxy as a separate process in the same container as the application, omit the --use-manual-proxy
parameter when starting the Python application.
pyagent run python ./app.py
The Python Agent automatically starts a separate process for the proxy in the same container. Avoid adding a sidecar container to the deployment so only the application container is defined.
Deploy the Python Agent in the Application Container
To instrument a Python application, the required Python Agent packages must be deployed to the application container and loaded by the application at startup. The available options are:
- Use a Dockerfile: This option uses a Dockerfile to deploy the Python Agent in the application Docker image at build time.
- Use Init Containers: This option uses Kubernetes init containers to deploy the Python Agent into the application container when the application starts up. Using the init containers option does not require any changes to the application Docker image.
For each of these options, the steps assume the use of a sidecar to run the Dynamic Languages Proxy and that you have kubectl
installed.
Once you have deployed the Python Agent, see Validate the Python Agent Install.
Note that Cluster Agent auto-instrumentation is not supported for Python applications running in Kubernetes clusters where the Cluster Agent is installed. See Container Platforms.
Use a Dockerfile
This option uses a Dockerfile to deploy the Python Agent in the Docker image at build time. The built Docker image must contain the application and the Python Agent.
To deploy the agent in the application image during the image build:
- Copy the Application Files to the Image
- Perform the PIP Install
- Copy the Controller Certs to the Image (on-premises Controller only)
- Use Pyagent to Run the Application
- Set the Python Agent Environment Variables
- Validate the Python Agent Install
Copy the Application Files to the Image
Edit the Dockerfile to copy the application folder, and set up the requirements and start script:
COPY mypythonapp/ /app/
WORKDIR /app
COPY requirements.txt .
RUN chmod +x ./app.py
EXPOSE 8080
Perform the PIP Install
Run the pip
install
command as described in Install the Python Agent. Specify the version of the latest appdynamics
release from the AppDynamics Python project. For example:
RUN pip install -U appdynamics==21.12.2.4693 -r requirements.txt
Copy the Controller Certs to the Image (On-Premises Controller Only)
For Python Agents communicating with an on-premises Controller, edit the Dockerfile to copy the cacerts
file containing the on-premises certs to the image and set the APPDYNAMICS_CONTROLLER_SSL_CERTFILE
environment variable.
For example:
COPY ./onprem-cacerts /opt/appdynamics/cacerts
ENV APPDYNAMICS_CONTROLLER_SSL_CERTFILE=/opt/appdynamics/cacerts
Use Pyagent to Run the Application
Use pyagent
to run the application based on the use of Flask or Django frameworks. See Install the Python Agent for additional support of WSGI frameworks. Include the --use-manual-proxy
parameter to prevent the Dynamic Languages Proxy from starting in the application container.
CMD pyagent run --use-manual-proxy python ./app.py
A complete Dockerfile Pyagent example:
FROM python:3.7
# Use latest version from https://pypi.org/project/appdynamics/#history
ENV APPD_AGENT_VERSION=21.12.2.4693
COPY mypythonapp/ /app/
WORKDIR /app
RUN chmod +x ./app.py
EXPOSE 8080
RUN pip install -U appdynamics==${APPD_AGENT_VERSION} -r requirements.txt
CMD pyagent run --use-manual-proxy python ./app.py
Set the Python Agent Environment Variables
Note that APPDYNAMICS_TCP_COMM_PORT
should be set to an available port in the application and proxy container and is used for the agent to proxy communication. See TCP Mode Configuration.
How you set the Python Agent environment variables depends on how you deploy the image. For a Docker deployment, set the agent environment variables in the Dockerfile, or external file you supply, as a parameter to docker run
. For example:
ENV APPDYNAMICS_TCP_COMM_PORT=9091
ENV APPDYNAMICS_AGENT_APPLICATION_NAME=<value>
ENV APPDYNAMICS_AGENT_TIER_NAME=<value>
ENV APPDYNAMICS_AGENT_REUSE_NODE_NAME=true
ENV APPDYNAMICS_AGENT_REUSE_NODE_NAME_PREFIX=<value>
ENV APPDYNAMICS_AGENT_ACCOUNT_NAME=<value>
ENV APPDYNAMICS_AGENT_ACCOUNT_ACCESS_KEY=<value>
ENV APPDYNAMICS_CONTROLLER_HOST_NAME=<value>
ENV APPDYNAMICS_CONTROLLER_PORT=<value>
ENV APPDYNAMICS_CONTROLLER_SSL_ENABLED=<value>
For Kubernetes applications, set these environment variables using configmaps, secrets, and the deployment spec as described in Best Practices to Configure Agents in Kubernetes.
Use a
configmap
to set the agent environment variables that are shared across Python applications in a namespace, as shown in thisappd-python-config.yaml
example:apiVersion: v1 data: APPDYNAMICS_TCP_COMM_PORT: "9091" APPDYNAMICS_AGENT_APPLICATION_NAME: "<value>" APPDYNAMICS_AGENT_REUSE_NODE_NAME: "<value>" APPDYNAMICS_AGENT_ACCOUNT_NAME: "<value>" APPDYNAMICS_CONTROLLER_HOST_NAME: "<value>" APPDYNAMICS_CONTROLLER_PORT: "<value>" APPDYNAMICS_CONTROLLER_SSL_ENABLED: "<value>" kind: ConfigMap metadata: name: appd-python-config
YMLApply the
configmap
to the application namespace:$ kubectl -n <app-ns> apply -f appd-python-config.yaml
BASHUpdate the deployment spec to reference the
configmap
:spec: containers: - name: python-app envFrom: - configMapRef: name: appd-python-config ...
YMLCreate a secret for the Controller access key using
kubectl
:$ kubectl -n <app-ns> create secret generic appd-agent-secret --from-literal=access-key=<access-key>
BASHUpdate the deployment spec to reference the secret:
spec: containers: - name: python-app env: - name: APPDYNAMICS_AGENT_ACCOUNT_ACCESS_KEY valueFrom: secretKeyRef: name: appd-agent-secret key: access-key ...
YMLSet the application-specific tier name environment variable
APPDYNAMICS_AGENT_TIER_NAME
in the deployment spec:spec: containers: - name: python-app env: - name: APPDYNAMICS_AGENT_TIER_NAME value: python-service - name: APPDYNAMICS_AGENT_REUSE_NODE_NAME_PREFIX value: python-service ...
YMLAdd the proxy container
spec: containers: ... - name: proxy image: appdynamics/dl-proxy:latest imagePullPolicy: Always env: - name: APPDYNAMICS_DEBUG_LOG value: "on" - name: APPDYNAMICS_LOGGING_LEVEL value: "debug" - name: APPDYNAMICS_TCP_COMM_HOST value: "0.0.0.0" - name: APPDYNAMICS_TCP_COMM_PORT value: "9091" - name: APPDYNAMICS_TCP_PORT_RANGE value: "10000-10100" ports: - containerPort: 9091 protocol: TCP resources: limits: cpu: 500m memory: 900M requests: cpu: 400m memory: 600M ...
YMLBelow is a complete example of a Kubernetes Deployment spec:
apiVersion: apps/v1 kind: Deployment metadata: name: mypython-app spec: selector: matchLabels: name: mypython-app replicas: 1 template: metadata: labels: name: mypython-app spec: containers: - name: mypython-app image: myrepo/python-app-with-appd:v1 imagePullPolicy: Always env: - name: APPDYNAMICS_AGENT_TIER_NAME value: mypython-app - name: APPDYNAMICS_AGENT_REUSE_NODE_NAME_PREFIX value: python-service - name: APPDYNAMICS_AGENT_ACCOUNT_ACCESS_KEY valueFrom: secretKeyRef: key: access-key name: appd-agent-secret envFrom: - configMapRef: name: appd-python-config ports: - containerPort: 8080 - name: proxy image: appdynamics/dl-proxy:latest imagePullPolicy: Always env: - name: APPDYNAMICS_DEBUG_LOG value: "on" - name: APPDYNAMICS_LOGGING_LEVEL value: "debug" - name: APPDYNAMICS_TCP_COMM_HOST value: "0.0.0.0" - name: APPDYNAMICS_TCP_COMM_PORT value: "9091" - name: APPDYNAMICS_TCP_PORT_RANGE value: "10000-10100" ports: - containerPort: 9091 protocol: TCP resources: limits: cpu: 500m memory: 900M requests: cpu: 400m memory: 600M restartPolicy: Always --- apiVersion: v1 kind: Service metadata: name: mypython-app spec: selector: name: mypython-app ports: - name: "8080" port: 8080 targetPort: 8080 type: LoadBalancer status: loadBalancer: {}
YML
Use Init Containers
This option uses Kubernetes init containers to install the Python Agent into the application container when the application starts up. The Use of init containers requires that the application image is built without the Python Agent. The benefit of this option is that it does not require changes to the application image.
The init container provides a startup script that is used to override the default application startup command. It runs pip
to install the Python Agent dependencies in the application container and then starts the application based on the configured APP_ENTRY_POINT
environment variable.
To instrument a Python application using init containers:
- Build the Application Image Without the Python Agent
- Add the Init Container to the Deployment Spec
- Set the Python Agent Environment Variables
- Validate the Python Agent Install
Build the Application Image Without the Python Agent
The following example is Dockerfile that builds an application image without including the Python Agent dependency.
FROM python:3.7
COPY mypythonapp/ /app/
WORKDIR /app
RUN chmod +x ./app.py
EXPOSE 8080
RUN pip install -r requirements.txt
CMD pyagent run python ./app.py
Add the Init Container to the Deployment Spec
The deployment spec below illustrates the changes required to use an init container:
- Line 16: The
appd-python-init
init container is defined and copies the contents of the init container to the application container. - Line 22: The
init
container references the python-agent-init image from Docker Hub. - Line 78: A volume mount is defined to share the contents of the init container with the application container.
Line 30: The application startup command is overridden to run the script
run-with-agent.sh
, which is copied from the init container.Line 34:
APP_ENTRY_POINT
andAPPDYNAMICS_AGENT_VERSION
are defined on the application container to specify the app entry point and agent version used byrun-with-agent.sh. APPDYNAMICS_AGENT_VERSION
has the format a.b.c.d and is based on the version number listed on the PyPi AppDynamics release page.
We recommend you to deploy Dynamic Languages proxy for better performance.
Use the following code samples depending on your proxy type:
apiVersion: apps/v1
kind: Deployment
metadata:
name: mypython-app-init
spec:
selector:
matchLabels:
name: mypython-app-init
replicas: 1
template:
metadata:
labels:
name: mypython-app-init
spec:
initContainers:
- name: appd-python-init
command:
- cp
- -r
- /opt/appdynamics/.
- /opt/temp
image: docker.io/appdynamics/python-agent-init:1.0
imagePullPolicy: Always
volumeMounts:
- mountPath: /opt/temp
name: appd-python-init
containers:
- name: mypython-app-init
image: myrepo/python-app-no-appd:v1
command: ["/bin/sh"]
args: ["-c", "/opt/appdynamics-python/run-with-agent.sh"]
imagePullPolicy: Always
env:
- name: APP_ENTRY_POINT
value: "--use-manual-proxy python /app/app.py"
- name: APPDYNAMICS_AGENT_VERSION
# Use latest version from https://pypi.org/project/appdynamics/#history
value: 21.12.2.4693
- name: APPDYNAMICS_AGENT_TIER_NAME
value: mypython-app-init
- name: APPDYNAMICS_AGENT_ACCOUNT_ACCESS_KEY
valueFrom:
secretKeyRef:
key: access-key
name: appd-agent-secret
envFrom:
- configMapRef:
name: appd-python-config
ports:
- containerPort: 8080
volumeMounts:
- mountPath: /opt/appdynamics-python
name: appd-python-init
- name: proxy
image: appdynamics/dl-proxy:latest
imagePullPolicy: Always
env:
- name: APPDYNAMICS_DEBUG_LOG
value: "on"
- name: APPDYNAMICS_LOGGING_LEVEL
value: "debug"
- name: APPDYNAMICS_TCP_COMM_HOST
value: "0.0.0.0"
- name: APPDYNAMICS_TCP_COMM_PORT
value: "9091"
- name: APPDYNAMICS_TCP_PORT_RANGE
value: "10000-10100"
ports:
- containerPort: 9091
protocol: TCP
resources:
limits:
cpu: 500m
memory: 900M
requests:
cpu: 400m
memory: 600M
volumes:
- name: appd-python-init
emptyDir: {}
restartPolicy: Always
---
apiVersion: v1
kind: Service
metadata:
name: mypython-app-init
spec:
selector:
name: mypython-app-init
ports:
- name: "8080"
port: 8080
targetPort: 8080
type: LoadBalancer
status:
loadBalancer: {}
apiVersion: apps/v1
kind: Deployment
metadata:
name: mypython-app-init
spec:
selector:
matchLabels:
name: mypython-app-init
replicas: 1
template:
metadata:
labels:
name: mypython-app-init
spec:
initContainers:
- name: appd-python-init
command:
- cp
- -r
- /opt/appdynamics/.
- /opt/temp
image: docker.io/appdynamics/python-agent-init:1.0
imagePullPolicy: Always
volumeMounts:
- mountPath: /opt/temp
name: appd-python-init
containers:
- name: mypython-app-init
image: myrepo/python-app-no-appd:v1
command: ["/bin/sh"]
args: ["-c", "/opt/appdynamics-python/run-with-agent.sh"]
imagePullPolicy: Always
env:
- name: APP_ENTRY_POINT
value: "python /app/app.py"
- name: APPDYNAMICS_AGENT_VERSION
# Use latest version from https://pypi.org/project/appdynamics/#history
value: 21.12.2.4693
- name: APPDYNAMICS_AGENT_TIER_NAME
value: mypython-app-init
- name: APPDYNAMICS_AGENT_ACCOUNT_ACCESS_KEY
valueFrom:
secretKeyRef:
key: access-key
name: appd-agent-secret
envFrom:
- configMapRef:
name: appd-python-config
ports:
- containerPort: 8080
volumeMounts:
- mountPath: /opt/appdynamics-python
name: appd-python-init
volumes:
- name: appd-python-init
emptyDir: {}
restartPolicy: Always
---
apiVersion: v1
kind: Service
metadata:
name: mypython-app-init
spec:
selector:
name: mypython-app-init
ports:
- name: "8080"
port: 8080
targetPort: 8080
type: LoadBalancer
status:
loadBalancer: {}
Set the Python Agent Environment Variables
When using an init container, set the Python Agent environment variables for Kubernetes as described in Use a Dockerfile.
Validate the Python Agent Install
Once you have deployed the Python application with the Python Agent and generated load on the application, the application should appear in the AppDynamics Controller based on the configured application, tier, and node names. To troubleshoot communication issues between the agent and the proxy, or proxy and Controller log on to the application and proxy containers. Note that logs will not appear until the application process receives requests.
# check that the app and proxy containers are running
kubectl -n <app ns> get pods
NAME READY STATUS RESTARTS AGE
mypython-app-7687956c77-q5z85 2/2 Running 0 40s
# if both containers aren't running, check events regarding image pulls, etc
kubectl -n <app ns> get events
# check the Python Agent logs in the application container for issues communicating with the proxy running in the sidecar
kubectl -n <app ns> exec -it <pod name> -c <app container name> /bin/bash
cd /tmp/appd/logs
cat <app-node names>.log
# check the proxy logs for issues communicating with the AppDynamics Controller
kubectl -n <app ns> exec -it <pod name> -c proxy /bin/bash
cd /tmp/appd/logs/<app folder>
cat agent.<timestamp>.log