Як задеплоіть на AWS проект на Symfony2

Стаття не претендує на ідеальну технічну точність і повноту, вона призначена для швидкого вирішення конкретної практичного завдання з мінімально достатнім розумінням суті що відбувається .

Завдання

Останні кілька місяців команда розробників в компанії WebKate працювала над досить великим стартапом для наших норвезьких замовників. Проект являє собою мультиплатформенні спортивну соцмережа . Мобільна частина реалізована за допомогою Xamarin . На бекенде - Symfony2 з API, адмінкой і веб- інтерфейсами для всіх типів користувачів . Виникла необхідність розгорнути проект на платформі Amazon Web Services . Здавалося б - візьми мануал та й зроби , але виявилося, не все так просто. Штатні мануали Амазону не передбачають такого раптового розвитку подій, та й взагалі, на жаль, не відрізняються зручністю і ясністю ( Амазон пропонує створювати проект і AWS -додаток з нуля, і як на мене, досить незручним способом). Методом гугленія були роздобутим деякі частини необхідного пазла. Але так як готової картини ніде не виявилося, довелося підключати метод наукового тику . У результаті вийшов досить простий і зручний спосіб деплоя . Отже, що у нас є : Цілком звичайний проект на Symfony 2.5 . Читає звичайну MySQL - базу. На запитання відповідає звичайними HTML - сторінками . Мешкає в звичайному git - репозиторії . На локальному LAMP - е працює дуже навіть непогано. Аккаунт на AWS . Що потрібно: Розгорнути проект на великому і надійному Амазон . Мінімізувати час і зусилля при вивантаженні нових версій проекту. Передбачити можливість швидкого і легкого масштабування надалі.

Для початку трохи про AWS

Загальною інформації на просторах інтернету цілком достатньо , тому спробую пояснити на пальцях . Отже, серед безлічі потрібних і зручних сервісів до нашого випадку мають безпосереднє відношення такі: EC2 - ( Elastic Compute Cloud ) - віртуальні сервера додатків RDS - ( Relational Database Service ) - реляційні бази EB - ( Elastic Beanstalk ) - сервіс , який використовує попередні два, надає комплексну середу програму з механізмами реплікації, балансування і т . д. Власне саме з Beanstalk -му ми будемо домовлятися щоб дав притулок наш проект, надав йому все необхідне, допоміг обжитися і сподобалася надалі. Тепер розберемося як це виглядає. У Beanstalk ви можете створювати Додатки ( Application ) . Додаток містить Середовища ( Environments ) . Кожна середа містить , власне , екземпляри самих серверів ( EC2 - Instances ) . Осібно сидять бази ( RDS- інстанси ) . Кожна прикріплена до своєї Середі . Також у кожній Середі є свій балансувальник , що розподіляє навантаження між серверами ( EC2 - інстанси ) цієї Середовища . Коли проект вже розгорнуто , користувачі бачать його по URL Середовища ( по суті це URL балансувальника , і користувач не може знати на якому саме EC2 - інстанси виконується код) . У процесі деплоя ви надаєте Додатком нову версію вашого коду . Як правило, ви відразу ж говорите йому на інстанси який Середовища розгорнути цю версію. База , при необхідності , заливається окремо , стандартним для MySQL способом , безпосередньо в RDS- інстанси , який прілінкованние до даної Середі . Додаток пам'ятає вивантажені версії проекту , і ви можете в будь-який момент переключити будь-яку Середу на будь-яку версію . У нашому випадку цих знань достатньо, а більш докладно можна почитати в документації Beanstalk .

Створення Додатки

Мається на увазі, що у вас є аккаунт на AWS , ви прописали користувачів, надали для них доступ до сервісів ( EC2 , RDS, EB) . З веб інтерфейсу створити Додаток досить просто. Заходимо на сторінку сервісу Elastic Beanstalk , натискаємо Create New Application , слідуємо інтуїтивно зрозумілому інтерфейсу і логіці. Можна підстрахуватися інструкцією . Назва для Додатки краще вибрати коротке - скажімо, MyApp . Для Сред непоганий варіант типу MyApp - dev (це я до того, що вам потім з консолі набирати ) . Не забудьте прописати Security Groups і підключити до них користувачів . Також вкажіть в налаштуваннях Середовища відносний шлях у проекті до кореневої папці хоста (наприклад/web ) . Незважаючи на те, що інстанси були створені через Beanstalk , ви можете їх бачити і через інтерфейс сервісу EC2 . Так само і з базами. Цілком можливо, що вам знадобиться ssh -доступ до інстанси . У такому випадку вам необхідно свій ключ додати в інтерфейсі EC2 ( вкладка Key Pairs ) і підключити його в налаштуваннях Середовища ( вкладка Instances ) . IP інстанси URL можна взяти в його властивостях в інтерфейсі EC2 . Коннект як ec2 - user без пароля. Аналогічно необхідні параметри RDS інстанси можна взяти в його властивостях в інтерфейсі RDS.

