Thursday, October 9, 2008

Устанавливаем на Amazon EC2 и Amazon EBS Java-приложение с MySQL

На примере типичного сайта опишу последовательность действий по установке на хостинг Amazon.

Приложение - сайт на Java, который требует большой вычислительной мощности. Поэтому было принято решение сразу запускаться на Amazon. В работе сайт использует на чтение-запись базу MySQL. Сайт будет развернут на одном экземпляре (instance) Elastic Computing Cloud (EC2). База MySQL - на томе (volume) Elastic Block Storage (EBS). Все пользовательские данные будут храниться в MySQL. На диске экземпляра будут храниться настройки, а также скрипт сборки приложения, который будет собирать приложения из внешних источников (например, из репозитария Subversion).

Далее в тексте, при описании вводимых команд, если приглашение оболочки начинается на $ - команду следует выполнять на локальном компьютере, если приглашение начинается на # - на удаленном экземпляре EC2.

Установка утилит EC2 и настройка окружения

  1. Заходим на http://aws-portal.amazon.com, логинимся, покупаем EC2. На страницах нужно будет найти и запомнить Access Key ID, Secret Access Key и Account ID. Также нужно сгенерировать и сохранить файл с сертификатом X.509 (cert-11111111111111.pem) и файл с приватным ключем (pk-11111111111111.pem).
  2. Устанавливаем Amazon EC2 Command-Line Tools.
    1. Скачиваем с Amazon.
    2. Распаковываем в нужное место (например, /usr/ec2).
    3. Прописываем окружение (вариант для Linux): pupkin@local$ export EC2_HOME=/usr/ec2/ec2-api-tools-1.3-19403 pupkin@local$ export PATH=$PATH:$EC2_HOME/bin pupkin@local$ export EC2_PRIVATE_KEY=/home/pupkin/mega-project/ec2/pk-11111111111111.pem pupkin@local$ export EC2_CERT=/home/pupkin/mega-project/ec2/cert-11111111111111.pem
    4. Проверить, правильно ли установлены утилиты можно, выполнив команду ec2-describe-images. Результатом команды будет список доступных для запуска образов виртуальных машин (AMI): pupkin@local$ ec2-describe-images -a IMAGE ami-5586623c 1fm2knh6gyecefa34102-phe-bucket/image.manifest.xml 437711880492 available public i386 machine IMAGE ami-63ec090a 1VYRBPTAGB3GRJD3N902-AMI-082407/image.manifest.xml 681122512140 available public i386 machine IMAGE ami-18cf2a71 1VYRBPTAGB3GRJD3N902-AMI-110407-dev/image.manifest.xml 681122512140 available public i386 machine ...

Настройка экземпляра

В качестве ОС выбираем Ubuntu Linux. За основу берем образ Ubuntu 8.04 LTS Hardy от alestic.com. Дальше доставим туда необходимые Java, MySQL и всё остальное.
  1. Запускаем экземпляр с нужным образом.
    1. Ищем последний по дате нужный образ. Выбираем base (лишнего нам не надо) и 64-битную платформу (нашему сайту будет нужно много памяти). pupkin@local$ ec2-describe-images -a |grep ubuntu |grep alestic |grep 64 IMAGE ami-17d7337e alestic-64/ubuntu-8.04-hardy-base-64-20080924.manifest.xml
    2. Генерируем ключик для доступа к экземпляру по SSH pupkin@local$ ec2-add-keypair pstam-keypair и сохраняем его в файле, например, /home/pupkin/mega-project/ec2/id_rsa-pstam-keypair.
      Если используется OpenSSH, для этого файлы нужно выставить правильные права доступа: pupkin@local$ chmod 600 /home/pupkin/mega-project/ec2/id_rsa-pstam-keypair
    3. Запускаем выбранный экземпляр pupkin@local$ ec2-run-instances ami-17d7337e -k pstam-keypair -t m1.large RESERVATION r-4073a129 701161471898 default INSTANCE i-1b903272 ami-17d7337e pending pstam-keypair 0 m1.large 2008-10-02T12:54:37+0000 us-east-1b aki-b51cf9dc ari-b31cf9da i-1b903272 - это идентификатор экземпляра. Он будет нужен позднее.
      pending - означает, что экземпляр в процессе запуска.

      Ждем 15 секунд, и выполняем команду pupkin@local$ ec2-describe-instances RESERVATION r-4073a129 701161471898 default INSTANCE i-1b903272 ami-17d7337e ec2-75-101-241-247.compute-1.amazonaws.com domU-12-31-39-01-59-41.compute-1.internal running pstam-keypair Статус должен поменяться на running. Если не поменялся - нужно подождать еще.
      Когда статус поменяется на running, в таблице будет видно внешний (ec2-75-101-241-247.compute-1.amazonaws.com) и внутренний (domU-12-31-39-01-59-41.compute-1.internal) адреса экземпляра. Внешний адрес используется для доступа к экземляру из интернета, внутренний - с других инстансов (если такие будут).
  2. Открываем доступ к экземпляру по нужным портам: pupkin@local$ ec2-authorize default -p 22 pupkin@local$ ec2-authorize default -p 80 проверяем pupkin@local$ telnet ec2-75-101-241-247.compute-1.amazonaws.com 22
  3. Логинимся на экземпляр и устанавливаем нужные пакеты pupkin@local$ ssh -i /home/pupkin/mega-project/ec2/id_rsa-pstam-keypair root@ec2-75-101-241-247.compute-1.amazonaws.com root@domU-12-31-39-01-59-41# apt-get update root@domU-12-31-39-01-59-41# apt-get install mysql-server root@domU-12-31-39-01-59-41# apt-get install apache2 root@domU-12-31-39-01-59-41# apt-get install sun-java6-jdk root@domU-12-31-39-01-59-41# apt-get install zabbix-agent root@domU-12-31-39-01-59-41# apt-get install subversion root@domU-12-31-39-01-59-41# apt-get install postfix root@domU-12-31-39-01-59-41# apt-get install mailx Дополнительные пакеты можно будет поставить и позднее, при необходимости.

