このページでは、コンテナ化されたアプリケーションに Python エージェントをインストールするオプションについて説明します。

コンテナ化されたアプリケーションに Python エージェントを展開する場合、ダイナミック言語プロキシと Python エージェントの両方を展開する必要があります。

ダイナミック言語プロキシの展開

ダイナミック言語プロキシは、アプリケーションプロセスで実行されている Python エージェントと AppDynamics コントローラ間の通信ゲートウェイとして機能します。

次の 2 つの使用可能なオプションのいずれかを使用して、ダイナミック言語プロキシを展開できます。

  • サイドカーコンテナ(推奨):このオプションは、コンテナごとに 1 つのプロセスのベストプラクティスに従います。ダイナミック言語プロキシは、アプリケーションコンテナとは別のサイドカーコンテナで実行されます。
  • アプリケーションコンテナ:このオプションは、デフォルト設定を使用して、アプリケーションと同じコンテナでプロキシを実行します。

サイドカーコンテナへのダイナミック言語プロキシの展開(推奨)

AppDynamics では、コンテナごとに 1 つのプロセスを維持するというベストプラクティスに従うことを推奨しています。

  1. サイドカーコンテナを使用してダイナミック言語プロキシを実行するには、Python アプリケーションの起動時に --use-manual-proxy パラメータを追加します。

    pyagent run --use-manual-proxy python ./app.py
    BASH

    --use-manual-proxy パラメータは、Python エージェントがダイナミック言語プロキシを同じアプリケーションコンテナ内の別のプロセスとして開始すること(デフォルト動作)を防ぎます。

  2. 展開されたサイドカーコンテナを、プロキシを実行するように設定します。この Kubernetes 展開仕様のスニペットでは、Docker Hub で公開されている dl-proxy イメージを使用する proxy という名前の 2 番目のコンテナを定義する方法を示しています。

    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

アプリケーションコンテナへのダイナミック言語プロキシの展開

プロキシをアプリケーションと同じコンテナ内の別のプロセスとして実行する場合は、Python アプリケーションの起動時に --use-manual-proxy パラメータを省略します。

pyagent run python ./app.py
BASH

Python エージェントは、同じコンテナ内のプロキシに対して別のプロセスを自動的に開始します。アプリケーションコンテナのみが定義されるように、サイドカーコンテナを展開に追加することは避けてください。

アプリケーションコンテナへの Python エージェントの展開

Python アプリケーションをインストゥルメント化するには、必要な Python エージェントパッケージをアプリケーションコンテナに展開し、スタートアップ時にアプリケーションによってロードする必要があります。次のオプションを使用できます。

  • Dockerfile の使用:このオプションでは、作成時に Dockerfile を使用して、アプリケーションの Docker イメージに Python エージェントを展開します。
  • Init コンテナの使用:このオプションでは、アプリケーションのスタートアップ時に Kubernetes init コンテナを使用して、アプリケーションコンテナに Python エージェントを展開します。init コンテナのオプションを使用する場合でも、アプリケーションの Docker イメージを変更する必要はありません。

これらの各オプションについて、この手順では、サイドカーを使用してダイナミック言語プロキシを実行し、kubectl をインストール済みであることを前提としています。

Python エージェントを展開したら、「Python エージェントのインストールの検証」を参照してください。

クラスタエージェントの自動インストゥルメンテーションは、クラスタエージェントがインストールされている Kubernetes クラスタで実行されている Python アプリケーションではサポートされないことに注意してください。「コンテナのインストールオプション」を参照してください。

Dockerfile の使用

このオプションは、Docker および Kubernetes で実行されているコンテナに適用されます。

このオプションでは、作成時に Dockerfile を使用して、Docker イメージに Python エージェントを展開します。作成された Docker イメージには、アプリケーションと Python エージェントが含まれている必要があります。 

イメージの作成時にエージェントをアプリケーションイメージに展開するには、次の手順を実行します。

  1. イメージへのアプリケーションファイルのコピー
  2. PIP インストールの実行
  3. イメージへのコントローラ証明書のコピー(オンプレミスコントローラのみ)
  4. Pyagent を使用したアプリケーションの実行
  5. Python エージェント環境変数の設定
  6. Python エージェントのインストールの検証

