AWS: мониторинг Simple Email Service с CloudWatch и Prometheus

Автор: | 06/10/2021
 

Случилась у нас бяда – AWS отключил нам отправку писем через AWS SES из-за bounce-рейта.

Проверить это можно в AWS SES > Reputation Dashboard, аккаунт сейчас в статусе Under review:

AWS: мониторинг Simple Email Service с CloudWatch и Prometheus

После обращения в тех. поддержку отправку почты нам временно включили, но решить проблему надо, а заодно – следить, что бы подобное не случалось в будущем.

Bounce и Complaint rate

Запретить отправку почты AWS может по двум причинам – завышенный Bounce rate и завышенный Complaint rate. В случае высокого рейтинга – почтовые сервера могут помечать сервер отправки как “спамера”, и блокировать приходящие с него письма вообще, что, разумеется, негативно сказывается на AWS SES, а потому они достаточно активно следят за этими показателями и могут (и отключают) отправку с этого SES-аккаунта.

Кратко рассмотрим, что такое Bounce и Compliant рейтинги, а потом настроим мониторинг с CloudWatch и Prometheus, что бы в Slack получать уведомления о превышении пороговых значений – 5% bounce, и свыше 1% compliant rates.

Общие советы по уменьшению Bounce rate можно найти в What can I do to minimize bounces?

Bounce rate

Bounce rate определяет, какая часть получателей не получила отправленного письма, см. Bounce Rate.

Считается как (кол-во bounced / кол-во отправленных всего) * 100, например:

>>> (10.0/10000)*100
0.1

Тут получаем 0.1% – отличный результат, если бы был реальным 🙂

Hard and Soft Bounce

При этом различают два типа bounce – hard и soft.

  • Hard bounce: при “жёстком” отказе – сервер получателя отказывается принимать письмо вообще. Обычно это возникает из-за ошибок типа отсутствия ящика получателя на сервере, домена, в который отправляется письмо, или если сервер вообще отказывается получать какие-либо письма
  • Soft bounce: сюда входят письма, которые сервер получателя принял и передал в пользовательский почтовый ящик, но не смог его доставить туда из-за, например, превышения ящиком дисковой квоты или размера письма

Complaint rate

Complaint rate считается, когда пользователь явно уведомляет, что он не хочет получать письма, например через кнопку “Report spam” в своём почтовом клиенте, или отправив жалобу напрямую AWS SES.

AWS SES CloudWatch metrics

Для алертинга используем метрики CloudWatch для AWS SES:

  • Sends: общее количество отправленных писем
  • Deliveries: общее количество доставленных писем
  • Bounces: сервер получателя отказался доставлять письмо в ящик (считаются hard bounces)
  • Complaints: письмо было доставлено получателю, но он отметил его как спам

Плюс дополнительно уже посчитаны значения для Bounce и Complaint – Reputation.BounceRate и Reputation.ComplaintRate.

Сейчас наше значение для Reputation.BounceRate == 0.1432, т.е. 14%:

AWS: мониторинг Simple Email Service с CloudWatch и Prometheus

(в конце этого поста рейтинг будет уже 18% – за сутки набрали ещё 4%)

Можно создать алерты используя сам AWS CloudWatch Alerts и SNS, см. Creating reputation monitoring alarms using CloudWatch, либо собирать метрики во внешнюю систему мониторинга, и слать алерты через неё.

В нашем случае, будем собирать в Prometheus, который через свой Alertmanager будет слать алерты в Opsgenie, а из него уже – нам в Slack.

Настройка Prometheus CloudWatch Exporter

Вообещ, мы используем yet-another-cloudwatch-exporter, но в случае с метриками для AWS SES он выводил полную ерунду, в Guthub Issues на вопросы отвечают редко, да и вообще он производит впечатление заброшенного проекта, хотя апдейты периодически выкатывают.

Поэтому для SES отдельно используем стандартный експортер, см. Prometheus: CloudWatch exporter — сбор метрик из AWS и графики в Grafana.

Его конфиг:

region: us-east-1
set_timestamp: false
delay_seconds: 60

metrics:

 - aws_namespace: AWS/SES
   aws_metric_name: Send

 - aws_namespace: AWS/SES
   aws_metric_name: Delivery

 - aws_namespace: AWS/SES
   aws_metric_name: Bounce

 - aws_namespace: AWS/SES
   aws_metric_name: Complaint

 - aws_namespace: AWS/SES
   aws_metric_name: Reputation.BounceRate

 - aws_namespace: AWS/SES
   aws_metric_name: Reputation.ComplaintRate

Для проверки метрик можно запустить скрипт из поста AWS: SES — Simple Email Service и WorkMail: настройка аккаунта и отправка почты, который раз в 10 секунд отправляет письмо:

watch -n 10 ./ses_email.py

Добавим графики в Grafana:

AWS: мониторинг Simple Email Service с CloudWatch и Prometheus

Сравним их с метриками в самом CloudWatch, что бы убедиться, что всё считается верно:

AWS: мониторинг Simple Email Service с CloudWatch и Prometheus

И осталось добавить алерт.

Prometheus alert

Но тут возникает проблема.

Из графика видно, что Bounce Rate выводится неравномерно:

AWS: мониторинг Simple Email Service с CloudWatch и Prometheus

Примерно раз в 20 минут запускается наша рассылка (5-6 отправок в минуту на графике – это тестовые, создаваемые запущенным выше скриптом), и сразу же появляются значения для метрики aws_ses_reputation_bounce_rate_sum.

Если использовать самый простой алерт типа:

- alert: AWSSESReputationBounceRate
  expr: aws_ses_reputation_bounce_rate_sum{job="aws_ses"} * 100 > 5
  for: 1s
  labels:
    severity: warning
  annotations:
    summary: 'AWS SES Bounce rate too high'
    description: 'Latest observed value: {{ $value | humanize }} %'
    tags: aws

То он будет активироваться и закрываться раз в те же 20 минут.

Что можно сделать?

Как вариант – использовать avg_over_time(), и делать выборку по данным за последние, например, 10 минут – тогда получим ровный график:

AWS: мониторинг Simple Email Service с CloudWatch и Prometheus

Обновляем алерт (тут задал 1 час):

- alert: AWSSESReputationBounceRate
  expr: avg_over_time(aws_ses_reputation_bounce_rate_sum{job="aws_ses"}[1h]) * 100 > 5
  for: 1s
  labels:
    severity: warning
  annotations:
    summary: 'AWS SES Bounce rate too high'
    description: 'Latest observed value: {{ $value | humanize }} %'
    tags: aws

И получаем алерт в Slack:

AWS: мониторинг Simple Email Service с CloudWatch и Prometheus

Готово.