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

Thank you for reading this post, don't forget to subscribe!

AWS отклю­чил нам отправ­ку писем через AWS SES из-за bounce-рейта.

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

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

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, например:

Тут полу­ча­ем 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%:

(в кон­це это­го поста рей­тинг будет уже 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.

Его кон­фиг:

Для про­вер­ки мет­рик мож­но запу­стить скрипт

кото­рый раз в 10 секунд отправ­ля­ет письмо:

watch -n 10 ./ses_email.py

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

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

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

Prometheus alert

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

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

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

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

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

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

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

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

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

гото­во