イメージへのアプリケーションファイルのコピー

Dockerfile を編集してアプリケーションフォルダをコピーし、要件を設定してスクリプトを開始します。

COPY mypythonapp/ /app/
WORKDIR /app
COPY requirements.txt .
RUN chmod +x ./app.py
EXPOSE 8080
TEXT

PIP インストールの実行

Pythonエージェントのインストール」の説明に従って pip install コマンドを実行します。AppDynamics Python プロジェクトから最新の appdynamics リリースのバージョンを指定します。次に例を示します。

RUN pip install -U appdynamics==21.12.2.4693 -r requirements.txt
TEXT

イメージへのコントローラ証明書のコピー(オンプレミスコントローラのみ)

オンプレミスのコントローラと通信する Python エージェントの場合は、Dockerfile を編集して、オンプレミスの証明書を含む cacerts ファイルをイメージにコピーし、APPDYNAMICS_CONTROLLER_SSL_CERTFILE 環境変数を設定します。 

次に例を示します。

COPY ./onprem-cacerts /opt/appdynamics/cacerts
ENV APPDYNAMICS_CONTROLLER_SSL_CERTFILE=/opt/appdynamics/cacerts
BASH

Pyagent を使用したアプリケーションの実行

pyagent を使用して、Flask または Django フレームワークの使用に基づいてアプリケーションを実行します。WSGI フレームワークの追加サポートについては、「Pythonエージェントのインストール」を参照してください。--use-manual-proxy パラメータを含めて、アプリケーションコンテナでダイナミック言語プロキシが開始されないようにします。

CMD pyagent run --use-manual-proxy python ./app.py
TEXT

完全な Dockerfile Pyagent の例:

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
TEXT

Python エージェント環境変数の設定

APPDYNAMICS_TCP_COMM_PORT は、アプリケーションおよびプロキシコンテナで使用可能なポートに設定する必要があり、エージェントからプロキシへの通信に使用されることに注意してください。詳細については、TCP モードの設定を参照してください。

Python エージェント環境変数の設定方法は、イメージの展開方法によって異なります。Docker 展開の場合、Dockerfile または指定した外部ファイルのエージェント環境変数をパラメータとして docker run に設定します。次に例を示します。

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>
ENV APPDYNAMICS_AGENT_CONTAINER_ENABLED=true
TEXT

Kubernetes アプリケーションの場合は、「Kubernetes でエージェントを設定するためのベストプラクティス」の説明に従って、configmap、秘密、および導入仕様を使用してこれらの環境変数を設定します。

  1. この appd-python-config.yaml の例で示されているように、configmap を使用して、名前空間内の Python アプリケーション間で共有するエージェント環境変数を設定します。

    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 
    YML
  2. configmap をアプリケーションの名前空間に適用します。

    $ kubectl -n <app-ns> apply -f appd-python-config.yaml 
    BASH
  3. 導入仕様を更新して、configmap を参照します。

    spec:
      containers:
      - name: python-app
        envFrom:
        - configMapRef:
            name: appd-python-config
     ...
    YML
  4. kubectl を使用してコントローラアクセスキーの秘密を作成します。

    $ kubectl -n <app-ns> create secret generic appd-agent-secret --from-literal=access-key=<access-key>
    BASH
  5. 導入仕様を更新して、秘密を参照します。

    spec:
      containers:
      - name: python-app
        env:
        - name: APPDYNAMICS_AGENT_ACCOUNT_ACCESS_KEY
          valueFrom:
            secretKeyRef:
              name: appd-agent-secret
              key: access-key
     ...
    YML
  6. 導入仕様でアプリケーション固有の階層名環境変数 APPDYNAMICS_AGENT_TIER_NAME を設定します。

    spec:
      containers:
      - name: python-app
        env:
        - name: APPDYNAMICS_AGENT_TIER_NAME
          value: python-service
        - name: APPDYNAMICS_AGENT_REUSE_NODE_NAME_PREFIX
          value: python-service
     ...
    YML
  7. プロキシコンテナを追加します

    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
     ...
    YML

    Kubernetes 導入仕様の完全な例を以下に示します。

    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

