💨

Laravel + Datadog + CloudRun Sidecarで運用したい時の設定

2024/01/03に公開

概要

本記事では、Laravel + Datadog + CloudRun Sidecarの環境で運用したいときにどのような設定をすれば良いかについて記述します。

対象読者・コンテキスト

本記事ではDatadogにログとトレース(APM)を連携するやり方を記載しています。
CI/CDツールとしてはCloudBuildを使うことを想定していますが、どのようなツールであっても設定は変わらないと思います。

CloudRun Sidecarとは?

従来のCloudRunは単一のコンテナでしかホスティングできませんでしたが、複数のコンテナを立ち上げて実行ができるようになりました。これをSidecarと言います。
今までLaravel + webサーバーの組み合わせをCloudRunでホスティングしようとすると、どうしても一つのコンテナに複数のサービスを入れざるを得ませんでした。これはDockerではベストプラクティスとされているone service per containerの思想に対立します。
しかしGKE(Kubernates)などのサービスを使うほど複雑な作りをしているわけでもないので、CloudRunのシンプルさに魅力を感じる...そんな時にSidecarを使うというわけです。

重要なポイントとして、お互いのコンテナの通信は、localhost:portで行うことが挙げられます。この辺りはdocker-composeなどの通信手段とは違う部分です。ここは本記事ではとても大事なポイントなのでぜひ覚えておいてください。
また素晴らしい機能の一つとして、コンテナ間でボリュームの共有ができる点が挙げられます。本記事でのdatadog agentによるログ収集は、この機能を用います。

公式の記事
https://cloud.google.com/blog/ja/products/serverless/cloud-run-now-supports-multi-container-deployments

CloudRun

CloudRunでは、Datadog, Laravel(app), Nginxイメージを3コンテナ体制で動かします。

Nginx

Dockerfile
FROM nginx:latest

...

COPY default.conf /etc/nginx/conf.d/default.conf

...

やっていることは単純で、confファイルをnginxのconfに上書きするだけです。
nginxのconfファイルではCloudRun上でリッスンしたいポート(デフォルトでは8080)をリッスンしてください。
また前述の通り、nginx -> appの接続はlocalhost:portで行うので、fastcgi_passにはそのように記載してください。

fastcgi_pass   127.0.0.1:{appコンテナでリッスンするポート番号};

app

Laravelの本体が入っているコンテナです。9000ポートでリッスンしていることを想定しています。Laravelのセットアップについて記述は省略します。

Dockerfile
FROM {PHP fpmのイメージ}

...

COPY .datadog-setup.php datadog-setup.php
RUN php datadog-setup.php --php-bin=all --enable-appsec --enable-profiling
ENV DD_AGENT_HOST=localhost
ENV DD_SERVICE=service_name
ENV DD_VERSION=1.0.0

...

datadog-setup.phpについてはDatadog用のトレーシングライブラリのインストーラーです。トレーシングライブラリはAPMなどに使います。ここでやっていることは、すでにgitにコミットされているインストーラーを起動して、各環境変数を定義しているだけです。
下記が公式の記事となります。
https://docs.datadoghq.com/ja/tracing/trace_collection/automatic_instrumentation/dd_libraries/php/

Datadogとコンテナを分けたのにこっちにもDatadogをインストールするのかと不思議に思うと思いますが、これはトレースをDatadog agentサービスが稼働しているコンテナに送信するための仕組みをインストールするので、また少し意味合いが異なります。実際にトレースやログを収集して処理しているのはDatadog agentのコンテナの方です。

  • DD_AGENT_HOST
    • トレースの送信先。デフォルトではlocalhost:8126に送信するので設定不要かもしれません
  • DD_SERVICE
    • サービス名。あなたのアプリケーション名を入力すると良いです。
  • DD_VERSION
    • バージョン。コミットハッシュなど動的にしたい場合はDockerfileにversionをARGとして定義して受け取れるようにすると良いです。
  • DD_ENV
    • お好きな環境名を設定してください。Dockerfileに記述していないのは環境ごとにこの値が異なるからです。おそらくCloudRun側の環境変数で設定することになると思います。

Datadog

Dockerfile
FROM gcr.io/datadoghq/agent:latest

COPY conf.yaml /etc/datadog-agent/conf.d/php.d/conf.yaml

ENV DD_SITE=datadoghq.com
ENV DD_APM_ENABLED=true
ENV DD_LOGS_ENABLED=true
ENV DD_APM_NON_LOCAL_TRAFFIC=false

Datadog agentが起動しているコンテナです。8126ポートでリッスンされていることを想定しています。

  • DD_SITE
    • datadoghq.comで良いと思います。むしろそれ以外のパターンはあるのでしょうか?
  • DD_APM_ENABLED
    • 文字通りの意味です。APMを使うので今回はtrueです。
  • DD_LOGS_ENABLED
    • こちらも文字通りの意味です。
  • DD_APM_NON_LOCAL_TRAFFIC
    • 大事なポイントです。Sidecarの場合はfalseにしてください。トレース取得をコンテナ間通信でする場合はtrueにするとDatadogにも記載があるかと思いますが、Sidecarではlocalhost経由で通信するのでfalseにします。
  • DD_HOSTNAME
    • お好きなホスト名を指定します。CloudRunのサービス名などになると思います。これも環境ごとに違うので、CloudRunの環境変数で設定するなどしてください。

conf.yamlは下記のように書きます。

logs:
  - type: file
    path: "/app/storage/logs/*"
    service: service_name
    source: php

ここでまたポイントですが、Datadog agentのログ取得はCloudRun Sidecarのボリューム共有機能を用いて取得します。ここでは取得するべきログが、/app/storage/logs/にボリューム共有でマウントされていることを想定しています。

ログ取得について

トレース(APM)についてはここまでの設定をしてもらえればいい感じに出ると思います。ログについては前述の通り、ボリューム共有機能を使っているので、CloudRun側で設定が必要です。

ボリュームはインメモリボリュームを使用します。詳しい設定手順は下記を参照してください。
https://cloud.google.com/run/docs/configuring/in-memory-volumes?hl=ja

ポイントはログが配置されているフォルダ(例: /app/storage/logs/)をDatadogとappコンテナで共有するように設定することです。こうすることで、DatadogコンテナからLaravelのログを取得して、それをDatadogに連携することができます。

インメモリボリュームについては、最大サイズがデフォルトではコンテナの合計メモリの半分です。もしログの量が多くメモリを圧迫する可能性がある場合は、Laravelのログローテーション機能を使ってみてください。

ちなみに

本記事ではインメモリボリュームにログを保持していますが、標準出力に出すとGCPが自動でログを取得してくれるので、そこからLog Routerを使ってDatadogに連携する方法もあります。
基本的にこちらの方が良いとは思いますが、ログが長すぎるとGCP上でのログが切れてしまう問題があったので、インメモリボリュームを使うやり方を採用しました。

Discussion