Архитектура масштабируемой почтовой системы

от автора

В этой статье мы рассматриваем один из вариантов реализации масштабируемой архитектуры большой почтовой системы.

6 декабря 2012 г. Google прекратил регистрацию новых аккаунтов для бесплатной версии Google Apps.

У клиентов нашей компании постоянно возникает потребность в электронной почте, обслуживающей их сайты.
Раньше мы настраивали им Google Apps, но после 6 декабря, изучив предлагаемые на рынке решения, решили, что настала пора строить собственную почтовую систему.

Как известно, аппетит приходит во время еды. Если уж решились строить что-то свое, то тогда стоит сразу закладывать возможности для роста.
Для проектируемой почтовой системы были сформулировали следующие требования:

  • масштабируемость (неограниченное количество обслуживаемых доменов, общий объем почтовых ящиков 100 терабайт и больше);
  • отказоустойчивость (все промежуточные сервисы должны быть продублированы);
  • расширяемость (добавление новых узлов в систему должно быть легким и простым).
Начали с выбора хранилища под письма…

На самом деле выбор был небольшой:

  • dovecot/cyrus с хранением в файловой системе через maildir/mailbox;
  • dbmail с хранением в базе данных.

После оценки количества сервисов, предоставляемых «из коробки», а также изучения нюансов использования, нами было решено остановиться на dbmail.
Вот краткий список вкусностей, которые предоставляет dbmail:

  • доступ к ящикам через IMAP, POP3;
  • sieve-скрипты для сортировки почты;
  • прием почты через smtp и lmtp протоколы;
  • администрирование через cli и SQL-запросы.

В качестве MTA был выбран postfix. Поскольку мы давно с ним работаем, с уверенностью полагаем его вполне быстрой, гибкой и легко настраиваемой программой. Тем более, что на сайте dbmail есть инструкция по настройке связки postfix+dbmail.

А балансировщиком нагрузки работает лучший прокси всех времен и народов: nginx.
Web-интерфейс к почтовым ящикам может предоставлять любая из десятков доступных программ. Для начало было решено воспользоваться на RoundCube.

В итоге начала вырисовываться следующая архитектура проекта:

1. На переднем крае у нас запущен nginx с включенным модулем Mail, он принимает от клиентов коннекты по протоколам SMTP, IMAP, POP3 и, на основании имени пользователя и пароля, проксирует коннект на нужный сервер.
2. В глубине обороны работает множество postfix и dbmail, каждый из которых обслуживает свои домены.

Для внешнего мира все это выглядит как один большой почтовый сервер.

В теории масштабируемость достигнута, теперь задача реализовать.

Каждый модуль системы будет работать в своем контейнере OpenVZ. По мере увеличения нагрузки, мы будем клонировать/переносить контейнеры на новые физические серверы.

В отдельные контейнеры положим nginx, postfix с различными фильтрами почты, dbmail и хранилище писем в MySQL базе данных разместим в одном контейнере, так как dbmail не должен сильно загружать процессор, а объемы данных, передаваемые между dbmail и mysql будут большими (дублирование данных в хранилище писем будем реализовывать через механизм MySQL репликации master-slave, организуя для каждого dbmail-модуля свой hotbackup-модуль).

Так же, для удобства, в отдельные контейнеры можно выделить веб-серверы с roundcube и панелью управления всей системой.

Все контейнеры общаются между собой по локальной сети с «серыми» адресами.
Реальные интернет адреса планировалось выдать только nginx-контейнерам.
В процессе установки и настройки nginx выяснилось, что SMTP-сессии без авторизации он проксировать не умеет. Решение данной проблемы немного изменило первоначально планируемую архитектуру проекта, что привело к повышению отказоустойчивости и расширяемости. Мы отказались от проксирования SMTP трафика через nginx, и решили, что postfix-модули будут получать его напрямую.

Все postfix-модули системы сделали одинаковыми, каждый со своим реальным IP-адресом, а определяем какому именно dbmail-модулю передавать почту через transport_maps.
В итоге любой postfix-модуль может принять почту для любого домена в системе, применить различные фильтры и доставить в нужное хранилище.
Балансироваться они будут через round-robin записи в DNS:

nginx1   IN A 1.1.2.1         nginx2   IN A 1.1.2.2  postfix1 IN A 1.1.1.1 postfix2 IN A 1.1.1.2 postfix3 IN A 1.1.1.3  mx1      IN A  1.1.1.1          IN A  1.1.1.2          IN A  1.1.1.3 mx2      IN A  1.1.1.2          IN A  1.1.1.3          IN A  1.1.1.1 mx3      IN A  1.1.1.3          IN A  1.1.1.2          IN A  1.1.1.1 imap     IN A  1.1.2.1          IN A  1.1.2.2 pop3     IN A  1.1.2.1          IN A  1.1.2.2 smtp     IN CNAME mx1 _spf     IN TXT     "v=spf1 ip4:1.1.1.1 ip4:1.1.1.2 ip4:1.1.1.3 ?all" 

В домене клиента добавляются необходимые записи:

@                        IN MX 10   mx1.dbmail.io. @                        IN MX 20   mx2.dbmail.io. @                        IN MX 30   mx3.dbmail.io. @                        IN TXT     "v=spf1 a mx include:_spf.dbmail.io -all" 

Почтовые клиенты пользователей настраиваются на прием почты с pop3.dbmail.io или imap.dbmail.io, а отправку почты через smtp.dbmail.io

Не дублированными и уникальными остались только dbmail-модули, но из напрямую интернета они не доступны, поэтому необходимости в динамическом распределении нагрузки на них пока нет.
Каждый из dbmail-модулей хранит почту для нескольких доменов, если ресурсы модуля будут заканчиваться,
часть доменов можно выселить в отдельный модуль.

А в дальнейшем есть планы перейти на хранение почты в какой-либо выделенной кластерной базе данных и унифицировать dbmail-модули.

В итоге получилась вот такая масштабируемая отказоустойчивая и расширяемая почтовая система:

Все элементы нашей почтовой системы общаются между собой по стандартным протоколам и, как наивно представлялось, — все должно было заработать сразу и без необходимости строить подпорки.
К сожалению, конструкцию пришлось допиливать напильником.
Историю настройки и отладки читайте в следующих статьях.

ссылка на оригинал статьи http://habrahabr.ru/company/centosadmin/blog/167051/


Комментарии

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *