Вступление
Это руководство является вторым в серии о развертывании приложений PHP с использованием Ansible в Ubuntu 14.04. Https://www.digitalocean.com/community/tutorials/how-to-deploy-a-basic-php-application-using-ansible-on-ubuntu-14-04[first учебник] охватывает основные шаги для развертывания приложение, и является отправной точкой для шагов, описанных в этом руководстве.
В этом руководстве мы рассмотрим настройку ключей SSH для поддержки средств развертывания / публикации кода, настройку брандмауэра системы, подготовку и настройку базы данных (включая пароль!), А также настройку планировщиков задач (crons) и демонов очереди. Цель этого учебного пособия - получить полностью работающий сервер приложений PHP с вышеупомянутой расширенной конфигурацией.
Как и в предыдущем уроке, мы будем использовать Laravel framework в качестве нашего примера PHP-приложения. Тем не менее, эти инструкции могут быть легко изменены для поддержки других платформ и приложений, если у вас уже есть свои собственные.
Предпосылки
Это руководство следует непосредственно из конца the первый учебник в серии, а также все настройки и файлы, сгенерированные для этого учебника. Если вы еще не завершили этот учебник, пожалуйста, сначала сделайте это, прежде чем продолжить этот учебник.
Шаг 1 - Переключение хранилища приложений
На этом шаге мы обновим репозиторий Git до слегка настроенного репозитория примеров.
Поскольку для установки по умолчанию Laravel не требуются расширенные функции, которые мы будем настраивать в этом руководстве, мы будем переключать существующее хранилище из стандартного хранилища на примерное хранилище с добавлением некоторого кода отладки, просто чтобы показать, когда что-то работает , Репозиторий, который мы будем использовать, находится по адресу + https: // github.com / do-community / do-ansible-adv-php +
.
Если вы этого еще не сделали, замените каталоги на + ansible-php +
из предыдущего урока.
cd ~/ansible-php/
Откройте нашу существующую книгу для редактирования.
nano php.yml
Найдите и обновите задачу «Clone git repository», чтобы она выглядела следующим образом.
Обновлено Ansible задача
- name: Clone git repository
git: >
dest=/var/www/laravel
repo=
update=
sudo: yes
sudo_user: www-data
register: cloned
Сохраните и запустите playbook.
ansible-playbook php.yml --ask-sudo-pass
Когда он завершит работу, зайдите на свой сервер в веб-браузере (т.е. + Http: /// +
). Вы должны увидеть сообщение «Не удалось найти драйвер» *.
Это означает, что мы успешно заменили хранилище по умолчанию для нашего примера хранилища, но приложение не может подключиться к базе данных. Это то, что мы ожидаем увидеть здесь, и мы установим и настроим базу данных позже в этом руководстве.
Шаг 2 - Настройка ключей SSH для развертывания
На этом этапе мы настроим ключи SSH, которые можно использовать для сценариев развертывания кода приложения.
Хотя Ansible отлично подходит для поддержки конфигурации и настройки серверов и приложений, часто используются такие инструменты, как Envoy и Rocketeer. перенести изменения кода на ваш сервер и запустить команды приложения удаленно. Большинству этих инструментов требуется соединение SSH, которое может напрямую обращаться к установке приложения. В нашем случае это означает, что нам нужно настроить ключи SSH для пользователя + www-data
.
Нам понадобится файл открытого ключа для пользователя, от которого вы хотите отправить свой код. Этот файл обычно находится в + ~ / .ssh / id_rsa.pub +
. Скопируйте этот файл в каталог + ansible-php +
.
cp ~/.ssh/id_rsa.pub ~/ansible-php/deploykey.pub
Мы можем использовать модуль Ansible + authorized_key +
, чтобы установить наш открытый ключ в + / var / www / .ssh / авторизованный_keys +
, что позволит инструментам развертывания подключаться и получать доступ к нашему приложению. Конфигурация должна знать только, где находится ключ, используя поиск, и для пользователя должен быть установлен ключ (в нашем случае + www-data +
).
Новое Ansible задание
- name: Copy public key into /var/www
authorized_key: user=www-data key="{{ lookup('file', 'deploykey.pub') }}"
Нам также нужно установить пользовательскую оболочку + www-data
, чтобы мы могли войти в систему. В противном случае SSH разрешит соединение, но оболочка не будет представлена пользователю. Это можно сделать с помощью модуля + user
и установки оболочки на` + / bin / bash` (или предпочитаемую вами оболочку).
Новое Ansible задание
- name: Set www-data user shell
user: name=www-data shell=/bin/bash
Теперь откройте книгу для редактирования, чтобы добавить новые задания.
nano php.yml
Добавьте вышеперечисленные задачи в вашу + php.yml +
playbook; конец файла должен соответствовать следующему. Дополнения выделены красным.
Обновлен php.yml
. . .
- name: Configure nginx
template: src=nginx.conf dest=/etc/nginx/sites-available/default
notify:
- restart php5-fpm
- restart nginx
handlers:
. . .
Сохраните и запустите playbook.
ansible-playbook php.yml --ask-sudo-pass
Когда Ansible завершит работу, вы сможете использовать SSH с пользователем + www-data
.
ssh www-data@
Если вы успешно вошли в систему, это работает! Теперь вы можете выйти из системы, введя + logout +
или нажав * CTRL + D *.
Нам не нужно будет использовать это соединение для каких-либо других шагов в этом руководстве, но будет полезно, если вы настраиваете другие инструменты, как указано выше, или для общей отладки и обслуживания приложений по мере необходимости.
Шаг 3 - Настройка брандмауэра
На этом этапе мы настроим брандмауэр на сервере, чтобы разрешить только соединения для HTTP и SSH.
Ubuntu 14.04 поставляется с UFW (Uncomplicated Firewall), установленным по умолчанию, и Ansible поддерживает его с модулем + ufw +. Он имеет ряд мощных функций и был разработан так, чтобы быть максимально простым. Он идеально подходит для автономных веб-серверов, которым нужно открыть только пару портов. В нашем случае мы хотим, чтобы порт 80 (HTTP) и порт 22 (SSH) были открыты. Вы можете также хотеть порт 443 для HTTPS.
Модуль + ufw +
имеет несколько различных опций, которые выполняют разные задачи. Различные задачи, которые нам нужно выполнить:
-
Включить UFW и запретить весь входящий трафик по умолчанию.
-
Откройте порт SSH, но ограничьте скорость, чтобы предотвратить атаки методом перебора.
-
Откройте порт HTTP.
Это можно сделать с помощью следующих задач, соответственно.
Новые Ansible задачи
- name: Enable UFW
ufw: direction=incoming policy=deny state=enabled
- name: UFW limit SSH
ufw: rule=limit port=ssh
- name: UFW open HTTP
ufw: rule=allow port=http
Как и прежде, откройте файл + php.yml +
для редактирования.
nano php.yml
Добавьте вышеупомянутые задачи в playbook; конец файла должен соответствовать следующему.
Обновлен php.yml
. . .
- name: Copy public key into /var/www
authorized_key: user=www-data key="{{ lookup('file', 'deploykey.pub') }}"
- name: Set www-data user shell
user: name=www-data shell=/bin/bash
handlers:
. . .
Сохраните и запустите playbook.
ansible-playbook php.yml --ask-sudo-pass
Когда это успешно завершится, вы все равно сможете подключиться через SSH (используя Ansible) или HTTP к вашему серверу; другие порты теперь будут заблокированы.
Вы можете проверить состояние UFW в любое время, выполнив эту команду:
ansible php --sudo --ask-sudo-pass -m shell -a "ufw status verbose"
Разбиваем команду Ansible выше:
-
+ ansible +
: запустить необработанное задание Ansible без книги воспроизведения. -
+ php
: запустить задачу против хостов в этой группе. -
+ - sudo
: Запустите команду как` + sudo`. -
+ - ask-sudo-pass +
: запрашивать пароль+ sudo +
. -
+ -m shell
: запустить модуль` + shell`. -
+ -a" ufw status verbose "+
: опции для передачи в модуль. Поскольку это команда+ shell +
, мы передаем необработанную команду (т.е.+ ufw status verbose
) прямо без каких-либо опций` + key = value`.
Это должно вернуть что-то вроде этого.
Вывод состояния UFW
| success | rc=0 >>
Status: active
Logging: on (low)
Default: deny (incoming), allow (outgoing), disabled (routed)
New profiles: skip
To Action From
-- ------ ----
22 LIMIT IN Anywhere
80 ALLOW IN Anywhere
22 (v6) LIMIT IN Anywhere (v6)
80 (v6) ALLOW IN Anywhere (v6)
Шаг 4 - Установка пакетов MySQL
На этом шаге мы настроим базу данных MySQL для нашего приложения.
Первый шаг - убедиться, что MySQL установлен на нашем сервере, просто добавив необходимые пакеты в задачу установки пакетов в верхней части нашей книги игр. Нам нужны следующие пакеты: + mysql-server
,` + mysql-client` и + php5-mysql
. Нам также понадобится + python-mysqldb +
, чтобы Ansible мог взаимодействовать с MySQL.
Когда мы добавляем пакеты, нам нужно перезапустить + nginx +
и + php5-fpm +
, чтобы новые приложения могли использоваться приложением. В этом случае нам нужно, чтобы MySQL был доступен для PHP, чтобы он мог подключаться к базе данных.
Одна из замечательных особенностей Ansible - это то, что вы можете изменить любое из заданий и повторно запустить вашу книгу игр, и изменения будут применены. Это включает в себя списки опций, как у нас с задачей + apt +
.
Как и прежде, откройте файл + php.yml +
для редактирования.
nano php.yml
Найдите задачу + install packages +
и обновите ее, чтобы включить указанные выше пакеты:
Обновлен php.yml
. . .
- name: install packages
apt: name={{ item }} update_cache=yes state=latest
with_items:
- git
- mcrypt
- nginx
- php5-cli
- php5-curl
- php5-fpm
- php5-intl
- php5-json
- php5-mcrypt
- php5-sqlite
- sqlite3
. . .
Сохраните и запустите playbook:
ansible-playbook php.yml --ask-sudo-pass
Шаг 5 - Настройка базы данных MySQL
На этом этапе мы создадим базу данных MySQL для нашего приложения.
Ansible может напрямую общаться с MySQL, используя предустановленные модули + mysql_ +
(например, + mysql_db +
, + mysql_user +
). Модуль + mysql_db +
обеспечивает способ обеспечения существования базы данных с определенным именем, поэтому мы можем использовать такую задачу для создания базы данных.
Новое Ansible задание
- name: Create MySQL DB
mysql_db: name=laravel state=present
Нам также нужна действующая учетная запись пользователя с известным паролем, чтобы наше приложение могло подключаться к базе данных. Один из подходов к этому состоит в том, чтобы сгенерировать пароль локально и сохранить его в нашей книге игр Ansible, но это небезопасно и существует лучший способ.
Мы сгенерируем пароль с помощью Ansible на самом сервере и будем использовать его там, где это необходимо. Чтобы сгенерировать пароль, мы будем использовать инструмент командной строки + makepasswd +
и запросим пароль из 32 символов. Поскольку + makepasswd +
не используется по умолчанию в Ubuntu, нам нужно добавить это и в список пакетов.
Мы также сообщим Ansible запомнить результат команды (т.е. пароль), поэтому мы можем использовать его позже в нашей книге. Однако, поскольку Ansible не знает, выполнил ли он уже команду + shell +
, мы также создадим файл при запуске этой команды. Ansible проверит, существует ли файл, и если это так, он предположит, что команда уже была выполнена, и больше не будет ее запускать.
Задача выглядит так:
Новое Ansible задание
- name: Generate DB password
shell: makepasswd --chars=32
args:
creates: /var/www/laravel/.dbpw
register: dbpwd
Далее нам нужно создать фактического пользователя базы данных MySQL с указанным паролем. Это делается с помощью модуля + mysql_user +
, и мы можем использовать опцию + stdout +
для переменной, которую мы определили в задаче генерации пароля, чтобы получить необработанный вывод команды оболочки, например: + dbpwd.stdout +
,
Команда + mysql_user +
принимает имя пользователя и необходимые привилегии. В нашем случае мы хотим создать пользователя с именем + laravel +
и предоставить ему полные привилегии для таблицы + laravel +
. Нам также нужно указать, чтобы задача запускалась только тогда, когда переменная + dbpwd +
имеет changed, что будет только тогда, когда будет запущена задача генерации пароля.
Задача должна выглядеть так:
Новое Ansible задание
- name: Create MySQL User
mysql_user: name=laravel password={{ dbpwd.stdout }} priv=laravel.*:ALL state=present
when: dbpwd.changed
Собрав все это вместе, откройте файл + php.yml +
для редактирования, чтобы мы могли добавить вышеуказанные задачи.
nano php.yml
Во-первых, найдите задачу + install packages +
и обновите ее, чтобы включить пакет + makepasswd +
.
Обновлен php.yml
. . .
- name: install packages
apt: name={{ item }} update_cache=yes state=latest
with_items:
- git
- mcrypt
- nginx
- php5-cli
- php5-curl
- php5-fpm
- php5-intl
- php5-json
- php5-mcrypt
- php5-sqlite
- sqlite3
- mysql-server
- mysql-client
- php5-mysql
- python-mysqldb
notify:
- restart php5-fpm
- restart nginx
. . .
Затем добавьте генерацию пароля, создание базы данных MySQL и задачи создания пользователя внизу.
Обновлен php.yml
. . .
- name: UFW limit SSH
ufw: rule=limit port=ssh
- name: UFW open HTTP
ufw: rule=allow port=http
handlers:
. . .
-
Пока не запускайте playbook! * Возможно, вы заметили, что, хотя мы создали пользователя и базу данных MySQL, мы ничего не сделали с паролем. Мы рассмотрим это на следующем шаге. При использовании задач
+ shell +
в Ansible всегда важно не забывать завершать весь рабочий процесс, связанный с выводом / результатами задачи, прежде чем запускать ее, чтобы избежать необходимости вручную входить в систему и сбрасывать состояние.
Шаг 6 - Настройка приложения PHP для базы данных
На этом этапе мы сохраним пароль базы данных MySQL в файле + .env +
для приложения.
Как мы это делали в предыдущем уроке, мы обновим файл + .env +
, чтобы включить в него вновь созданные учетные данные базы данных. По умолчанию файл Laravel + .env +
содержит следующие строки:
Laravel .env file
DB_HOST=localhost
DB_DATABASE=homestead
DB_USERNAME=homestead
DB_PASSWORD=secret
Мы можем оставить строку + DB_HOST +
как есть, но обновим остальные три, используя следующие задачи, которые очень похожи на задачи, которые мы использовали в предыдущем уроке для установки + APP_ENV +
и + APP_DEBUG +
.
Новые Ansible задачи
- name: set DB_DATABASE
lineinfile: dest=/var/www/laravel/.env regexp='^DB_DATABASE=' line=DB_DATABASE=laravel
- name: set DB_USERNAME
lineinfile: dest=/var/www/laravel/.env regexp='^DB_USERNAME=' line=DB_USERNAME=laravel
- name: set DB_PASSWORD
lineinfile: dest=/var/www/laravel/.env regexp='^DB_PASSWORD=' line=DB_PASSWORD={{ dbpwd.stdout }}
when: dbpwd.changed
Как и в случае с задачей создания пользователя MySQL, мы использовали сгенерированную переменную пароля (+ dbpwd.stdout +
), чтобы заполнить файл паролем, и добавили опцию + when +
, чтобы гарантировать, что он запускается только когда ` + dbpwd + `изменился.
Теперь, поскольку файл + .env +
уже существовал до того, как мы добавили задачу генерации пароля, нам нужно сохранить пароль в другом файле. Задача генерации может искать существование этого файла (который мы уже настроили в задаче). Мы также будем использовать опции + sudo +
и + sudo_user +
, чтобы сообщить Ansible, что нужно создать файл как + www-data +
.
Новое Ansible задание
- name: Save dbpw file
lineinfile: dest=/var/www/laravel/.dbpw line="{{ dbpwd.stdout }}" create=yes state=present
sudo: yes
sudo_user: www-data
when: dbpwd.changed
Откройте файл + php.yml +
для редактирования.
nano php.yml
Добавьте вышеупомянутые задачи в playbook; конец файла должен соответствовать следующему.
Обновлен php.yml
. . .
- name: Create MySQL User
mysql_user: name=laravel password={{ dbpwd.stdout }} priv=laravel.*:ALL state=present
when: dbpwd.changed
handlers:
. . .
-
Опять же, пока не запускайте playbook! * У нас есть еще один шаг, прежде чем мы сможем запустить playbook.
Шаг 7 - Миграция базы данных
На этом шаге мы запустим миграцию базы данных, чтобы настроить таблицы базы данных.
В Laravel это делается с помощью команды + migrate +
(т.е. + php artisan migrate --force +
) в каталоге Laravel. Обратите внимание, что мы добавили флаг + - force
, потому что этого требует среда` + production`.
Задача Ansible для выполнения этого выглядит следующим образом.
Новое Ansible задание
- name: Run artisan migrate
shell: php /var/www/laravel/artisan migrate --force
sudo: yes
sudo_user: www-data
when: dbpwd.changed
Теперь пришло время обновить наш playbook. Откройте файл + php.yml +
для редактирования.
nano php.yml
Добавьте вышеупомянутые задачи в playbook; конец файла должен соответствовать следующему.
Обновлен php.yml
. . .
- name: Save dbpw file
lineinfile: dest=/var/www/laravel/.dbpw line="{{ dbpwd.stdout }}" create=yes state=present
sudo: yes
sudo_user: www-data
when: dbpwd.changed
handlers:
. . .
Наконец, мы можем сохранить и запустить playbook.
ansible-playbook php.yml --ask-sudo-pass
Когда это закончится, обновите страницу в вашем браузере, и вы должны увидеть сообщение:
your_server_ip /»> Http: ///
Queue: NO
Cron: NO
Это означает, что база данных настроена правильно и работает должным образом, но мы еще не настроили задачи cron или демон очереди.
Шаг 8 - Настройка задач cron
На этом шаге мы настроим любые задачи cron, которые необходимо настроить.
Задачи Cron - это команды, которые запускаются по заданному расписанию и могут использоваться для выполнения любого количества задач для вашего приложения, таких как выполнение задач обслуживания или рассылка обновлений активности электронной почты - по сути, всего, что необходимо делать периодически без вмешательства пользователя вручную. Задачи Cron могут выполняться так часто, как каждую минуту, или так редко, как вам требуется.
Laravel поставляется с командой Artisan под названием + schedule: run +
по умолчанию, которая предназначена для запуска каждую минуту и выполняет определенные запланированные задачи в приложении. Это означает, что нам нужно добавить только одну задачу cron, если наше приложение использует эту функцию.
Ansible имеет модуль + cron +
с рядом различных опций, которые переводят непосредственно в разные опции, которые вы можете настроить через cron:
-
+ job +
: команда для выполнения. Требуется, если состояние = присутствует. -
«+ минута», «+ час», «+ день», «+ месяц» и «+ день недели +»: минута, час, день, месяц или день недели, когда должно выполняться задание, соответственно.
-
+ special_time +
(+ перезагрузка +
,+ ежегодно +
,+ ежегодно +
,+ ежемесячно +
,+ еженедельно +
,+ ежедневно +
,+ ежечасно +
): псевдоним для указания специального времени.
По умолчанию он создает задачу, которая запускается каждую минуту, чего мы и хотим. Это означает, что задача, которую мы хотим, выглядит следующим образом:
Новое Ansible задание
- name: Laravel Scheduler
cron: >
job="run-one php /var/www/laravel/artisan schedule:run 1>> /dev/null 2>&1"
state=present
user=www-data
name="php artisan schedule:run"
Команда + run-one +
- это небольшой помощник в Ubuntu, который обеспечивает запуск команды только один раз. Это означает, что если предыдущая команда + schedule: run +
все еще выполняется, она больше не будет выполняться. Это полезно, чтобы избежать ситуации, когда задача cron блокируется в цикле, и со временем все больше и больше экземпляров одной и той же задачи запускаются до тех пор, пока на сервере не закончатся ресурсы.
Как и прежде, откройте файл + php.yml +
для редактирования.
nano php.yml
Добавьте вышеупомянутое задание в playbook; конец файла должен соответствовать следующему.
Обновлен php.yml
. . .
- name: Run artisan migrate
shell: php /var/www/laravel/artisan migrate --force
sudo: yes
sudo_user: www-data
when: dbpwd.changed
handlers:
. . .
Сохраните и запустите playbook:
ansible-playbook php.yml --ask-sudo-pass
Теперь обновите страницу в вашем браузере. Через минуту он обновится, чтобы выглядеть так.
your_server_ip /»> Http: ///
Queue: NO
Cron:
Это означает, что cron работает в фоновом режиме правильно. В качестве части примера приложения есть задание cron, которое выполняется каждую минуту, обновляя запись состояния в базе данных, чтобы приложение знало, что оно выполняется.
Шаг 9 - Настройка демона очереди
Как и команда Artisan + schedule: run +
из шага 8, Laravel также поставляется с работником очереди, который можно запустить с помощью команды Artisan + queue: work --daemon +
. На этом шаге мы настроим работника демона очереди для Laravel.
Работники очереди похожи на задания cron в том, что они выполняют задачи в фоновом режиме. Разница заключается в том, что приложение помещает задания в очередь либо посредством действий, выполняемых пользователем, либо из задач, запланированных с помощью задания cron. Задачи очереди выполняются рабочим по одной за раз и будут обрабатываться по требованию, когда они будут найдены в очереди. Задачи очереди обычно используются для работы, для выполнения которой требуется время, например для отправки электронных писем или выполнения вызовов API для внешних служб.
В отличие от команды + schedule: run +
, это не та команда, которую нужно запускать каждую минуту. Вместо этого он должен постоянно работать в фоновом режиме. Обычный способ сделать это - использовать сторонний пакет, такой как supervisord, но этот метод требует понимания того, как настроить и управлять указанной системой. Есть гораздо более простой способ реализовать это с помощью cron и команды + run-one +
.
Мы создадим запись в cron для запуска рабочего демона очереди и используем + run-one +
для его запуска. Это означает, что cron запустит процесс при первом запуске, и любые последующие запуски cron будут игнорироваться + run-one +
во время работы работника. Как только работник остановится, + run-one +
позволит команде выполнить снова, и работник очереди снова запустится. Это невероятно простой и простой в использовании метод, который избавляет вас от необходимости изучать, как настроить и использовать другой инструмент.
Учитывая все это, мы создадим еще одну задачу cron для запуска нашего работника очереди.
Новое Ansible задание
- name: Laravel Queue Worker
cron: >
job="run-one php /var/www/laravel/artisan queue:work --daemon --sleep=30 --delay=60 --tries=3 1>> /dev/null 2>&1"
state=present
user=www-data
name="Laravel Queue Worker"
Как и прежде, откройте файл + php.yml +
для редактирования.
nano php.yml
Добавьте вышеупомянутое задание в playbook; конец файла должен соответствовать следующему:
Обновлен php.yml
. . .
- name: Laravel Scheduler
cron: >
job="run-one php /var/www/laravel/artisan schedule:run 1>> /dev/null 2>&1"
state=present
user=www-data
name="php artisan schedule:run"
handlers:
. . .
Сохраните и запустите playbook:
ansible-playbook php.yml --ask-sudo-pass
Как и раньше, обновите страницу в своем браузере. Через минуту он обновится и будет выглядеть так:
your_server_ip /»> Http: ///
Queue:
Cron: YES
Это означает, что работник очереди корректно работает в фоновом режиме. Задание cron, которое мы начали на последнем шаге, помещает задание в очередь. Это задание обновляет базу данных при ее запуске, чтобы показать, что она работает.
Теперь у нас есть рабочий пример приложения Laravel, который включает в себя работающие cron-задания и очереди.
Заключение
В этом руководстве рассматриваются некоторые более сложные темы при использовании Ansible для развертывания приложений PHP. Все используемые задачи могут быть легко изменены в соответствии с большинством приложений PHP (в зависимости от их конкретных требований), и это должно дать вам хорошую отправную точку для создания собственных приложений для ваших приложений.
Мы не использовали ни одной SSH-команды как часть этого руководства (кроме проверки входа пользователя в систему + www-data +
), и все, включая пароль пользователя MySQL, было настроено автоматически. После выполнения этого руководства ваше приложение готово к работе и поддерживает инструменты для принудительного обновления кода.