Установка консолі

AWS надає консольний інструмент для роботи зі своїми сервісами. Його потрібно встановити : 1 . Завантажити AWS Elastic Beanstalk Command Line Tool . 2 . Розпакувати його (наприклад як/opt/AWS - ElasticBeanstalk - CLI ) . 3 . Виконати в будь-якій директорії :
export PATH=$PATH:/opt/AWS-ElasticBeanstalk-CLI/api/bin/:/opt/AWS-ElasticBeanstalk-CLI/eb/linux/python2.7/ Інструмент встановлений, тепер розповімо про нього нашим проектом : 4 . У кореневій директорії нашого репозиторію виконати :
/ opt/AWS - ElasticBeanstalk - CLI/AWSDevTools/Linux/& lt ; a href = " http://AWSDevTools-RepositorySetup.sh " & gt ; AWSDevTools-RepositorySetup.sh & lt ;/a & gt ; 5 . Там же виконати : git aws.config і ввести
свої AWS - креденшали (користувача якого ви створили в акаунті) ,
зону де прописана середу в яку ми збираємося деплоіть свій проект ( наприклад eu - west -1) назва Додатки ( application ) (наприклад MyApp )
назву Середовища ( environment ) (наприклад MyApp - dev ) Після цього там же, в кореневій директорії репозиторія , можна виконувати команду git aws.push при цьому поточна гілка репозиторію буде автоматично задеплоена в задану Середу . Цілком можливо ви захочете створити іншу Середу (наприклад MyApp - live ) і деплоіть в неї інші гілки цього ж проекту . У такому випадку ви завжди можете переключитися на іншу Середу командою git aws.config , при цьому креденшали перепитує вже не будуть, так як вони вже збережені в домашній директорії поточного користувача. У процесі деплоя всередині EC2 - інстанси отриманий з репозиторію код розміщується в директорію/var/app/ondeck . Якщо є файл composer.json то виконується подгрузка залежностей і виконуються скрипти , прописані для композер . У разі Symfony це генерація Ассет , чистка кеша і т.д . Якщо виявляється , що ми розгортаємо проект на Symfony , то інстанси силами ACL надає необхідні доступи до папок кеша і логів . Після чого, якщо все пройшло гладко, віддаляється директорія з розгорнутою проектом попередньої версії , і новий , готовий до роботи проект переноситься на його місце, в директорію/var/app/current . Здавалося б все , але є проблемка - нам доведеться щоразу лізти руками в кожен інстанси , щоб прописати дані в parameters.ini нашої улюбленої Symfony . Але не все так погано.

Створення скрипта

