12
4

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 1 year has passed since last update.

DatadogAgentとアプリケーションをCloud Runに同居させる

Last updated at Posted at 2021-11-24

要約

  • Cloud Runで動くPHPアプリケーションのAPMをDatadogに送信したい
  • supervisordを使ってコンテナ内にDatadogAgentとApacheを同居させた
  • supervisordのEventListener機能を使って、"Apacheの終了=コンテナの終了"を実現した

経緯

弊社のプラットフォーム事業本部ではDatadogの利用が進められています。
パフォーマンスの可視化を進めるために、私のいるチームが持っているPHPアプリケーションも、
Datadogに対応してAPMを送信できるようにしようとしています。
PHPアプリケーションはApacheモジュールとして動作する形になっていて、
GCPのフルマネージドなCloud Run上で稼働しています。

さて、Cloud Run上で動くアプリケーションのAPMを取るための方法としては、
公式ドキュメントにこのような記述があります。

注: この機能は、Google Cloud Run for Anthos/GKE でサポートされています (Cloud Run Fully Managed ではサポートされていません)。

😇
というわけでDatadogのGoogle Cloud Platform インテグレーションを使ったAPMの収集はできないらしいので、別の方法を考える必要があります。

コンテナの中でDatadogAgentとアプリケーションの両方を動かすことを考えたので、どのように実現したかを書きます。

環境情報

  • image: php:x.x-apache

実現方法

ざっくりと以下の三つの点について説明します。

  • DatadogAgentインストール
  • Dockerコンテナで二つのアプリケーションを同居させる
  • コンテナごと終了する

DatadogAgentインストール

datadog-agentとdatadog-php-tracerをインストールします。
datadog-agentがメトリクスをサーバーに送信する役割で、
datadog-php-tracerがアプリケーションのAPMをとってagentに投げる役割です。

基本的にパッケージからインストールするかインストールスクリプトの実行で完了します。

# Install datadog-agent
ARG dd_api_key
ENV DD_API_KEY=$dd_api_key
RUN curl -Lo install_agent.sh https://raw.githubusercontent.com/DataDog/datadog-agent/main/cmd/agent/install_script.sh \
    && bash install_agent.sh

# Install datadog-tracer
ENV DDTRACE_VERSION=0.xx.0
RUN curl -Lo datadog-php-tracer.deb https://github.com/DataDog/dd-trace-php/releases/download/${DDTRACE_VERSION}/datadog-php-tracer_${DDTRACE_VERSION}_amd64.deb \
    && dpkg -i ./datadog-php-tracer.deb \
    && rm datadog-php-tracer.deb

また、datadog以前はNew RelicでAPMを取っていました。
datadog-tracerのPHP拡張モジュールと両方入れると
Found incompatible module: newrelic, disabling conflicting functionality
と言われて競合しました。

Dockerコンテナで二つのアプリケーションを同居させる

Dockerコンテナで複数のアプリケーションを動かす方法については、
公式ドキュメントに記載があります。
ドキュメントには二通りの方法が提示されています。

  1. shell scriptを使う方法
  2. supervisordを使う方法

再起動等のプロセス制御をやりたいのでsupervisordを使います。

supervisordの設定ファイル(supervisord.conf)にdatadog-trace-agentとapacheの設定を記述します。

supervisord.conf
[supervisord]
nodaemon=true

[program:datadog-tracer]
command=/opt/datadog-agent/embedded/bin/trace-agent
user=dd-agent
autorestart=true

[program:apache2]
command=/bin/bash -c "apache2-foreground"

基本的に上記の設定だけで簡単に同居させることができます。
supervisordがdockerコンテナの中でPID1として動くので、nodaemon=trueにする必要があります。

apacheにautorestartが設定されていないですが、これが次のEventListenerの話になります。

EventListener

元々はApacheがPID1プロセスとして動いていたため、Apacheが落ちるとコンテナも一緒に落ちる仕組みになっていました。
supervisordの導入でsupervisordがPID1になります。
これによって上記の仕組みが働かなくなるため、別の仕組みを考える必要があります。

supervisordにはEventsという仕組みがあります。
supervisordがevents notificationを飛ばし、EventListenerと呼ばれるプロセスがこれをハンドリングします。
EventListenerは自分で自由にコードを書いて動かすことができるので、これによって目的を実現できます。

supervisord.conf
[eventlistener:exit-listener]
command=/usr/local/bin/exit_apache_listener.py
events=PROCESS_STATE_EXITED 

command=/usr/local/bin/exit_apache_listener.pyでEventListenerのコードを指定します。
events=PROCESS_STATE_EXITEDでハンドリングするイベントを指定しています。
プロセスが正常に起動したことを知らせるPROCESS_STATE_RUNNINGや、プロセスが停止状態になったことを知らせるPROCESS_STATE_STOPPED等、
いくつかのイベントが定義されています。
今回はsupervisord管理外のプロセス停止に反応したいので、PROCESS_STATE_EXITED指定します。

exit_apache_listener.pyでは無限ループでイベントをListenしています。

exit_apache_listener.py
#!/usr/bin/env python
# -*- coding: utf-8 -*-
import os
import signal
import sys

from supervisor import childutils

def main():
    while True:
        headers, payload = childutils.listener.wait()
        # '\n'を末尾に付けないと、プログラムが異常終了する
        payload_header, data = childutils.eventdata(payload + '\n')
        childutils.listener.ok()

        # apacheのマスタープロセスが終了した時に、親プロセス(supervisord)を終了する
        if (payload_header['processname'] == 'apache2') and (headers['eventname'] == 'PROCESS_STATE_EXITED'):
            os.kill(os.getppid(), signal.SIGTERM)

if __name__ == "__main__":
    main()

Apacheが終了したら、Apacheの親プロセス、すなわちsupervisordにSIGTERMを送って終了させています。
supervisordはPID1で動いていたので、supervisordを終了することでコンテナごと終了させることができます。

終わりに

Datadogのインテグレーションが用意されていないフルマネージドなCloud Runで、Datadogに対応する方法を書きました。
実験では実際に動作を確認していて、本番環境への適用はまだなので、コストやパフォーマンス等で面白い話があったらまた書くかもしれないです。

ちなみにdatadog以前はNew RelicでPHPアプリケーションのモニタリングをしていたのですが、
New Relicの場合はagentデーモンが勝手に立ち上がる仕組みがあって、簡単にCloud Runに乗せることができます😇😇😇

プラットフォーム事業本部では発信活動を強化しています。

12
4
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
12
4

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?