Init コンテナの使用

このオプションは、Kubernetes で実行されているコンテナに適用されます。

このオプションでは、アプリケーションのスタートアップ時に Kubernetes init コンテナを使用して、アプリケーションコンテナに Python エージェントをインストールします。init コンテナを使用するには、Python エージェントを使用せずにアプリケーションイメージを作成する必要があります。このオプションの利点は、アプリケーションイメージを変更する必要がないことです。

init コンテナは、デフォルトのアプリケーション スタートアップ コマンドを上書きするために使用されるスタートアップスクリプトを提供します。これは、pip を実行して Python エージェントの依存関係をアプリケーションコンテナにインストールしてから、設定された APP_ENTRY_POINT 環境変数に基づいてアプリケーションを起動します。

init コンテナを使用して Python アプリケーションをインストゥルメント化するには、次の手順を実行します。

  1. Python エージェントを使用しないアプリケーションイメージの作成
  2. 導入仕様への Init コンテナの追加
  3. Python エージェント環境変数の設定
  4. Python エージェントのインストールの検証

Python エージェントを使用しないアプリケーションイメージの作成

Python エージェントの依存関係を含めずにアプリケーションイメージを作成する Dockerfile の例を以下に示します。

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
TEXT

導入仕様への Init コンテナの追加

以下の導入仕様は、init コンテナを使用するために必要な変更を示しています。

  • 16 行目:appd-python-init init コンテナが定義され、init コンテナの内容をアプリケーションコンテナにコピーします。
  • 22 行目:init コンテナが、Docker Hub からの python-agent-init イメージを参照します。
  • 78 行目:init コンテナの内容をアプリケーションコンテナと共有するために、ボリュームマウントが定義されます。
  • 30 行目:アプリケーション スタートアップ コマンドが、init コンテナからコピーされたスクリプト run-with-agent.sh を実行するように上書きされます。

  • 34 行目:アプリのエントリポイントと run-with-agent.sh. によって使用されるエージェントバージョンを指定するために、アプリケーションコンテナで APP_ENTRY_POINTAPPDYNAMICS_AGENT_VERSION が定義されます。 APPDYNAMICS_AGENT_VERSION は a.b.c.d の形式で、PyPi AppDynamics リリースページに記載されているバージョン番号に基づきます。

パフォーマンスを向上させるために、ダイナミック言語プロキシを展開することをお勧めします。

プロキシタイプに応じて、次のサンプルコードを使用します。

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: {}]

---
kind: RoleBinding
apiVersion: rbac.authorization.k8s.io/v1
metadata:
    name: pod-reader-binding
    namespace: default
    subjects:
- kind: ServiceAccount
    name: default
    namespace: default
roleRef:
    kind: Role
    name: pod-reader
    apiGroup: rbac.authorization.k8s.io
YML
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: {}

---
kind: RoleBinding
apiVersion: rbac.authorization.k8s.io/v1
metadata:
    name: pod-reader-binding
    namespace: default
    subjects:
- kind: ServiceAccount
    name: default
    namespace: default
roleRef:
    kind: Role
    name: pod-reader
    apiGroup: rbac.authorization.k8s.io
YML


Python エージェント環境変数の設定

init コンテナを使用する場合は、「Dockerfile の使用」の説明に従って、Kubernetes の Python エージェント環境変数を設定します。

Python エージェントのインストールの検証

Python エージェントを使用して Python アプリケーションを展開し、アプリケーションに対する負荷を生成すると、設定されたアプリケーション、階層、およびノードの名前に基づいて、アプリケーションが AppDynamics コントローラに表示されます。エージェントとプロキシ、またはプロキシとコントローラ間の通信の問題をトラブルシューティングするには、アプリケーションおよびプロキシコンテナにログオンします。アプリケーションプロセスがリクエストを受信するまで、ログは表示されないことに注意してください。

# 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
BASH