PHPエージェントの特徴
PHP環境でNew Relic APMを利用する場合、APMエージェントとデーモンプロセスをインストールします。これは、一般的にPHPではApache / NginxなどのWebサーバー上に複数のphpアプリケーションが稼働しているケースがあり、それぞれのPHPアプリケーション内でAPMエージェントが収集したデータをNew Relicへ送信する部分を効率化するためです。
この構成については、Webサーバー上に初めてPHPのAPMエージェントをインストールする際、そのサーバー上にデーモンプロセスがインストールされていない場合は自動的にインストールされるため、ご利用の皆様があまり意識する必要がありませんでした。しかし、昨今アプリケーションがコンテナ化され各phpアプリケーションが別々のコンテナに分散して起動されるようになると、このデーモンプロセスをどのように構成するかを明確に理解してデプロイする必要性が高まってきました。
本Postでは、このような背景を鑑み、コンテナアプリケーションにおけるNew Relic APM on PHP(APMエージェントとデーモンをどのようにデプロイするか)の構成パターンを整理します。コンテナ環境に対するセットアップ手順は公式ドキュメントに記載されていますので、詳細は割愛します。
コンテナ環境におけるエージェント構成パターン
大きく、以下の2パターンに分けることができます。
- APMエージェントとデーモンプロセスを同一のコンテナで稼働させる
- APMエージェントとデーモンプロセスを別々のコンテナで稼働させる
1. 同一コンテナパターン
まずは、アプリプロセス(APMエージェント)とデーモンプロセスを同一のコンテナで稼働させるパターンです。
前述した通り、New Relic APMのPHPエージェントはデフォルトでデーモンプロセスも同時にインストールされるため、仮想マシンの場合と同じ手順でセットアップするとこちらの構成になります。今までと変わらない手順でセットアップを行うことができるため、手順もシンプルで比較的簡単に利用を開始することができます。
しかしながら、同一コンテナ内にアプリケーションとデーモンプロセスが混在することになるため、デーモンプロセスの負荷を考慮したリソース管理ができません。
(Amazon ECSやKubernetesなどのオーケストレーションサービスは、コンテナ運用における前提(1コンテナ1プロセス)でリソース制御が可能となっているため、1コンテナ内に複数プロセスが起動していた場合にプロセス毎のリソース管理はできない)
また、オートスケールなどによって多くのコンテナが起動する場合や、マイクロサービス化によってPHPアプリケーションが増えた場合、デーモンプロセスが使用するリソースが増え、無駄なリソースを使ってしまうことにつながります。さらには、万が一デーモンプロセスに問題が発生してデータが送信できなくなった場合、デーモンプロセスの再起動などを行う必要になりますが、デーモンプロセスはアプリケーションと同一コンテナ内にいるため再起動するためにはアプリケーションコンテナ全体を再起動する必要があり、サービスに影響を与えることになります。
2. 別コンテナ(デーモン共通化)パターン
これらの課題を解決するのが、デーモンプロセスをアプリケーションコンテナと別々で起動させるパターンです。
New Relicでは、デーモンプロセスコンテナを公開しており、これをアプリケーションコンテナと別で起動することで簡単に分離することができます。
この際、クラスターの内部ロードバランサーを経由することで、デーモン自体のスケールも簡単に実現できます。
Kubernetesマニフェスト例
例えばKubernetesを利用している場合、アプリケーションPodとは別のDeploymentでデーモンPodを起動し、合わせてClusterIPでServiceを作成することで、アプリケーションコンテナ内のAPMエージェントが収集したデータをデーモンPodに送信するようにします。
具体的なマニフェスト例は以下の通りです。
apiVersion: apps/v1
kind: Deployment
metadata:
name: newrelic-php-daemon
labels:
app: newrelic-php-daemon
spec:
replicas: 1
selector:
matchLabels:
app: newrelic-php-daemon
template:
metadata:
labels:
app: newrelic-php-daemon
spec:
containers:
- name: newrelic-php-daemon
image: newrelic/php-daemon
imagePullPolicy: Always
ports:
- containerPort: 31339
livenessProbe:
tcpSocket:
port: 31339
initialDelaySeconds: 5
periodSeconds: 10
---
apiVersion: v1
kind: Service
metadata:
name: newrelic-php-daemon-service
spec:
type: ClusterIP
selector:
app: newrelic-php-daemon
ports:
- protocol: TCP
port: 31339
targetPort: 31339
この時、エージェント側は以下の設定を行います。
- newrelic.daemon.dont_launch=3
- エージェント側でデーモンプロセスを起動しないようにする
- newrelic.daemon.address
- デーモンのホスト名とポートNo 例)newrelic-php-daemon-service:31339
- エージェントはここで指定した場所に対してデータを送信しようとする
エージェント設定の詳細は公式ドキュメントを参照してください。
Option構成. サイドカーパターン
デーモンプロセスをアプリケーションプロセスから分離させるアプローチとして、サイドカー構成も候補としてあり得ます。
少なくともアプリケーションPod内のリソース利用を明確に分離することができるので、デーモンプロセスを別のServiceやDeploymentとしてデプロイすることに何らかの制約がある場合でも、アプリケーションのリソース使用量を明確に管理したい場合はこちらの構成も良いでしょう。
まとめ
各パターンのメリット・デメリットを整理すると以下の通りです。
いかがでしょうか?New Relicとしては、デーモンプロセスを共通化することを推奨しておりますが、皆様の状況やスキルセット、組織的な管理体制によって最適なパターンはそれぞれかと思います。
本Postが皆様の最適な構成を検討する参考になれば幸いです。
本ブログに掲載されている見解は著者に所属するものであり、必ずしも New Relic 株式会社の公式見解であるわけではありません。また、本ブログには、外部サイトにアクセスするリンクが含まれる場合があります。それらリンク先の内容について、New Relic がいかなる保証も提供することはありません。