はじめに
みんなのマーケットでSREチームに所属しています、千代田です。
今回は、弊社で導入している、Prometheusを用いたSupervisor上のプロセス監視について紹介します。
また、最後の方にSREチームとしての今後の課題について書きました。
Supervisorとは
Supervisor: A Process Control System
Supervisor is a client/server system that allows its users to monitor and
control a number of processes on UNIX-like operating systems.
くらしのマーケットでは複数のPythonアプリケーションをWSGIアプリケーションとして動かしており、
アプリケーションを実行するためのアプリケーションサーバとしてuWSGIを利用しています。
さらにブランチ別での環境構築システムや弊社独自のブルーグリーンデプロイを実現するために、
uWSGIプロセスの管理としてSupervisorを使用しています。
今回の監視を導入するに至った経緯
過去にSupervisor上のプロセスがfailしたことに気がつかず、翌日に発覚するといったことがありました。
その為、Supervisor上のプロセスの状態について検知するしくみが必要だと判断し、今回の監視を導入しました。
構成
監視はPrometheusとnode_exporterで行っています。
アラート通知はAlertmanager経由でSlackにPOSTしています。

導入
Supervisorの動いているサーバを用意します(導入済みを前提としている為、割愛します)。
監視対象のサーバに最新のnode_exporterを導入します
もしDockerをすでに運用されている場合には、
サーバに直接的なオペレーションを行うよりも、コンテナのnode_exporterを使用することを推奨します。
wget https://github.com/prometheus/node_exporter/releases/download/v0.15.2/node_exporter-0.15.2.linux-amd64.tar.gz tar xvzf node_exporter-0.15.2.linux-amd64.tar.gz cd node_exporter-0.15.2.linux-amd64 mv node_exporter /usr/local/bin/node_exporter
Supervisordのコンフィグを設定します
inet_http_serverを設定する必要がある為、コンフィグに追記します。
[inet_http_server] port = 127.0.0.1:30002
設定後はSupervisordを再起動する必要があります。
node_exporterを起動します
node_exporterはデフォルトでポート9100を使用する為、必要に応じてポートを変更します。
sudo /usr/local/bin/node_exporter --web.listen-address=:30001 --collector.supervisord --collector.supervisord.url=http://localhost:30002/RPC2
以上で、監視対象のサーバの設定は終わりです。
Prometheusで確認してみます
監視側のサーバにPrometheusを導入/設定する部分については割愛します。
Prometheusのコンソールにて、Expressionにnode_supervisord_upを入力して実行します。

Valueについてですが、1が起動している状態で、0が起動していない状態になります。
また、より詳細な判定を行いたい場合は、node_supervisord_stateを使用してください。
こちらのValueについては公式の説明を見た方がわかりやすい為、リンクのみとさせていただきます。
Prometheusのコンフィグを設定します
今回はAWS上で実行している為、ec2_sd_configsを使用しています。
必要に応じて変更してください。
global:
scrape_interval: 15s
evaluation_interval: 15s
rule_files:
- '/etc/prometheus/alert.rules'
scrape_configs:
- job_name: 'node'
ec2_sd_configs:
- region: ap-northeast-1
port: 30001
- source_labels: [__meta_ec2_tag_Name]
target_label: name
alerting:
alertmanagers:
- scheme: http
static_configs:
- targets: ['AlermanagerのIP:9093']
Prometheusにアラートを追加します
下の例は、example_processがFORで指定した時間の間、停止していた場合にアラートを上げます。
また、ANNOTATIONSの中でアラート時に送信する内容を設定しています。
今回の場合は、$labels.nameでホスト名を、$valueでアラートが上がった際の値を取得しています。
ALERT ExampleProcessRunning
IF node_supervisord_up{job='node',group="example_process",exported_name="example_process"} == 0
FOR 5m
LABELS { serverity = "warning" }
ANNOTATIONS {
firing_text = "Name: {{ $labels.name }}\n Value: {{ $value }}"
}
AlertManagerで通知を行うようにします
今回は、Slackに通知を行います。
api_urlにはWebhookのendpointを設定してください。
global:
route:
receiver: 'slack'
group_by: ['name', 'alertname', 'severity']
group_wait: 30s
group_interval: 5m
repeat_interval: 24h
receivers:
- name: 'slack'
slack_configs:
- api_url: 'https://hooks.slack.com/services/END_POINT'
channel: '#channel'
title: '[PROBLEM] {{ .GroupLabels.alertname }}'
text: '{{ .CommonAnnotations.firing_text }}'
実際にアラートを送信します
supervisorctlでアプリケーションを停止させ、5分ほど待つとアラートが飛んできます。
supervisorctl stop example_process

以上で簡易的にですが、アラートを送ることができました!
必要に応じてsend_resolvedなどのパラメータを用いれば、改善したことを通知するアラート等を流すこともできます!
SREチームとしての課題
現在、くらしのマーケットでは各サーバで動いているアプリケーションをDockerへ移行していく為の準備を進めています。
その為、AWS ECS/EKS(サービス前ですが)などを用いての運用/監視の体制を作っていかなければいけません。
しかしながらDockerに関しての知見がまだまだ浅い為、こういった新しいものへの挑戦/解決方法が今後の課題となりそうです。
最後までお読みいただき、ありがとうございました!
また、一緒に働いてみたいといった方もぜひお待ちしてます!
次回は、Webエンジニアによる、TypeScriptの紹介記事です。