1 . Справа в тому, що у нас всередині інстанси вже є необхідні для parameters.ini дані . Вони Інжект в інстанси Середовищем і видно в PHP як змінні оточення . А якщо чогось немає , ми можемо внести в конфігурацію Середовища, і воно буде Інжект в кожен створюваний там інстанси . 2 . Ми можемо написати скрипт збірки попереднього файлу конфігурації і прописати його виконання в композер . // /src/MyApp/AppBundle/Util/AwsDeploy.php & lt ; ? php namespace MyApp AppBundle Util ; use Symfony Component Yaml Yaml ; use Composer Script Event ; class AwsDeploy {     public static function buildParameters (Event $ event )     {         if ( array_key_exists (' RDS_HOSTNAME ' , $ _SERVER )) {                      // Якщо проект розгортається в Beanstalk , збираємо дані , передані нам Середовищем про підключене RDS- інстанси ( базі ) .             $ parameters = array (                 ' database_host ' = & gt ; $ _SERVER [' RDS_HOSTNAME '] ,                 ' database_port ' = & gt ; $ _SERVER [' RDS_PORT '] ,                 ' database_name ' = & gt ; $ _SERVER [' RDS_DB_NAME '] ,                 ' database_user ' = & gt ; $ _SERVER [' RDS_USERNAME '] ,                 ' database_password ' = & gt ; $ _SERVER [' RDS_PASSWORD '] ,             ) ;             // Також збираємо довільні параметри , які ми перед цим помістили в конфігурацію Середовища             foreach ($ _SERVER as $ key = & gt ; $ val ) {                 if (' PARAM_ ' == substr ($ key , 0 , 6) ) {                     $ parameters [ strtolower ( substr ($ key , 6) )] = $ val ;                 }             }             // Зберігаємо ці дані у файл параметрів             file_put_contents ('/var/app/ondeck/app/config/parameters.yml ' , Yaml :: dump ( array (' parameters ' = & gt ; $ parameters ) , 99 )) ;         }     } } І прописуємо запуск. Причому обов'язково ДО остаточного складання файлу параметрів ( Incenteev \ ParameterHandler \ ScriptHandler :: buildParameters ): // /composer.json ....     " scripts " : {         " post - root - package - install " : [             " SymfonyStandard \ Composer :: hookRootPackageInstall "         ],         " post - install - cmd " : [             " MyApp \ AppBundle \ Util \ AwsDeploy :: buildParameters " ,             " Incenteev \ ParameterHandler \ ScriptHandler :: buildParameters " ,             " Sensio \ Bundle \ DistributionBundle \ Composer \ ScriptHandler :: buildBootstrap " ,             " Sensio \ Bundle \ DistributionBundle \ Composer \ ScriptHandler :: clearCache " ,             " Sensio \ Bundle \ DistributionBundle \ Composer \ ScriptHandler :: installAssets " ,             " Sensio \ Bundle \ DistributionBundle \ Composer \ ScriptHandler :: installRequirementsFile " ,             " Sensio \ Bundle \ DistributionBundle \ Composer \ ScriptHandler :: removeSymfonyStandardFiles "         ],         " post - update - cmd " : [             " MyApp \ AppBundle \ Util \ AwsDeploy :: buildParameters " ,             " Incenteev \ ParameterHandler \ ScriptHandler :: buildParameters " ,             " Sensio \ Bundle \ DistributionBundle \ Composer \ ScriptHandler :: buildBootstrap " ,             " Sensio \ Bundle \ DistributionBundle \ Composer \ ScriptHandler :: clearCache " ,             " Sensio \ Bundle \ DistributionBundle \ Composer \ ScriptHandler :: installAssets " ,             " Sensio \ Bundle \ DistributionBundle \ Composer \ ScriptHandler :: installRequirementsFile " ,             " Sensio \ Bundle \ DistributionBundle \ Composer \ ScriptHandler :: removeSymfonyStandardFiles "         ]     } , .... Якщо є необхідність передати додаткові дані у файл параметрів - можна додати змінні в конфігурації Середовища ( Configuration - & gt ; Software configuration - & gt ; Environment properties ) з назвами , що починаються з « PARAM_ ». Наприклад, змінна з назвою « PARAM_NEW_VAL » буде передана в parameters.yml як « new_val ».

Підсумки

Ось тепер деплоймент проекту дійсно автоматичний . У разі будь-яких збоїв ви можете переглянути логи через відповідний розділ в інтерфейсі Beanstalk . При цьому недодеплоенний проект залишиться в інстанси в/var/app/ondeck доступний для дослідження по ssh . Ну і, природно , стара версія проекту при цьому буде як ні в чому не бувало обслуговувати запити , і користувачі вашого проекту так і не дізнаються про дрібних технічних проблемка . Сподіваюся , стаття виявиться корисною для тих, хто починає працювати з AWS . Бажаю вам заощаджений на деплойменте час витратити на нові корисні фічі для вашого проекту. :)

Опубліковано: 08/01/15 @ 10:57
Розділ Різне

Рекомендуємо:

17 січня - 7 лютого, Київ - Семінар « Підготовка до іспиту PMP® »
Android -дайджест # 2. Красивий і чуйний UI
Як я здавав ISTQB Advanced Level
Як українські IT- компанії відзначили Новий рік 2015
Як пережити випробувальний термін