はじめに

New Relicはインフラからアプリケーション、フロントエンド、モバイルに至るまで様々なデータを自動的に収集し、可視化することができます。また、自動では収集しないサービス独自のデータだったり、ビジネス指標など、様々なカスタムデータもCustom Eventとして柔軟にNew Relicに送信することもできます。Custom EventはAPI経由で直接登録する事も可能ですが、自動で定期的に情報を収集・登録を行いたい場合は、nri-flexを使うと便利です。本Postでは、Kubernetes上でnri-flexの仕組みを使って柔軟にデータを登録する方法について解説します。

Kubernetes上でのnri-flexの仕組み

nri-flexは、Infrastructureエージェントのプラグインという形で動くため、登録したいデータの収集コマンド等をConfigとして定義し、所定のディレクトリに配置するだけで定期的にデータ収集および登録を実行してくれるとても柔軟性の高い機能です。New RelicのKubernetes Integrationでは、内部的にはInfrastructureエージェントがDaemon Setで起動しているため、このエージェントにConfig Mapで実行させたいコマンドなどを設定することにより、各ノード上で定期的にコマンドが実行され、その結果がNew Relicに送られます。

Daemon Setsであるが故の課題

データを収集したいInfrastructureエージェントにプラグインを設定するだけでカスタムデータが登録できるのはこの機能自体はとても便利です。ただ、Kubernetesで設定するには少し課題があります。前述の通り、Kubernetes Integration上で動くInfrastructureエージェントはDaemon Setで動くため、全てのノードでコマンドが実行されてしまうのです。各ノード内の情報を収集する場合はとても便利なのですが、ノード外の情報を収集したいケース(例えば、外部データベースのミドルウェアレベルのメトリクス収集を行いたい場合など)は、全ノードで実行されるとデータが重複して収集・登録されてしまいます。

nri-flexをDeploymentとして動かす

Daemon Set上でnri-flexを動かすのではなく、独立したDeploymentとしてnri-flexを動かすことでこの課題を解決します。以下のマニフェストにある通り、Infrastructureエージェントをデータ転送モードとして起動することでKubernetes Integrationで収集している情報は取得しないようにし、nri-flex用のConfig Mapを渡してあげることでnri-flexだけを実行するようにしています。この例ではGoogleとYahooに対してpingを行い、そのレスポンス結果を整形してNew Relicに送信する設定になっています。

apiVersion: apps/v1
kind: Deployment
metadata:
  name: nr-sample-flex
  labels:
    app: nr-sample-flex
spec:
  replicas: 1
  selector:
    matchLabels:
      app: nr-sample-flex
  template:
    metadata:
      labels:
        app: nr-sample-flex
    spec:
      hostNetwork: true
      hostPID: true
      containers:
        - name: nr-sample-flex
          image: newrelic/infrastructure:latest
          imagePullPolicy: Always
          env:
            - name: NRIA_LICENSE_KEY
              value: <ライセンスキーを指定してください>
            - name: NRIA_IS_FORWARD_ONLY
              value: "true"
          resources:
            limits:
              memory: 300M
            requests:
              cpu: 100m
              memory: 100M
          volumeMounts:
              # Config Mapで指定した内容をエージェントの所定のパスにマウントする
            - mountPath: /etc/newrelic-infra/integrations.d/
              name: nri-integration-cfg-volume
      volumes:
        - name: nri-integration-cfg-volume
          configMap:
            name: nri-integration-cfg

---
apiVersion: /v1
kind: ConfigMap
metadata:
  name: nri-integration-cfg
  namespace: default
data:
  nri-flex.yml: |
    ---
    integrations:
      - name: nri-flex
        config:
          name: pingFlex
          apis:
            - name: ping
              commands:
                - name: google
                  run: ping -c 5 google.com || true
                  split_output: statistics ---
                  regex_matches:
                    - expression: ([0-9]+\.?[0-9]+)\/([0-9]+\.?[0-9]+)\/([0-9]+\.?[0-9]+)\/([0-9]+\.?[0-9]+)
                      keys: [min, avg, max, stddev]
                      ### there are two different variants for the packet statistics returned, below allows support for both
                    - expression: (\d+) packets transmitted, (\d+) packets received, (\S+)% packet loss
                      keys: [packetsTransmitted, packetsReceived, packetLoss]
                    - expression: (\d+) packets transmitted, (\d+) received, (\d+)% packet loss, time (\d+)
                      keys:
                        [packetsTransmitted, packetsReceived, packetLoss, timeMs]
              custom_attributes:
                url: google.com
            - name: ping
              commands:
                - name: yahoo
                  run: ping -c 5 yahoo.com || true
                  split_output: statistics ---
                  regex_matches:
                    - expression: ([0-9]+\.?[0-9]+)\/([0-9]+\.?[0-9]+)\/([0-9]+\.?[0-9]+)\/([0-9]+\.?[0-9]+)
                      keys: [min, avg, max, stddev]
                      ### there are two different variants for the packet statistics returned, below allows support for both
                    - expression: (\d+) packets transmitted, (\d+) packets received, (\S+)% packet loss
                      keys: [packetsTransmitted, packetsReceived, packetLoss]
                    - expression: (\d+) packets transmitted, (\d+) received, (\d+)% packet loss, time (\d+)
                      keys:
                        [packetsTransmitted, packetsReceived, packetLoss, timeMs]
              custom_attributes:
                url: yahoo.com

データを確認する

このサンプルで登録されたデータはpingSampleというテーブルに保存されます。具体的には、Config Map内のapis配下にあるnameに指定した文字列+Sampleというテーブル名で登録されます。2つのコマンドがpingという名前で設定されているので、両方の結果がpingSampleというテーブルに保存される、という仕組みです。GoogleとYahooに対するping結果が重複なく登録されていることがわかります。

GoogleとYahooに対するping結果が重複なく登録されている。

まとめ

いかがでしたか?nri-flexは、とても柔軟にCustom Eventsを登録できる仕組みですが、Kubernetes特有の仕組みがあるが故に個別の考慮が必要になるケースもあります。本PostがKubernetes運用のさらなる効率化に向けた参考になれば幸いです。