Снижаем затраты на использование AWS EC2

в 13:24, , рубрики: Amazon Web Services, AWS, EC2, Lsyncd, nginx, системное администрирование, метки: , , ,

На странице стоимости компонентов EC2 на Амазоне есть одна строчка, на которую сначала можно не сильно обратить внимание, но которая может привести к серьезным финансовым затратам — Data Transfer, трафик. Если аренду инстансов и EBS-томов можно запланировать и контролировать, то трафик предсказать довольно сложно, а игнорировать его не даст ежемесячный счет)

Для примера: средний новостной сайт, 30 тысяч посещений в сутки, его вполне потянет небольшой small или даже micro instance. Возьмем полный размер страницы 2 мегабайта, месячный трафик тогда будет (без учета закэшированного контента) — 30000 * 0.002 * 30 = 1800 GB или $216. Получается стоимость Data Transfer даже больше аренды самого инстанса! На S3 ситуация с ценами на трафик точно такая же.


Большую часть этого трафика составляет статический контент, который не обязательно раздавать непосредственно с Амазона. Нужен дешевый и быстрый канал — для этих целей отлично подходят самые простые выделенные сервера на Хетцнере.

Статика хоть и статична, но меняется постоянно — файлы закачиваются, обновляются, удаляются, поэтому придётся настроить автоматическую синхронизацию между инстансем Амазона и сервером статики.

Возьмем для этих целей lsyncd — он следит за файлами в заданных директориях используя inotify и выполняет кусочек скрипта на Lua если что-то поменялось (более полное описание lsyncd в хорошем посте: habrahabr.ru/post/132098/)

На Амазоновском сервере (примеры для CentOS):

Ставим lsyncd, rsync:

yum install lsyncd
mkdir -p /var/log/lsyncd

Создаем конфиг в /etc/lsyncd.conf со смыслом «Синхронизируем все происходящие с файлами изменения, кроме файлов php, не чаще чем раз в 3 секунды, используем rsync через ssh.»

settings = {
  logfile    = "/var/log/lsyncd/lsyncd.log",
  statusFile = "/var/log/lsyncd/lsyncd.status",
}

sync {
  default.rsyncssh,
  source = "/home/user/example.com",
  host = "static.example.com",
  targetdir = "/home/user/static.example.com",
  rsyncOps = {"-av", "--temp-dir=/tmp", "--delete", "--exclude=*php"},
  exclude = {"somestaticfile.json"},
  delay = 3,
}

Генерируем (если их еще нет) ключи через ssh-keygen, прописываем сгенерированный id_rsa.pub на сервер статики в authorized_keys.

Запускаем lsyncd:

lsync /etc/lsyncd.conf 

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

server {
   listen       80;
   server_name  static.example.com

   location / {
      root   /home/user/static.example.com;
      add_header Access-Control-Allow-Origin *; #для беспроблемного получения JSON через jQuery
      try_files $uri @pass;
   }
   location @pass {
      proxy_set_header  Host  "example.com;
      proxy_pass http://example.com;
	}
}

Получаем в итоге комбинированную надежность и гибкость AWS и дешевизну Хетцнера.

PS
Для сайтов с большим количеством файлов может потребоваться повысить лимиты на inotify в sysctl:

fs.inotify.max_user_instances = 1024
fs.inotify.max_user_watches = 65000
fs.inotify.max_queued_events = 16384

Автор: amgorb

Источник

* - обязательные к заполнению поля


https://ajax.googleapis.com/ajax/libs/jquery/3.4.1/jquery.min.js