mackerel-container-agentにおけるプラグイン導入方法のご紹介

Mackerelでは、物理・仮想環境ではmackerel-agentを、コンテナ環境ではmackerel-container-agentを使用してメトリックを取得します。

この記事ではコンテナ環境、主にAmazon ECSにおいてmackerel-container-agentを使用する上でプラグインをどのように導入・設定するか、その方法をご紹介します。

mackerel-container-agentとは

mackerel-container-agentはAmazon ECSやKubernetesなど、コンテナオーケストレーションプラットフォームにおけるコンテナの監視をするためのソフトウェアで、タスク・Podのサイドカーコンテナ(主となるコンテナを補助する役割を持つコンテナ)として導入します。

詳しい導入方法はヘルプをご参照ください。

mackerel-container-agent

mackerel-container-agentはデフォルトではタスク・PodのCPU使用量、メモリ使用量、ネットワーク通信量のメトリックを取得します。 これに追加してアプリケーション固有のメトリックを取得するにはプラグインを使用する必要があります。

コンテナ環境特有の注意

物理・仮想環境では、構成管理ツールやSSHを通してマシン環境に直接プラグインをインストールして使用します。 ですがコンテナ環境は物理・仮想環境とは下記のような点が異なり、直接プラグインをインストールすることは推奨されません。

  • コンテナ環境は物理・仮想環境に比べてライフサイクルが短く、頻繁に再作成される。そのため動作中のコンテナへ直接ファイルを追加せず、コンテナイメージや共有ボリュームに追加する。
  • コンテナ同士はプロセスを共有しない。そのため共有ボリュームもしくはネットワーク経由でデータをやりとりする必要がある。
  • コンテナ内のデータや共有ボリュームは永続化されない。永続化が必要な場合は外部ストレージやサービスと連携する。

mackerel-container-agentでプラグインを使用する

mackerel-container-agentは標準的なプラグイン同梱版のDockerイメージも提供しています。同梱版はイメージのタグがv0.9.0-plugins*1またはpluginsとなっており、それぞれv0.9.0latestに対してプラグインを同梱したものとなります。

docker run mackerel/mackerel-container-agent:v0.9.0-plugins

具体的な同梱されたプラグインはコンテナを監視する/プラグインの利用で確認できます。利用したいプラグインが同梱版に入っているなら、こちらを使うことをおすすめします。

プラグイン同梱イメージを利用する

利用したいプラグインが同梱されていた場合でも、何も設定していなければ実行されません。プラグインを実行するための設定をmackerel-container-agentに与える必要があります。 構成は下図のようになります。

プラグイン同梱イメージの利用

以下はmackerel-container-agentのプラグイン同梱版に含まれるmackerel-plugin-gostatsを使う手順です。 その他のプラグインも同様の手順で実行できるようになります。

プラグインがメトリックを取得できるようにアプリケーションを実装する

mackerel-plugin-gostatsを利用するには、アプリケーションにgostatsの情報を出力するエンドポイントを実装する必要があります。以下はその実装例です。

import (
    "net/http"

    "github.com/fukata/golang-stats-api-handler"
)

func main() {
    http.HandleFunc("/api/stats", stats_api.Handler)
    http.ListenAndServe(":8080", nil)
}

プラグインを設定する

mackerel-agentと異なり、mackerel-container-agentの設定はYAMLで記述することになります。具体的には以下の通りです。

plugin:
  metrics:
    gostats:
      command: mackerel-plugin-gostats -host=localhost -port=8080 -path=/api/stats

プラグイン自体はmackerel-agentのものと同等となるため、各オプションの説明は省略します。設定ファイルで利用できるパラメータはコンテナを監視する/利用可能なプラグイン設定を参照ください。

ECSタスクやKubernetes Podにおいて、一般的にはコンテナ同士はネットワークインターフェースを共有します。そのためmackerel-container-agentからアプリケーションコンテナへはlocalhostを指定してネットワークアクセス可能となります。

設定ファイルを与える方法

上記で書いた設定ファイルは、環境変数MACKEREL_AGENT_CONFIGでmackerel-container-agentへ渡します。Amazon S3, HTTP, HTTPSまたはファイルパスのいずれかを利用できます。

例えば、S3を利用する場合は、MACKEREL_AGENT_CONFIG=s3://bucket/mackerel/conf/mackerel.yamlを設定します。Kubernetesの場合はConfigMapに設定ファイルを入れておき、コンテナ側からボリュームマウントしてMACKEREL_AGENT_CONFIG=file://path/to/mackerel.yamlを設定します。

どの方法でも動作しますが、この記事ではECSにおいてプラグインをどのように導入・設定するかを扱っているため、S3経由で渡す方法を選択します。

S3から設定ファイルを与える例

設定ファイルの配布手段が決まったら、実際に設定を与えましょう。まずは上記で作成したプラグインの設定をS3にアップロードします。