Настройка Elastic IP

При каждом старте экземпляре ему выдается новый IP-адрес. Чтобы при этом избежать проблем с DNS-ом, закажем также Elastic IP. pupkin@local$ ec2-allocate-address ADDRESS 75.101.137.69 pupkin@local$ ec2-associate-address -i i-1b903272 75.101.137.69 ADDRESS 75.101.137.69 i-1b903272 - это идентификатор экземляра. Если вы его забыли, можно посмотреть командой ec2-describe-instances). Теперь этот адрес можно (и нужно) прописать в DNS, например, связав с именем http://mega-project.pupkin.com.

Настройка EBS

  1. Создаем том. pupkin@local$ ec2-create-volume -s 200 -z us-east-1b us-east-1b - зона, или датацентр Amazon. Её нужно выбрать такой же, в какой запущен экземпляр, чтобы не гонять лишний трафик. Посмотреть зону экземпляра можно командой ec2-describe-instances. Ждем пока поднимется, смотрим информацию о томах: pupkin@local$ ec2-describe-volumes VOLUME vol-2a08ed43 200 us-east-1b available 2008-10-02T15:50:14+0000
  2. Подключаем том к инстансу pupkin@local$ ec2-attach-volume -i i-1b903272 vol-2a08ed43 -d /dev/sdd1
  3. Для новосозданного тома создаём и монтируем файловую систему на экземпляре pupkin@local$ ssh -i /home/pupkin/mega-project/ec2/id_rsa-pstam-keypair root@ec2-75-101-241-247.compute-1.amazonaws.com root@domU-12-31-39-01-59-41# mkfs -t ext3 /dev/sdd1 root@domU-12-31-39-01-59-41# mkdir /mnt/db root@domU-12-31-39-01-59-41# mount /dev/sdd1 /mnt/db Монтирование /dev/sdd1 в /mnt/db нужно прописать в /etc/fstab. Тогда при перезапуске экземпляра том примонтируется автоматически.

Настройка ПО

  1. MySQL MySQL нужно перенести из папки по умолчание (/var) на EBS в раздел с данными (мы его смонтировали в /mnt/db).
    1. Останавливаем MySQL. root@domU-12-31-39-01-59-41# /etc/init.d/mysql stop * Stopping MySQL database server mysqld
    2. Копируем уже созданную БД. root@domU-12-31-39-01-59-41# mkdir /mnt/db/lib /mnt/db/log root@domU-12-31-39-01-59-41# mv /var/lib/mysql /mnt/db/lib/ root@domU-12-31-39-01-59-41# mv /var/log/mysql /mnt/db/log/ root@domU-12-31-39-01-59-41# test -f /vol/log/mysql/mysql-bin.index && perl -pi -e 's%/var/log/%/vol/log/%' /vol/log/mysql/mysql-bin.index
    3. Правим конфиг. root@domU-12-31-39-01-59-41# vim /etc/mysql/my.cnf Раздел mysqld должен быть таким [mysqld] innodb_file_per_table datadir = /mnt/db/lib/mysql log_bin = /mnt/db/log/mysql/mysql-bin.log max_binlog_size = 1000M log_slow_queries = /mnt/db/log/mysql/mysql-slow.log long_query_time = 10
    4. Запускаем. root@domU-12-31-39-01-59-41# /etc/init.d/mysql start
  2. Собственно сайт
    1. Создаём пользователя, под которым будет работать сайт (если сайт сделан в виде отдельного процесса). root@domU-12-31-39-01-59-41# /usr/sbin/adduser mega-project
    2. Пишем скрипт сборки, который
      • чекаутит последнюю версию сайта из репозитария Subversion;
      • делает сборку;
      • перезапускает сайт из новособранной версии.
    3. Запускаем скрипт, настраиваем конфиги приложения, запускаем приложение. Теперь можно зайти на http://mega-project.pupkin.com/ и посмотреть на работающий сайт :)

Сохраняем образ тома

