SupervisorのWorkerプロセスが落ちた時にした対処法
概要
Laravel / PHP のジョブキューを Supervisor で常駐させている構成で、queue‑worker プロセスが死んでいたのでその時の対処法をまとめたメモです。
- 監視 : CloudWatch Logs → Metric Filter → Alarm
- 通知 : AWS Chatbot → Slack
- メンション : 必要なら SNS → Lambda → Slack Webhook
1. 全体構成
Supervisor (queue-worker) ─▶ CloudWatch Logs
│
▼
Metric Filter ───▶ CloudWatch Alarm ───▶ SNS ───▶ AWS Chatbot ──▶ Slack #alarms
│
└──▶ Lambda ─▶ Slack Webhook (メンション)
- 通常通知 は Chatbot で十分。
- メンション付き を投げたいときだけ Lambda を噛ませる。
- どちらのルートも SNS に Pub/Sub しているので運用は一元化。
2. 前提:Supervisor のログを CloudWatch に流す
; /etc/supervisor/conf.d/queue-worker.ini
[program:queue-worker]
command=php artisan queue:work --sleep=3 --tries=3 --timeout=90
stdout_logfile=/var/log/supervisor/queue-worker.log
stderr_logfile=/var/log/supervisor/queue-worker-error.log
autorestart=true
startretries=5 ; 再起動試行回数を 3 → 5 へ
# /etc/awslogs/awslogs.conf
[queue-worker]
log_group_name = /app/queue-worker
log_stream_name = {instance_id}
file = /var/log/supervisor/queue-worker-error.log
- startretriesを増やして再起動の回数を増やした。
3. Metric Filter
項目 | 設定例 |
---|---|
Log group | /app/queue-worker |
Filter pattern | ?FATAL |
Metric value | 1 |
Namespace | QueueWorker |
Metric name | WorkerFatal |
- 今回は FATAL のみ検知してメトリクス化。
- 単発エラーを無視したければ、次のアラーム側で データポイント 2 / 5 分 などとする。
4. CloudWatch Alarm
resource "aws_cloudwatch_metric_alarm" "queue_worker_fatal" {
alarm_name = "queue-worker-fatal"
comparison_operator = "GreaterThanOrEqualToThreshold"
evaluation_periods = 1
metric_name = aws_cloudwatch_log_metric_filter.queue_worker.metric_transformation[0].name
namespace = aws_cloudwatch_log_metric_filter.queue_worker.metric_transformation[0].namespace
period = 60 # 1 分間
statistic = "Sum"
threshold = 1
alarm_actions = [aws_sns_topic.queue_worker_alert.arn]
}
5. AWS Chatbot で Slack 通知
- Chatbot コンソール → Slack ワークスペースを連携。
- 通知したいチャンネル
#alarms
を選択。 - SNS トピック
queue_worker_alert
をサブスクライブ。
通知イメージ
[ALARM] "queue-worker-fatal" in ap-northeast-1
Timestamp: 2025-07-14T01:12:00Z
Reason: Threshold Crossed: 1 datapoint [...] >= 1.
6. Slack で @here / @user を付けたい場合
Chatbot はチャンネル投稿のみ。メンションを付ける なら Lambda を追加します。
6‑1. SNS → Lambda の配線
resource "aws_lambda_function" "slack_mention" {
function_name = "queue_worker_slack_mention"
runtime = "python3.12"
handler = "main.lambda_handler"
role = aws_iam_role.lambda_slack.arn
filename = "lambda.zip" # 後述
timeout = 10
}
resource "aws_sns_topic_subscription" "lambda_sub" {
topic_arn = aws_sns_topic.queue_worker_alert.arn
protocol = "lambda"
endpoint = aws_lambda_function.slack_mention.arn
}
6‑2. Lambda (Python) サンプル
import json, os, urllib.request
SLACK_WEBHOOK = os.environ["SLACK_WEBHOOK"] # SSM から参照推奨
MENTION = os.environ.get("MENTION", "@here")
TEMPLATE = (
f"{MENTION} :queue: *{{alarm_name}}* が DEAD です\n"
"*Reason* : {reason}\n"
"*Link* : {link}"
)
def lambda_handler(event, _):
message = json.loads(event["Records"][0]["Sns"]["Message"])
text = TEMPLATE.format(
alarm_name=message["AlarmName"],
reason=message["NewStateReason"],
link=message["AlarmUrl"],
)
payload = json.dumps({"text": text}).encode()
req = urllib.request.Request(SLACK_WEBHOOK, data=payload)
urllib.request.urlopen(req)
return {"status": "ok"}
7. まとめ & 運用 Tips
観点 | チェックリスト |
---|---|
再起動の可否 | Supervisor の autorestart を true に+ちゃんと落ちるログを吐くか? |
アラーム抑止 | メンテ時間は Composite Alarm or EventBridge Scheduler で無効化すると便利 |
大規模運用 | 複数ワーカーなら Dimensions = { Service="queue" } で集約メトリクスにする |
Redis / Supervisor は 再接続まわりで落ちやすい ので、早めの自動検知ルートを整えておくと安心です。テストでは kill -9
でプロセスを殺してアラームが来るか確認してみてください。