aws s3 cp mackerel.yaml s3://bucket/mackerel/conf/mackerel.yaml

次に、ECSのタスク定義でMACKEREL_AGENT_CONFIG環境変数に上記のバケットURLを設定します。

MACKEREL_AGENT_CONFIG_POLLING_DURATION_MINUTESも設定しておくと、指定された時間ごとに設定ファイルを確認して、変更があれば自動で再読み込みできるので便利です。

独自プラグインを使用する

使用したいプラグインが同梱イメージに含まれていない場合は、独自のDockerイメージを作成する必要があります。最近の傾向では、なるべくユーザーに近い値を観測するほうが望ましいとされているので、アプリケーションで計装したメトリックを返すエンドポイントを用意して、プラグインからはそれらの値を取得する形で実装してみましょう。こちらの構成は下図のようになります。

独自プラグインの利用

ここではサンプルなので、実行するたびにランダムで1〜6を返す/diceエンドポイントと、それを取得するだけのプラグインを用意しました。

package main

import (
    "fmt"
    "math/rand"
    "net/http"
    "time"
)

func main() {
    http.HandleFunc("/dice", func(w http.ResponseWriter, r *http.Request) {
        n := rand.Intn(6)
        fmt.Fprintf(w, "custom.sampleapp.dice\t%d\t%d\n", n+1, time.Now().Unix())
    })
    http.ListenAndServe(":8080", nil)
}

以下の内容をmackerel-plugin-diceとして保存します。パーミッションで実行属性を与えておいてください。

#!/bin/sh
exec curl -sf http://localhost:8080/dice

プラグインを含んだDockerイメージを作成する

このdiceプラグインを組み込んだイメージを作成するためのDockerfileを用意します。 このDockerfileではmackerel-container-agent:v0.9.0をベースイメージとするように定義しています。

# syntax=docker/dockerfile:1
FROM mackerel/mackerel-container-agent:v0.9.0
RUN  apt-get update && \
    apt-get install -y --no-install-recommends curl ca-certificates && \
    apt-get clean && \
    rm -rf /var/lib/apt/lists/*
COPY mackerel-plugin-dice /usr/local/bin/mackerel-plugin-dice

イメージをECRにプッシュする

ビルドしたイメージを、ECSのタスク定義から参照可能とするために、イメージをリポジトリにプッシュします。ここではAmazon ECRをプッシュ先のリポジトリとします。

リポジトリを作成するには、次のコマンドを実行します。

aws ecr create-repository --repository-name mackerel-container-agent

リポジトリができたらイメージを作成してプッシュします。

aws ecr get-login-password | docker login --username AWS --password-stdin <YOUR_REGISTRY>
docker build -t <YOUR_REGISTRY>/mackerel-container-agent:v0.9.0-custom .
docker push <YOUR_REGISTRY>/mackerel-container-agent:v0.9.0-custom

設定ファイルを作成する

mackerel-plugin-diceを使用するための設定ファイルを作成します。

plugin:
  metrics:
    dice:
      command: mackerel-plugin-dice

最後に、設定ファイルをS3バケットにコピーします。

aws s3 cp mackerel.yaml s3://bucket/mackerel/conf/mackerel.yaml

作成したイメージと設定でECSにデプロイする

ここまで終わったら、Amazon ECSのタスク定義でmackerel-container-agentのイメージの指定を "<YOUR_REGISTRY>/mackerel-container-agent:v0.9.0-custom" に変更し、環境変数 MACKEREL_AGENT_CONFIGs3://bucket/mackerel/conf/mackerel.yaml を設定してデプロイすれば完了です。

プラグインの動作を確認する

デプロイが終わったらMackerelでタスクが登録されているか確認しましょう。

https://mackerel.io/orgs/<YOUR_ORG>/hosts

タスク定義に環境変数MACKEREL_ROLESを設定することで、個々のタスクをMackerelのロールとしてグループ化できます。グループ化したタスクはロール一覧画面で確認できます。ぜひご活用ください。

https://mackerel.io/orgs/<YOUR_ORG>/services/<SERVICE>#role=<ROLE>

うまく動いていない場合には

Mackerelにタスクが登録されない、メトリックが投稿されないなどうまく動いていない場合には、ECSサービスのイベントログやmackerel-container-agentやアプリケーションコンテナのログをご確認ください。

ログを確認しても原因の判明や解決に至らない場合は、サポートチームへ連絡からお問い合わせください。

まとめ

この記事では、コンテナ環境におけるプラグインの利用方法を紹介しました。公式ではよく利用されるプラグインを同梱したイメージを提供していますが、独自のプラグインが必要な場合は、各自でプラグインを同梱したイメージを管理していただく必要があります。

コンテナ環境でも、物理・仮想環境におけるmackerel-agentと同様に、ここで紹介したような方法で追加のメトリックを取得してMackerelで監視させることができます。ぜひご活用ください。

*1:新しいバージョンがリリースされている場合は新しいものの利用を推奨します