Чтобы не потерялась проделанная работа, нужно сохранить образ настроеного экземпляра. Сохраненный образ также пригодится, если экземпляр нужно будет перезапустить, для поднятия кластера и др.
  1. Копируем ключи и сертификат - они будут нужны на экземпляре. pupkin@local$ cd /home/pupkin/mega-project/ec2/id_rsa-pstam-keypair pupkin@local$ scp -i id_rsa-pstam-keypair id_rsa-pstam-keypair root@ec2-75-101-241-247.compute-1.amazonaws.com: pupkin@local$ scp -i id_rsa-pstam-keypair pk-11111111111111.pem root@ec2-75-101-241-247.compute-1.amazonaws.com: pupkin@local$ scp -i id_rsa-pstam-keypair cert-11111111111111.pem root@ec2-75-101-241-247.compute-1.amazonaws.com:
  2. Собираем пакет с файлами root@domU-12-31-39-01-59-41# ec2-bundle-vol -e /tmp -d /mnt -k pk-11111111111111.pem -c cert-11111111111111.pem -u <Account ID без символов -> -p mega-project-image -s 1500 1500 - размер образа. На стоимость хранения не оказывает влияния, но при небольших размерах быстрее архивируется (перед хранением) и быстрее стартует экземпляр.
    Размер образа должен быть не меньше, чем размер примонтированной на / файловой системы.
    Если значение размера будет слишком маленьким, команда ec2-bundle-vol может выдать сообщение об ошибке execution failed: "rsync ... "
  3. Заливаем собранный пакет в Amazon Structured Storage Service (S3). root@domU-12-31-39-01-59-41# ec2-upload-bundle -b pupkin-images -m /mnt/mega-project-image.manifest.xml -a <Access Key Id> -s <Secret Access Key>
  4. С локальной машины регистрируем пакет как образ.
  5. pupkin@local$ ec2-register pupkin-images/mega-project-images.manifest.xml Всё, дело сделано :).

Возникшие проблемы и вопросы

  1. Почему-то MySQL сразу при старте начинает сильно загружать процессор. Полечилось перезапуском MySQL.
UPD. При переносе данных MySQL в другую папку нужно также поправить настройки apparmor (в /etc/apparmor.d/usr.sbin.mysqld) и logrotate (в /etc/logrotate.d/mysql-server)

10 comments:

Unknown said...

Отличная полезная заметка. Сейчас выбираю между vds и сервисом амазона. Как оно в использовании? приятно?

Vasyl Stashuk said...

Очень и очень :)

Все новые большие сервисы на нем буду поднимать.

Один из старых сайтов запущен на собственном сервере - так собираюсь переносить на Амазон.

Единственный негатив, который обнаружился при эксплуатации - у сервера Reverse DNS резолвится в прикольное имя, и некоторые параноидальные почтовые сервера не хотят принимать почту. Лечится поднятием отдельного сервера для почты, или использованием бесплатного (например, Google Apps) или платного (например, AuthSMTP) провайдера почты.

Alexander Smirnov said...

Вы забыли прописать в /etc/fstab монтирование...
Да и по-моему проще было бы монтировать папки из volume сразу в /etc/mysql, /var/lib/mysql etc...
тогда не будет необходимости править конфиги mysql,apparmor etc.

Vasyl Stashuk said...

Pimpl, действительно, еще нужно занести в /etc/fstab, спасибо.

Поправил пост.

Alexander Smirnov said...

По поводу почты. Вы добаляли MX запись к dns ?.. Просто тоже недавно поднимали почту на амазоне - все вроде прошло спокойно.

vasyas.blogspot.com said...

Дело не в том, что принципиально нельзя отправить письмо. Отправить можно. Но очень многие поисковики кладут в спам письма, которые пришли с IP, у которых нет нормального Reverse DNS. А у Амазон как раз нет.

Alexander Smirnov said...

Ммм.. Я так понимаю вы не регистрировали доменного имени, тогда да - многие почтовые сервера игнорируют/отбрасывают такие письма.
Я немного о другом говорил, мы просто тоже встречались с проблемой - даже после того как у вас появляется доменное имя привязанное к вашему ip - многие почтовые сервера(не будем показывать пальцем на яндекс) всеравно будут отбрасывать ваши письма пока у вас не появится на dns MX запись на ваш почтовый сервер - она может ссылаться на ту же машину, главное чтобы она была...

Anonymous said...

Не, доменное имя было.
Побоюсь описать известные вещие, но, грубо говоря, есть два вида DNS resolving: прямой DNS, когда по имени определяем IP, и обратный, когда по IP узнаем имя (через PTR-запись). Так вот, многие сервера MTA отправляли письма в спам, если IP SMTP сервер не резолвися в нормальное DNS имя.

Alexander Smirnov said...

Не знал. Вы сподвигли меня на более глубокое изучение данного вопроса, за что большое спасибо, нашли потенциальные проблемы. Интересно что далеко не все почтовые сервера требуют наличия верной ptr записи, не заметили проблему из-за отсутствия проблем с доставкой почты на gmail, yandex, mail.ru...

Vasyl Stashuk said...

Проблема с PTR проявилась как раз в процессе эксплуатации - пришлось в срочном порядке переходить на другой хостинг для SMTP.

Рад оказаться полезным.
Если найдете, как можно поднять SMTP на Amazon EC2 - будет очень интересно узнать.