こんにちは。
勉強も兼ねて個人サーバを運用してるんですが、何かあったときってアラート
とかログをとりあえず見てなんか起こってるぽいと感じることが多々あります。
ただ、調べだすとなんだかんだ半日過ぎてたりして好きではあるんですけど、
ログをgrepしたりsedしたりでデータを抜き出すのに手間がかかってるし、
なんならログしか見られないからほぼほぼログから推測するしかなかったりで結構な手間です。
たまたま会社の先輩からイベントもやってるよということでNew Relicを教えてもらい、名前は聞いたことあったのですが触れる機会を作れていなかったし、データ収集してあれこれできるといっぱい夢を吹き込まれた(誇張)ので触ってみることにしました。
【New Relicってなんやねん】
数多くの監視ツールの一つですが、その中でもオブザーバビリティの実現に必要な機能を多数備えたツールです。
これまでの一般的な監視に用いられたリソース情報やログだけでなく処理のトレース情報などを組み合わせてどこで何が なぜ起こったのかを可視化していくことで、監視データや監視結果を組み合わせて発生している事象やトラブルを個人のナレッジや経験で突き止めていたことをシステム的に可視化できるツールだと思います。
最近触り始めたような人間の説明より公式さんでオブザーバビリティとNew Relicで何ができるかを説明しているのでぜひご覧ください。
【やってみたこと】
本当はいろいろできるNew Relicですが、いきなり全部やってみようとかはハードルが高いので、まずは個人のサーバにNew Relicを導入して触ってみることにして、個人的に現状の個人サーバで毎回コマンド使って出していたデータ出力や今後異常検知なんかもやってみたいので通知機能を試してみることにしました
- New Relicアカウントの作成とAgentインストール
- Postfixのデータ取得をやってみた
- 監視アラートをWebhookでDiscordに飛ばしてみる
【サーバ環境】
個人で借りているさくらのVPSサーバです。主な環境やスペックは下記の通り。
- プラン:さくらのVPS 1Gプラン(CPU 2vCPU,メモリ 1GB)
- OS:AlmaLinux9
- 主な用途:メールサーバ(postfix)
【New Relicアカウントの作成とAgentインストール】
1.New Relicのアカウント作成
利用にはNew Relicのアカウントが必要です。
登録にクレジットカードは不要で、メールアドレスなどの必要情報を登録することで提供されている機能のほとんどを利用することができる上に月間100GBまでのデータ量なら無料で利用できます。
仮にデータ量をオーバーしてもいきなり課金ってこともないのでとりあえずお試し勢も安心です。
月100GBって?
この記事で使っているサーバ1台が半月で7GB程度、1日あたり0.3GB程度です。
実際のデータ量は動作アプリケーションや取得データに依存し、このデータにはリソースメトリクスのデータも含みます。
業務で使うサーバでも数台は見ることができるのではないかと思います。
アカウント登録はこちらからどうぞ
2.Agentのインストール
New Relicアカウントの作成が終わったのでAgentを導入します。
今回はサーバのリソースとログを取得できるようにしたいので、ファーストステップガイドInfrastructure導入という公式資料を参考にインストールを進めます。
これらの基本的な導入資料は公式でまとめられたページがありますので、ここから目的のデータを探すのもいいですし、New Relicのコンソールにログインすると取得できるデータごとに一覧が用意され、各コンポーネントごとに導入をガイドしてくれますので、基本的なインストールは割と簡単です。
New Relic InfrastructureはAgentを通じてOS情報や稼働状態を取得します。
- 左側ガイドから
Integrations & Agents
を選択し、検索画面にLinux
と入力します
-
Linux
を選択すると今回は初めての登録でユーザキーが必要なのでCreate a new key
を選択すると自動でユーザキーが生成されます
- インストール用コマンドが用意されますので
Copy to clipbord
を押せばそのままコンソールへ貼り付けるだけでインストールコマンドが実行可能です
Automatically answer "yes" to~
にチェックを入れると自動でインストールの実行に進むコマンドが生成されます。
- インストール後にNew Relicのコンソール上からAgentのインストール結果を確認できます
ここまで終わると各種メトリクスデータとログデータの収集が開始されます。
ほかのデータやアプリケーションデータが必要な場合はNew Relicコンソールから追加でインストールします。
- OS情報
- リソースモニタリング情報
- messagesログ
- secureログ
こういったAgentは割とAgent側の設定を手動でやる必要のあることが多い印象ですが、基本的な導入だけであればNew Relicコンソール側で実行するだけで終われるのでお手軽でした。
またダッシュボードもあらかじめ用意されたものが多数あるので、メジャーなアプリケーションなら簡単なウィザードでシステムの状態を確認できるようになります。
【Postfixのデータ取得をやってみた】
postfixを使ってメールサーバを動かしているのでpostfixのデータ取得を試してみることに。
postfix用コンポーネントのインストール
postfixの場合、インストールはどうやらマニュアルに沿って行うようなので以下のURLに沿ってインストールを実施
Infrastracture Agentが未インストールの場合はインストールします
1. pflogsummのインストール
インストール手順の1~3まではマニュアル通りで、項番4はログ保存先フォルダが私の環境だと/var/log/maillog
に保存されていたので、そこだけ修正して下記のようにすることでデータが出力されることを確認
cat /var/log/maillog | pflogsumm
cat /var/log/maillog | pflogsumm -d today
2. Flex設定ファイルの作成
サンプルコンフィグがあるのでこちらのログファイル参照だけ/var/log/maillog
に置換してpostfix-flex-config.yml
に保存
3. ログ転送設定を追加
ログ転送ファイルを修正。
こちらはおそらくすでにmessagesやsecureのログ転送設定がされているので、追加でマニュアルに記載のログ転送設定をする。
logs:
- name: messages
file: /var/log/messages
attributes:
logtype: linux_messages
- name: secure
file: /var/log/secure
attributes:
logtype: linux_secure
- name: newrelic-cli.log
file: /root/.newrelic/newrelic-cli.log
attributes:
newrelic-cli: true
logtype: newrelic-cli
- name: mail.log
file: /var/log/maillog
attributes:
logtype: postfix_maillog
4. Agentの再起動
NewRelic Agentサービスを再起動する。
sudo systemctl restart newrelic-infra.service
5. インストール結果確認&New Relicコンソール設定
New RelicコンソールでIntegrations & Agents
->postfix
を選択。
まずインストールを行うように促されますがすでにインストール済みなのでDone
を選択
終わるとダッシュボードやアラートなどが自動でセットアップされますのでこれでセットアップ完了です。
インストールは終わったけどあれ?
インストールは終わってダッシュボードも見えるようになりましたが、2つほど問題が。
-
ダッシュボードのサービスステータスがDownのまま
ダッシュボードにもデータが出てきて おおっ!!! と思ったのもつかの間、サービスのステータスがDownのままです。
-
サービスダウンのアラートが発生
さらに数分後からサーバでpostfixサービスのダウンアラートが!?
修正点
・ ダッシュボード
ダッシュボードの判定式をサービス表示部分のEdit
から見られるので見てみると
こんな感じの式でした。NSQL式をいじってみると、前半のSELECT文にあるUp/Down判定の数字を文字列扱いしていることが悪さをしている模様。
ということで数式を以下のように直してみましたところ
- SELECT latest(if(status='1','Up','Down')) as 'Postfix Service Status' FROM (SELECT latest(value) as 'status' from PostfixUp)
+ SELECT latest(if(status=1,'Up','Down')) as 'Postfix Service Status' FROM (SELECT latest(value) as 'status' from PostfixUp)
・ アラート
ダッシュボードのほうは解消しましたが、アラートは解消しない。
サーバのステータスは問題ないので、導入時に設定したコンフィグを確認しpostfix-flex-config.yml
を見たところ・・・
PostfixUp
とPostfixDown
の取得値が全く同じやないかい!!
ま、サンプルコンフィグですからね~。
とりあえずPostfixDown
のメトリクス取得方法を下記のように変更。
- event_type: PostfixDown
commands:
- - run: echo "value:$(systemctl status postfix | grep 'Active':' active' | wc -l)"
+ - run: echo "value:$(systemctl is-active postfix | grep -v 'active' | wc -l)"
split_by: ':'
これでアラートは解消してめでたし、めでたし。
今回設定したpostfix-flex-config.ymlはこちら
設定したpostfix-flex-config.yml
---
integrations:
- name: nri-flex
config:
name: postfixFlex
apis:
#check if Postfix service is up.
- event_type: PostfixUp
commands:
- run: echo "value:$(systemctl status postfix | grep 'Active':' active' | wc -l)"
split_by: ':'
#check if Postfix service is down.
- event_type: PostfixDown
commands:
- run: echo "value:$(systemctl is-active postfix | grep -v 'active' | wc -l)"
split_by: ':'
#Read the grand totals messages by using the below script.
- event_type: PostfixGrandTotals
commands:
- run: cat /var/log/maillog | pflogsumm | grep -A 21 'Grand Totals'
split: horizontal
set_header: [metricValue, message]
regex_match: true
split_by: \s+(\d+\w*)\s+(.*)
#Read the number of messages delivered & received in bytes.
- event_type: PostfixMessageBytes
commands:
- run: cat /var/log/maillog | pflogsumm | grep -A 1 'bytes received'
split: horizontal
set_header: [metricValue, messageBytes]
regex_match: true
split_by: \s+(\d+\w*)\s+(.*)
#Read the number of messages held by the user.
- event_type: PostfixHeldMessage
commands:
- run: echo "value:$(cat /var/mail/<USER> | grep -c 'Subject:')"
split_by: ':'
#Read the count of SASL authentication failure notifications.
- event_type: PostfixSASLauthFailed
commands:
- run: echo "value:$(cat /var/log/maillog | grep 'status=deferred (SASL authentication failed' | wc -l)"
split_by: ':'
#Read the count of bounced non-delivery notifications.
- event_type: PostfixBounceNondeliveryNotification
commands:
- run: echo "value:$(cat /var/log/maillog | grep 'postfix/bounce' | wc -l)"
split_by: ':'
#Read the number of messages passed through the email delivery process.
- event_type: PostfixEmailDeliveryProcess
commands:
- run: echo "PICKUPvalue:$(cat /var/log/maillog | grep 'pickup' | wc -l)"
split_by: ':'
- run: echo "CLEANUPvalue:$(cat /var/log/maillog | grep 'cleanup' | wc -l)"
split_by: ':'
#Read the number of message inserted in mail queue.
- event_type: PostfixMessageInsertedinMailQ
commands:
- run: echo "Ivalue:$(cat /var/log/maillog | grep 'queue active'| wc -l)"
split_by: ':'
#Read the number of message handled by SMTP process.
- event_type: PostfixMessageHandledBySMTP
commands:
- run: echo "SENTmsg:$(cat /var/log/maillog | grep 'status=sent' | grep "postfix/smtp" | wc -l)"
split_by: ':'
- run: echo "BOUNCEDmsg:$(cat /var/log/maillog | grep 'status=bounced' | grep "postfix/smtp" | wc -l)"
split_by: ':'
- run: echo "DEFERREDmsg:$(cat /var/log/maillog | grep 'status=deferred' | grep "postfix/smtp" | wc -l)"
split_by: ':'
#Read the number of message removed from mail queue.
- event_type: PostfixMessageRemovedFromMailQ
commands:
- run: echo "Rvalue:$(cat /var/log/maillog | grep 'removed'| wc -l)"
split_by: ':'
#Read the number of SMTPD connection.
- event_type: PostfixSMTPDconnection
commands:
- run: echo "value:$(cat /var/log/maillog | grep ' connect from' | wc -l)"
split_by: ':'
#Read the number of SMTPD disconnection.
- event_type: PostfixSMTPDdisconnection
commands:
- run: echo "value:$(cat /var/log/maillog | grep 'disconnect from' | wc -l)"
split_by: ':'
#Read the number of SMTP connection.
- event_type: PostfixSMTPconnection
commands:
- run: echo "value:$(cat /var/log/maillog | grep ' connect to' | wc -l)"
split_by: ':'
#Read the number of SMTP disconnection.
- event_type: PostfixSMTPdisconnection
commands:
- run: echo "value:$(cat /var/log/maillog | grep 'disconnect to' | wc -l)"
split_by: ':'
#Read the number of connection timed out.
- event_type: PostfixSMTPDtimedOut
commands:
- run: echo "value:$(cat /var/log/maillog | grep 'timeout after CONNECT' | wc -l)"
split_by: ':'
#Read the number of connection lost.
- event_type: PostfixSMTPDconnectionLost
commands:
- run: echo "value:$(cat /var/log/maillog | grep 'lost connection' | wc -l)"
split_by: ':'
#Read the per-hour traffic report.
- event_type: PostfixMessagePerHourReport
commands:
- run: cat /var/log/maillog | pflogsumm -d today | grep -i 'Per-Hour Traffic Summary' -A 27
split: horizontal
header_split_by: \s+(\w+)\s+(\w+)\s+(\w+)\s+(\w+)\s+(\w+)\s+(.*)
set_header:
[
time,
received.perhour,
delivered.perhour,
deferred.perhour,
bounced.perhour,
rejected.perhour,
]
regex_match: true
split_by: \s+(\d+-\d+)\s+(\d+)\s+(\d+)\s+(\d+)\s+(\d+)\s+(\d+)
#Read the per-day traffic summary.
- event_type: PostfixMessageTrafficPerDay
commands:
- run: cat /var/log/maillog | pflogsumm --zero_fill | grep -C 12 'Per-Day Traffic Summary' -B 0 -A 8 | sed '/Per-Hour Traffic Daily Average/q'
split: horizontal
header_split_by: \s+(\w+)\s+(\w+)\s+(\w+)\s+(\w+)\s+(\w+)\s+(.*)
set_header:
[date, received, delivered, deferred, bounced, rejected]
regex_match: true
split_by: \s+(\w+\s+\d+\s+\d+)\s+(\d+)\s+(\d+)\s+(\d+)\s+(\d+)\s+(\d+)
#Read the host/domain summary: message delivery & received.
- event_type: PostfixHostSummary
commands:
- run: cat /var/log/maillog | pflogsumm | grep -i 'Host/Domain Summary':' Message Delivery' -A 8 | sed -n '2,9p'
split: horizontal
header_split_by: \s+(\w+\s+\w+)\s+(\w+)\s+(\w+)\s+(\w+\s+\w+)\s+(\w+\s+\w+)\s+(.*.)
set_header:
[sentCount, bytesDelivered, defers, avgDaily, maxDaily, host]
regex_match: true
split_by: \s+(\d+)\s+(\d+\w*)\s+(\d+)\s+(\d+.\d+\s+\w)\s+(\d+.\d+\s+\w)\s+(.*)
- run: cat /var/log/maillog | pflogsumm | grep -A 15 'Host/Domain Summary':' Messages Received' | sed '/Senders by message count/q'
split: horizontal
header_split_by: \s+(\w+\s+\w+)\s+(\w+)\s+(.*.)
set_header: [msgCount, bytesReceived, hostDetail]
regex_match: true
split_by: \s+(\d+)\s+(\d+\w*)\s+(.*)
#Read the senders & recipients with message count.
- event_type: PostfixSenderRecipientMessageCount
commands:
- run: cat /var/log/maillog | pflogsumm | grep -C 11 'Senders by message count' -B 1 -A 9 | sed '/Recipients by message count/q'
split: horizontal
header_split_by: (.*.)
set_header: [sender.msgCount, senders]
regex_match: true
split_by: \s+(\d+)\s+(.*)
- run: cat /var/log/maillog | pflogsumm | grep -C 11 'Recipients by message count' -B 1 -A 9 | sed '/Senders by message size/q'
split: horizontal
header_split_by: (.*.)
set_header: [recipient.msgCount, recipients]
regex_match: true
split_by: \s+(\d+)\s+(.*)
#Read the daemon message details.
- event_type: PostfixDaemonMessage
commands:
- run: cat /var/log/maillog | pflogsumm | grep -A 10 'Master daemon messages'
split: horizontal
set_header: [daemon.msgCount, daemonMessage]
regex_match: true
split_by: \s*(\d+)\s+(\w+.*.)
#Read the message deferral details.
- event_type: PostfixDeferralMessage
commands:
- run: cat /var/log/maillog | pflogsumm | grep -A 15 'message deferral detail' | sed '/message bounce detail (by relay)/q'
split: horizontal
header_split_by: (\s+\w+\s+.*)
set_header: [deferral.msgCount, deferralMessage]
regex_match: true
split_by: \s*(\d+)\s+(\w+.*.)
#Read the warning message details.
- event_type: PostfixWarningMessage
commands:
- run: cat /var/log/maillog | pflogsumm | grep -v 'mail_queue_enter' | grep -C 100 'Warnings' -B 1 -A 10 | sed '/Fatal Errors/q'
split: horizontal
header_split_by: \s+(\w+)\s+(.*)
set_header: [Warning.msgCount, warningMessage]
regex_match: true
split_by: \s*(\d+)\s\s\s(.*.)
#Read the error message details.
- event_type: PostfixErrorMessage
commands:
- run: cat /var/log/maillog | pflogsumm | grep -C 15 'Fatal Errors' -B 1 -A 10 | sed '/Panics/q'
split: horizontal
header_split_by: \s+(\w+)\s+(.*)
set_header: [Fatal.msgCount, fatalMessage]
regex_match: true
split_by: \s*(\d+)\s\s\s(.*.)
#Read the message bounce details.
- event_type: PostfixBounceMessage
commands:
- run: cat /var/log/maillog | pflogsumm | grep -A 10 'message bounce detail (by relay)' | sed '/message reject detail/q'
split: horizontal
header_split_by: \s+(\w+)\s+(.*)
set_header: [Bounce.msgCount, bounceMessage]
regex_match: true
split_by: \s*(\d+)\s\s\s(.*.)
【監視アラートをWebhookでDiscordに飛ばしてみる】
無事に監視できるようになったのでやはりアラートを飛ばせないとということで、メールでもいいんですが、そもそもそのメールの受信先はこのサーバだったりしますし、携帯メアドでもいいのですが、味気ないのでWebhook使って携帯で通知されるようにしてみましょう。
Teamsではありませんが、設定はこちらを参考にさせていただきました。
Discord(Webhook送信先設定)
自分のサーバ上に新たなチャンネルを作ってWebhookの受信設定をします。
本筋じゃないので割愛しますが、チャンネルの設定で連携サービスを設定すればウェブフックURLが取得可能になります。
New Relic側の設定
-
Alerts
->Destination
の順で移動したらAdd a destination
からWebhook
を選択します。
- 任意の名前と先ほど取得したウェブフックURLを入力して
Save destination
を押します
問題なく登録できれば一覧に表示されます。
-
Alerts
->Workflows
->Create your first workflow
の順で選択
- ワークフロー名とアラートのフィルタ条件を指定し、通知方法として
Webhook
を選択
- チャンネル名(任意)を入力後、Destinationから先ほど設定した通知先名を選択
- 送信メッセージテンプレートをペイロードとして設定が可能なので、送信先(今回はDiscord)の仕様に合わせて下記のように変更する
変更後、Send test notification
を押すとテストメッセージが送信できるDiscord側で受信したテストメッセージ{ "flag": 4, "content": "問題が発生しました。\n {{escape annotations.title.[0] }}" }
-
Save message
を押す
ここまで設定すると以下のアラートはすでに飛ぶようになっています。
アラート設定はAlerts
->Alert policies
で見ることができます。
- Golden Signals
- Postfix alert policy
HostCheckerは投稿者がカスタムで作成したものです。
【まとめ】
全体としてあまり作りこみをしなくてもかなりサーバの稼働状態が見やすくなったと感じた。
今回は触れなかったがログのパースなどもプレビューを見ながらできるなどまだあまり触っていない私でも気軽にできたので、入り口のとっつきやすさと得られる結果の大きさはただただ感動であった。
APMなど他のコンポーネントとの連動に関しては見られない環境なので機会をみて試してみたいと思っている。
- インストールはお手軽で基本機能だけでもリソースやログを取得し整理してくれるので大変便利
- メジャーなアプリであればこちらも簡単な操作で必要データを取得し整理までしてくれる
- メジャーなアプリであればダッシュボードテンプレートも豊富でお手軽にデータが俯瞰できるようになり、どこでどういった動きをしているかも見やすい
- postfixはインストールで少し躓いたけど、これまで日次のテキストレポートでしか見られなかった稼働状態をリアルタイムかつグラフィカルに俯瞰できるようになった上、状態把握がすごくしやすいと感じた