Продакшн сервера на Fornex - выбор площадки хостинга и настройка
Primary tabs
Итак, давайте представим что Вы долго и упорно писали и создавали Ваш проект, но вот весь код написан, автоматические и ручные тесты успешно выполнены, ( пиво выпито, инвестиции заказчика спущены, нужное подчеркнуть) и вот настало время выходить в продакшен!
Однако этот самый продакшен должен быть как-то подготовлен… Если разработку вы вели у себя используя стенд на Vagrant или упаси высший разум на каком-нибудь Denver, то теперь надо как-то где то подготовить для этого площадку, настроить, задеплоить… Интересно? Поехали!
План разворачивания сайта
Итак, краткий план:
Выбор площадки
Развертывание инфраструктуры
Настройка серверов
Подготовка мониторинга
Перенос кода и данных
Настройка DNS
Выбор площадки
Идеальным выбором для размещения своего проекта на мой взгляд является площадка, имеющая свой API, с помощью которого можно автоматизировать управление инфраструктурой - создание серверов например. То есть не сидеть и не тыкать в интерфейсе мышкой а написать один раз скрипт или использовать некоторое специализированное решение. Яркий пример - AWS, Digital Ocean и иже с ними. Там Вам даже не придется ничего придумывать в плане автоматизации.
Дефакто стандартом для управления инфраструктурой в виде кода ( IAAC - Infrastructure As A Code) является Hashicorp Terraform - поэтому просто смотрим, есть ли в списке его плагин - провайдеров поддержка нужного Вам сервиса, либо идем на Github и ищем там ( возможно плагин уже есть просто не вошел в официальный список - я так находил для DNS от GoDaddy.
Плюсы такого решения - Вы тратите от пары часов до дня чтобы разобраться как это работает и написать подходящий код (лучше при этом сразу загуглить best practices), а потом забываете про настройку как про страшный сон и просто добавляете пару строчек кода если надо. Ну и конечно храните это как проект в Git.
Минусы
- стоимость вычислительных ресурсов на
таких площадках ( сиречь аренда виртуалок)
стоит несравнимо дорого по сравнению
с теми кто еще не имеет таких функций.
Поэтому если у Вас еще не очень большой
проект или более того - он учебный,
оставим пока эти возможности в голове,
так сказать на память, и посмотрим более
простое и недорогое решение. Например,
площадка хорошего европейского
качества, быстрый, качественный провайдер
Fornex
(да, не лишним будет упомянуть, что выбирая
отечественных хостинг провайдеров вы должны учитавать состояние правовой системы и практики ещё применения (а тут бывают промашки),
яркий тому пример - недавняя попытка
рейдерского захвата датацентра
компании IHOR)
(с другой стороны, бывают ситауации, когда без сервера в России не обойтись, но не будет отклоняться от темы)
.
Специально для
читателей этого сайта Fornex предоставил
промокод fkn.ktu10 который дает скидку
10% на покупку всех услуг провайдера.
Для активации промокода, нужно
зарегистрироваться,
выбрать нужную услугу и тариф, а затем
нажать на ссылку «у меня есть
промо-код».
Отлично. площадку выбрали,
займемся инфраструктурой!
Развертывание инфраструктуры
Итак, тут все просто - как уже договорились выше, считаем что у нас учебный или очень небольшой проект, автоматизация развертывания нам не нужна, поэтому просто заказываем и арендуем пару виртуальных серверов - один под наши бизнес задачи, второй для технических нужд - мониторинг там, бекапы и тп.
На каждый сервер ставим Ubuntu Linux без всяких там надстроек, панелей управления и пр
И не забываем закинуть туда автоматически ssh ключ:
Итак, вот для начала и наша инфраструктура. Для тех, чей проект будет серьезней, советую все же подробней ознакомиться с Terraform!
Настройка серверов
Настраивать сервера вручную, подключаясь к каждому по ssh - это моветон в 2019 году! Во первых, это монотонно и утомительно, во вторых - это плохо масштабируется ( вот надо Вам настроить не 2 сервера а 20 - так же будете команды вбивать?) а в третьих, велик риск получить сервера “снежинки”, конфигурация каждого из которых уникальна, в силу того что каждый раз Вы могли ошибиться или привнести некий “кастом”, просто потому что в процессе работы Вы думали и решили немного изменить сценарий а перенастраивать уже ранее настроенные хосты лень, нет времени, как нибудь потом.
Именно поэтому уже не первый год знающие люди прибегают к использованию специализированных средств управления конфигурацией: puppet, chief, ansible и тд. Про преимущества каждого предлагаю прочитать соответствующие статьи в интернете, коих много. В рамках данного руководства предлагаю использовать Ansible. И нет, не потому что стильно, модно, молодежно ( нужное подчеркнуть), а потому что очень простой yaml декларативный синтаксис, отсутствие необходимости ставить агенты, доступ через ssh (то есть сразу из коробки да еще и безопасно), плюс есть возможность просто одновременно выполнять команды на хостах - эдакий parallel ssh.
Если Вас это заинтересовало, вот тут по ссылке хорошее руководство.
В нашем случае все будет предельно просто… Мы лишь хотим вначале проверить возможность “достучаться” до серверов с помощью Ansible а потом с его помощью поставить часть пакетов и сконфигурировать. Для начала напишем тн “inventory” файл, который будет в себя включать информацию о самих хостах - как до них достучаться и т.д. Выглядит он следующим образом (обзовем его hosts.yml):
И опишем заготовку тн “playbook” файла - то есть нашего сценария, в котором будут располагаться задачи:
Теперь с помощью командной строки проверим что сценарий отработает - это покажет нам что синтаксис верен, хосты доступны, ssh ключ подходит и тп:
Отлично! До хостов мы достучались, можно и сконфигурировать! Итак, что мы хотим:
Поставить ряд пакетов с дополнительными утилитами по списку,
Установить веб сервер ( пусть в одном случае это будет Apache, а в другом Nginx)
СУБД ( Конечно же Mysql)
И настроить фаервол ( откроем 22, 80, 443 и еще 10050-10051 это порты системы мониторинга но об этом позже)
Приступаем к написанию! По итогу у нас получается следующий playbook ( Довольно длинный):
--- - hosts: all gather_facts: yes tasks: - name: Install a list of packages apt: name: "{{ packages }}" vars: packages: "{{ packages_list }}"
- name: Install apache apt: name: apache2 when: inventory_hostname == "infrastructure"
- name: Install nginx apt: name: nginx when: inventory_hostname == "service"
- name: DB | Specify MySQL root password before installing debconf: name: 'mysql-server' question: 'mysql-server/root_password' value: '{{ db_root_password | quote}}' vtype: 'password' become: true
- name: DB | Confirm MySQL root password before installing debconf: name: 'mysql-server' question: 'mysql-server/root_password_again' value: '{{ db_root_password | quote}}' vtype: 'password' become: true
- name: DB | Install MySQL server apt: name: "{{ db_packet_install_list }}" state: present
- name: DB | Create a new database mysql_db: name: "{{ database_name }}" state: present encoding: utf8 login_host: localhost login_port: "{{ db_port }}" login_user: "{{ db_root }}" login_password: "{{ db_root_password }}"
- name: DB | Create user and grant privileges for database mysql_user: name: "dbadmin" host: "localhost" password: "{{ db_non_root_password }}" priv: '{{ database_name }}.*:ALL' state: present login_host: localhost login_port: "{{ db_port }}" login_user: "{{ db_root }}" login_password: "{{ db_root_password }}"
- name: Firewall | Allow access to list of ports ufw: rule: allow port: "{{ item }}" proto: tcp with_items: - "{{ firewall_open_ports }}"
- name: Firewall | Enable UFW and set default policy to Deny ufw: state: enabled policy: deny
|
Он довольно простой - лишь ставит пакеты да что-то немного конфигурирует. На самом деле, с помощью Ansible можно сделать куда больше! Но у нас же учебный пример, ведь так? Иначе мне придется переписать все руководство… Если Вы заметили - в некоторых местах стоят не значения а переменные, в фигурных скобках. Их значения я вынес в файл inventory:
all: hosts: service: ansible_host: 5.187.7.24 infrastructure: ansible_host: 5.187.4.37 vars: ansible_port: 22 ansible_connection: ssh ansible_user: root ansible_ssh_private_key_file: ~/.ssh/your_ssh_key ansible_python_interpreter: /usr/bin/python3 db_root: root db_port: 3306 db_packet_install_list: - mysql-client - mysql-common - mysql-server database_name: "test" db_root_password: "Qwerty.123" db_non_root_password: "Test!123" firewall_open_ports: - 80 - 443 - 22 - 10050 - 10051 packages_list: - vim - mc - git - htop - iotop - sysstat - tmux - molly-guard - software-properties-common - host - git - mtr - ufw - tree - ntp - python3-pymysql - debconf-utils |
Пароль так хранить кстати не стоит - познакомьтесь с такой штукой как Ansible vault.
Итак, попробуем запустить и посмотрим, каков же будет результат:
Отлично, ansible прошелся по всем нашим серверам (коих пока только 2 но можно и 20 и 100) и все настроил! А теперь посмотрите на текст плейбука и прикиньте, сколько бы вы все это писали на bash, с проверкам иусловий и обработкой ошибок….
Подготовка мониторинга
Отлично, мы настроили сервера, пришло время подключить мониторинг.
В качестве учебного примера мы возьмем не модные сейчас TICK и TIG связки а классический Zabbix, тем более что для малого проекта его нам должно хватить за глаза (Плюсы для новичков - отличная русскоязычная документация и возможность интегрировать его с кучей решений за счет наработок сообщества).
Для установки самого zabbix мы будем использовать машину под именем infrastructure, а наблюдать он будет за машиной service ( ну и за другими если таковые найдутся в Вашем проекте). Помимо наблюдения за доступностью самой ОС, можно подключить наблюдение за любым сервисом - с помощью встроенных или кастомных шаблонов ( вы можете написать их сами или найти в интернете).
Установку было бы неплохо автоматизировать при помощи Ansible, но во первых такой playbook уже есть, а во вторых не будем концентрироваться на установке ибо статей и инструкций в интернете вагон ( не считая официальной документации откуда и надо это все брать).
Итак, сервер поставили, агент на другой сервер тоже поставили, весь конфиг там будет вот такой:
По сути нам нужно поменять 2 директивы - имя хоста ( должно быть уникальным) и IP адрес сервера zabbix, те. адрес с которого мы разрешаем делать запросы. Сохраняем, перезапускаем, идем в веб интерфейс zabbix:
Configuration - Hosts - create host - добавляем наш узел:
Навешиваем ему несколько стандартных шаблонов:
И гордо жмем кнопку ADD! В списке хостов у нас будет их уже два - первый это сам zabbix сервер, второй это наш хост. Ждем пока он приобретет зеленый статус в колонке “Availability”
И Можно начинать любоваться данными которые потекли к нам рекой (Monitoring - latest data)
А можно и графиками
Отлично, телеметрия у нас есть. Но zabbix нам нужен и для алертинга - предупреждения на случай если что то пошло не так. По умолчанию он умеет отправлять уведомления по эл почте, но при желании можно научить его слать и в telegram, и в slack.
Если же Вы решили что для Вашего проекта такая схема это перебор ( ну действительно учебный или тестовый), тот же Fornex “из корбки” предоставляет простой мониторинг со сбором стандартных метрик с виртуальных машин- процессор, память, диск, сеть:
Так, с мониторингом закончили, идем дальше!
Перенос кода и данных
Итак, пришло время “задеплоить” Ваш проект - то есть развернуть его в рабочей среде для дальнейшей эксплуатации.
Рассмотрим 2 сценария:
Вы вели разработку локально, не пользуясь никакой системой контроля версий. Накодили и готово. В таком случае достаточно собрать Ваш проект в один архив, загрузить на удаленный сервер, разархивировать там в нужную папку, выставить права доступа и готово! Плюс такого решения - простота, минус- есть шанс потерять наработки в процессе из за ошибок. В этом месте хочу дать ровно 1 совет - выкиньте уже в топку FTP протокол. Есть же SFTP и SCP которые вы получаете “из коробки”, установив ssh сервер на свой vds ( а он обычно и так установлен)/
Вы использовали.. скажем GIT! Отлично! Тогда заходим на Ваш гит сервер, получаем там ссылку для скачивания архива актуальной версии или делаем “git clone” на машине с последующим очищением каталога от метаданных git-а ( удалить скрытую папку git)... И выставляем права. Звучит уже больше как CI/CD процесс - например если Вы пользователь GitLab можете настроить себе такой pipeline - чтобы он логинился на сервер, и делал за вас все три этих действия ( клон, очистка, выставление прав). В итоге вы будете получать код по нажатию кнопки.
Но как быть, если в сценарии 2 если вы хотите попробовать развернуть разные версии? То есть действительно реализовать что то близкое к настоящему CI/CD ? Ведь вы не сможете клонировать постоянно все в одну и ту же папку… Очень просто - при клонировании, укажите как назвать создаваемый в результате каталог, прибавляя к его имени скажем… временную отметку.. И создавайте на него некоторый чистый “симлинк”... Давайте объясню на примере:
Пусть Ваш веб-сервер ожидает увидеть код сайта и все сопутствующие файлы в каталоге “/var/www/sitename”.
Делая git clone, просим клонировать его содержимое репозитория в папку “/var/www/sitename_date_time_1”
Делаем симлинк “/var/www/sitename”, который указывает на “/var/www/sitename_date_time_1”
Удаляем из папки “/var/www/sitename_date_time_1” подпапку “.git” и выставляем корректные права.
Перезапускаем веб сервер
В случае повторения операции, при клонировании будет создана папка “/var/www/sitename_date_time_2” ( дата и время будет отличаться)
Симлинк будет переключен на новую папку, права изменены, так же перезапускаем веб сервер.
Бонусом вы получите легкую возможность “откатиться” на предыдущую версию сайта за пару команд! ( Вернуть симлинк, перезапустить веб сервер).
Если gitlab не является Вашим хостингом, можете на второй, инфраструктурной машине развернуть jenkins или любое другое ПО для реализации CI/CD процесса которое будет Вам по душе.
Отлично, код мы перенесли и даже научились его непрерывно доставлять, как это модно сейчас… Осталось перетащить еще и данные. И тут я имею ввиду не контент типа картинок и прочих статических файлов - для них сценарий аналогичен сценарию 1 - грузите их архивом по scp/sftp… Кстати если Вы хотите выкатывать код по сценарию 2, каталог с статическими файлами типа картинок и документов лучше держать отдельно от кода и ни в коем случае не работать с ним с помощью git!
Так вот, сейчас я хотел поговорить о переносе содержимого базы данных. Для каждого движка СУБД есть свои рекомендуемые утилиты для создания и восстановления резервной копии - mysqldump для Mysql, pg_dump для PostgreSQL, mongodump для MongoDB и тд… Вполне возможно что они подойдут Вам в этом сценарии, однако стоит упомянуть про то, что в большинстве случаев процесс дампинга базы данных приводит к блокировке ( тн локу) таблиц на момент создания дампов - то есть у Вас нет возможности в этот момент ничего в базу писать. В случае учебного проекта или небольшого сайта это не проблема от слова совсем, а вот в случае когда у Вас клиенты на сайте в режиме 24/7 это может быть проблема! И тут есть два выхода:
использование более гибких решений
перенос данных за счет репликации
По п.1 - нужно просто найти подходящий инструмент, ознакомиться с тем как он работает, потестить ( убедиться что это то, что надо) и применять! Например для Mysql есть замечательная утилита Xtrabackup.
По п.2 - этот вариант очень хорошо подходит если Вам необходимо иметь минимальный временной разрыв с т.з. актуальности данных между Вашими площадками ( предположим что Вы занимаетесь не развертыванием сайта после разработки а переносите решение с хостинга А - скажем какого нибудь ruvds или timeweb на хостинг В - в тот же Fornex). Тогда этот вариант предпочтительнее - Вы просто настраиваете на новом месте свежеустановленный экземпляр СУБД в качестве реплика- слейва ( то есть тот кто реплицирует а не тот с кого…) и ждете пока он скачает все данные… Останется только переключить его обратно в нормальный режим когда закончите перенос! Вот примеры для MySQL и PostgreSQL.
Настройка DNS
Итак, надеюсь доменное имя у Вас уже куплено - вы должны озаботиться этим заранее… Теперь, когда у нас есть полностью подготовленный сервер, с развернутым сайтом, обновленными данными в базе и прочими ништяками, пришло время представить его миру!
Самый простой шаг - зайти в консоль Вашего регистратора DNS и создать там запись типа А, которая направила бы основное имя вашего домена ( например abcdefg.com) на IP адрес сервера с сайтом.
По хорошему, рекомендуется сделать для его выделенное имя в Вашем домене, например www.abcdefg.com, а abcdefg.com уже направить на это имя с помощью записи типа CNAME.
Еще более удобное и интересное решение- не использовать консоль Вашего регистратора ( в большинстве случаев они увы убогие и неудобные), а делегировать управление Вашим доменом кому нибудь - у любого хостера есть такая услуга, в том числе и у FORNEX. После этого управлять своим доменом ( совсем правильно говорить “своей зоной DNS”) через его консоль. Давайте например я покажу это на примере “abcdefg.com” ( так как я лишь демонстрирую порядок действий, я не буду проводить всю процедуру целиком тк не владею этим доменом. Полный порядок описан в документации по ссылке выше).
Вначале мы добавляем нужный нам домен
И заодно можем сразу выбрать сервер, который будет указан во всех DNS записях, создаваемых по умолчанию. Это избавит нас от необходимости конфигурировать их руками ( только если в будущем мы захотим что-то исправить).
После добавления зайдем в настройки
И убедимся, что все необходимые записи уже сделаны и в целом заданы верно
Однако я бы рекомендовал поправить их вот так
Чтобы в будущем, при очередном переезде Вам пришлось отредактировать на 1 запись меньше.
Успехов Вам и высокого аптайма!
- Log in to post comments
- 6134 reads