Развёртывание простого PHP-приложения с помощью Ansible в Ubuntu 14.04

Данное руководство поможет выполнить оркестровку базового приложения PHP с помощью Ansible.

Примечание: В качестве примера PHP-приложения в руководстве используется фреймворк Laravel. Чтобы развернуть другое приложение, просто откорректируйте код и команды, предложенные в руководстве.

Требования

  • Сервер Ubuntu 14.04 для PHP-приложения (далее – сервер PHP, вместо IP-адреса этой машины используется your_server_ip).
  • Сервер Ubuntu 14.04 для Ansible.(далее – сервер Ansible, все инструкции руководства нужно выполнить именно на этом сервере). Дополнительные нструкции по установке Ansible можно найти здесь.
  • Пользователь с доступом к sudo на каждом сервере (необходимые инструкции по созданию такого пользователя можно найти здесь).
  • SSH-ключи на сервере 2 (чтобы создать такие ключи, выполните это руководство).

1: Установка Ansible

Добавьте PPA-архив Ansible:

sudo apt-add-repository ppa:ansible/ansible

Обновите индекс пакетов:

sudo apt-get update

Чтобы установить Ansible, введите:

sudo apt-get install ansible

После установки нужно создать новый рабочий каталог и выполнить базовую конфигурацию Ansible. По умолчанию Ansible использует файл hosts (/etc/ansible/hosts), в котором хранятся данные о всех поддерживаемых серверах. Этот файл является глобальным, он влияет на работу системы, потому лучше создать отдельный конфигурационный файл.

Создайте локальный файл для настройки хостов в рабочем каталоге.

Сначала создайте рабочий каталог и откройте его:

mkdir ~/ansible-php
cd ~/ansible-php/

Создайте новый файл ansible.cfg и откройте его в текстовом редакторе:

nano ansible.cfg

Добавьте в раздел [defaults] директиву hostfile со значением hosts:

[defaults] hostfile = hosts

Сохраните и закройте ansible.cfg. Теперь нужно создать файл hosts и поместить в него IP-адрес сервера, на котором нужно развернуть PHP-приложение.

nano hosts

Скопируйте и вставьте в файл следующие строки:

your_server_ip ansible_ssh_user=8host

Примечание: Вместо your_server_ip укажите IP сервера PHP, вместо 8host – имя пользователя с доступом к sudo.

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

ansible php -m ping

При этом сервер может предложить заполнить форму SSH для аутентификации хоста. Если всё работает должным образом, команда вернёт:

111.111.111.111 | success >> {
"changed": false,
"ping": "pong"
}

2: Установка зависимостей

Теперь нужно установить и настроить несколько пакетов, которые понадобятся для дальнейшей работы: git, nginx, sqlite3, mcrypt и пару пакетов php5-*.

Для начала создайте базовый плейбук php.yml:

nano php.yml

Добавьте в него следующие настройки. Первые две строки задают группу хостов, которую нужно использовать (в нашем случае php) и запускают команды с sudo. Остальные строки добавляют модуль с необходимыми пакетами. В случае необходимости вы можете откорректировать список пакетов в зависимости от потребностей приложения.

---
- hosts: php
sudo: yes
tasks:
- 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

Сохраните php.yml. Запустите ansible-playbook, чтобы установить эти пакеты на сервер. Добавьте опцию –ask-sudo-pass, если вам нужно ввести пароль пользователя sudo сервера PHP.

ansible-playbook php.yml --ask-sudo-pass

3: Конфигурационные файлы системы

Теперь нужно отредактировать конфигурационные файлы сервера PHP. Важнее всего сейчас настроить опцию cgi.fix_pathinfo в php5-fpm, так как она подвергает сервер опасности.

Сначала рассмотрим все блоки, которые нужно добавить в файл (всё содержимое файла php.yml можно найти в конце раздела).

Модуль lineinfile добавляет в конфигурации нужное значение. Это делается с помощью регулярного выражения.

Также нужно перезапустить php5-fpm и nginx, чтобы обновления вступили в силу. Для этого добавьте два обработчика в раздел handlers. Обработчики запускаются только в том случае, если задача изменяется. Кроме того, они находятся в конце плейбука, потому обработчик запустится всего раз, даже если он используется несколькими задачами одновременно.

Код имеет такой вид:

- name: ensure php5-fpm cgi.fix_pathinfo=0
lineinfile: dest=/etc/php5/fpm/php.ini regexp='^(.*)cgi.fix_pathinfo=' line=cgi.fix_pathinfo=0
notify:
- restart php5-fpm
- restart nginx
handlers:
- name: restart php5-fpm
service: name=php5-fpm state=restarted
- name: restart nginx
service: name=nginx state=restarted

Примечание: Версия Ansible 1.9.1 содержит баг, из-за которого модуль service не может перезапустить php5-fpm.

Команда Ansible работает над исправлением. Пока что вы можете обойти эту проблему, для этого нужно заменить команду service в обработчике restart php5-fpm командой shell.

- name: restart php5-fpm
shell: service php5-fpm restart

После этого нужно включить модуль php5-mcrypt. Для этого запустите сценарий php5enmod с помощью задачи shell и проверьте файл 20-mcrypt.ini. С помощью задачи Ansible создаст файл; если файл существует, задача не будет запущена.

- name: enable php5 mcrypt module
shell: php5enmod mcrypt
args:
creates: /etc/php5/cli/conf.d/20-mcrypt.ini

Откройте php.yml для редактирования:

nano php.yml

Добавьте в файл задачи и обработчики:

---
- hosts: php
sudo: yes
tasks:
- 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
- name: ensure php5-fpm cgi.fix_pathinfo=0
lineinfile: dest=/etc/php5/fpm/php.ini regexp='^(.*)cgi.fix_pathinfo=' line=cgi.fix_pathinfo=0
notify:
- restart php5-fpm
- restart nginx
- name: enable php5 mcrypt module
shell: php5enmod mcrypt
args:
creates: /etc/php5/cli/conf.d/20-mcrypt.ini
handlers:
- name: restart php5-fpm
service: name=php5-fpm state=restarted
- name: restart nginx
service: name=nginx state=restarted

Запустите плейбук:

ansible-playbook php.yml --ask-sudo-pass

Теперь на сервере есть все необходимые пакеты и базовые конфигурации.

4: Клонирование репозитория Laravel

Теперь нужно клонировать фреймворк Laravel на сервер с помощью Git. Как и в предыдущем разделе, сначала мы рассмотрим функции каждого блока кода, а в конце представим полный код файла php.yml.

Прежде чем клонировать репозиторий, нужно создать каталог /var/www. Для этого используется такая задача:

- name: create /var/www/ directory
file: dest=/var/www/ state=directory owner=www-data group=www-data mode=0700

С помощью модуля Git клонируйте репозиторий на сервер. Укажите целевой каталог; строка update=no скажет Ansible не обновлять репозиторий, если он уже существует. В случае с Laravel ссылка на репозиторий git выглядит так: https://github.com/laravel/laravel.git.

Задачу нужно запустить с помощью пользователя www-data, чтобы иметь все привилегии. Просто укажите пользователя с помощью директивы sudo_user.

- name: Clone git repository
git: >
dest=/var/www/laravel
repo=https://github.com/laravel/laravel.git
update=no
sudo: yes
sudo_user: www-data

Примечание: В репозиториях с защитой SSH можно добавить строку accept_hostkey=yes, которая пропустит подтверждение хоста по SSH.

Снова откройте php.yml:

nano php.yml

Добавьте в конец плейбука следующие задачи:

...
- name: enable php5 mcrypt module
shell: php5enmod mcrypt
args:
creates: /etc/php5/cli/conf.d/20-mcrypt.ini
- name: create /var/www/ directory
file: dest=/var/www/ state=directory owner=www-data group=www-data mode=0700
- name: Clone git repository
git: >
dest=/var/www/laravel
repo=https://github.com/laravel/laravel.git
update=no
sudo: yes
sudo_user: www-data
handlers:
- name: restart php5-fpm
service: name=php5-fpm state=restarted
- name: restart nginx
service: name=nginx state=restarted

Сохраните и закройте плейбук. Затем запустите его:

ansible-playbook php.yml --ask-sudo-pass

5: Установка приложения с помощью Composer

С помощью инструмента Composer установите PHP-приложение и его зависимости.

Composer предоставляет команду create-project, которая устанавливает все необходимые зависимости и выполняет все действия, описанные в разделе post-create-project-cmd файла composer.json. Это обеспечивает правильную настройку приложения.

Чтобы загрузить Composer в /usr/local/bin/composer, используйте следующую задачу Ansible.

- name: install composer
shell: curl -sS https://getcomposer.org/installer | php -- --install-dir=/usr/local/bin --filename=composer
args:
creates: /usr/local/bin/composer

После установки Composer появляется доступ к его модулям. В данном случае нужно указать, где находится проект (с помощью параметра working_dir), а затем запустить команду create-project как пользователь www-data.

- name: composer create-project
composer: command=create-project working_dir=/var/www/laravel optimize_autoloader=no
sudo: yes
sudo_user: www-data

Примечание: Задача create-project может занять много времени на свежем сервере, поскольку Composer не сможет использовать кэш файлов и будет загружать всё необходимое самостоятельно.

Откройте php.yml:

nano php.yml

В конец плейбука (раздел tasks, перед handlers) добавьте следующие задачи:

...
- name: Clone git repository
git: >
dest=/var/www/laravel
repo=https://github.com/laravel/laravel.git
update=no
sudo: yes
sudo_user: www-data
- name: install composer
shell: curl -sS https://getcomposer.org/installer | php -- --install-dir=/usr/local/bin --filename=composer
args:
creates: /usr/local/bin/composer
- name: composer create-project
composer: command=create-project working_dir=/var/www/laravel optimize_autoloader=no
sudo: yes
sudo_user: www-data
handlers:
- name: restart php5-fpm
service: name=php5-fpm state=restarted
- name: restart nginx
service: name=nginx state=restarted

Запустите плейбук:

ansible-playbook php.yml --ask-sudo-pass

Если сейчас вы снова запустите Ansible, это опять запустит команду composer create-project, Laravel получит новый APP_KEY. Нужно сделать так, чтобы эта задача запускалась только после свежего клонирования. Для этого зарегистрируйте переменную с результатом задачи git clone и проверьте этот результат в задаче composer create-project. Итак, если задача git clone изменилась. Программа запустит задачу composer create-project; если изменений не произошло, эта задача будет пропущена.

Примечание: Модуль composer в некоторых версиях Ansible содержит баг, который выдаёт OK вместо Changed, так как он игнорирует выполненные скрипты, даже если не было установлено никаких зависимостей.

Откройте файл php.yml:

nano php.yml

Найдите задачу git clone. Добавьте опцию register, которая будет сохранять результаты этой задачи в переменной cloned:

- name: Clone git repository
git: >
dest=/var/www/laravel
repo=https://github.com/laravel/laravel.git
update=no
sudo: yes
sudo_user: www-data
register: cloned

Найдите задачу composer create-project. Добавьте опцию when, которая проверяет изменения переменной cloned.

- name: composer create-project
composer: command=create-project working_dir=/var/www/laravel optimize_autoloader=no
sudo: yes
sudo_user: www-data
when: cloned|changed

Запустите плейбук:

ansible-playbook php.yml --ask-sudo-pass

Теперь Composer не будет изменять APP_KEY после каждого запуска.

6: Обновление переменных окружения

Теперь нужно обновить переменные окружения приложения.

Laravel предоставляет стандартный файл .env, который задаёт APP_ENV значение local, а APP_DEBUG – значение true. Их нужно изменить на production и false соответственно.

Для этого можно использовать модуль lineinfile в следующих задачах:

- name: set APP_DEBUG=false
lineinfile: dest=/var/www/laravel/.env regexp='^APP_DEBUG=' line=APP_DEBUG=false
- name: set APP_ENV=production
lineinfile: dest=/var/www/laravel/.env regexp='^APP_ENV=' line=APP_ENV=production

Откройте php.yml.

nano php.yml

Добавьте в конец плейбука такие задачи:

...
- name: composer create-project
composer: command=create-project working_dir=/var/www/laravel optimize_autoloader=no
sudo: yes
sudo_user: www-data
when: cloned|changed
- name: set APP_DEBUG=false
lineinfile: dest=/var/www/laravel/.env regexp='^APP_DEBUG=' line=APP_DEBUG=false
- name: set APP_ENV=production
lineinfile: dest=/var/www/laravel/.env regexp='^APP_ENV=' line=APP_ENV=production
handlers:
- name: restart php5-fpm
service: name=php5-fpm state=restarted
- name: restart nginx
service: name=nginx state=restarted

Сохраните и запустите файл:

ansible-playbook php.yml --ask-sudo-pass

Модуль lineinfile задаст переменным среды правильные значения.

7: Настройка Nginx

Теперь нужно настроить Nginx для обслуживания приложения PHP.

Откройте в браузере ссылку http://your_server_ip/, чтобы получить доступ к серверу. Вместо страницы приложения Laravel на экране появится стандартная страница Nginx. Это значит, что на данный момент Nginx не поддерживает приложение из каталога /var/www/laravel/public. Чтобы исправить это, откройте каталог конфигураций Nginx и добавьте поддержку php-fpm.

Создайте файл nginx.conf:

nano nginx.conf

Добавьте в этот файл следующий блок server. Данные настройки определяют каталог Laravel и задают имя хоста, которое будет использовать Nginx (и которое было указано в файле hosts как server_name переменной inventory_hostname).

server {
listen 80 default_server;
listen [::]:80 default_server ipv6only=on;
root /var/www/laravel/public;
index index.php index.html index.htm;
server_name {{ inventory_hostname }};
location / {
try_files $uri $uri/ =404;
}
error_page 404 /404.html;
error_page 500 502 503 504 /50x.html;
location = /50x.html {
root /var/www/laravel/public;
}
location ~ \.php$ {
try_files $uri =404;
fastcgi_split_path_info ^(.+\.php)(/.+)$;
fastcgi_pass unix:/var/run/php5-fpm.sock;
fastcgi_index index.php;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
include fastcgi_params;
}
}

Сохраните и закройте nginx.conf.

Используйте модуль template, чтобы передать новые конфигурации. Модуль template похож на модуль copy, но между ними есть одно большое различие. Модуль copy просто копирует один или несколько файлов, не внося в них никаких изменений, а модуль template копирует файлы и определяет в них все переменные. Поскольку в конфигурационном файле используется {{ inventory_hostname }}, модуль template определит IP-адрес, который был использован в файле hosts. Таким образом, конфигурационные файлы Ansible не придётся жёстко кодировать.

Однако, при написании задач всегда следует продумать, что в таком случае произойдёт на сервере. Поскольку настройки Nginx изменятся, нужно перезапустить Nginx и php-fpm с помощью опции notify.

- name: Configure nginx
template: src=nginx.conf dest=/etc/nginx/sites-available/default
notify:
- restart php5-fpm
- restart nginx

Откройте php.yml:

nano php.yml

Добавьте следующую задачу nginx в конец раздела tasks. В результате файл php.yml будет иметь такой вид:

---
- hosts: php
sudo: yes
tasks:
- 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
- name: ensure php5-fpm cgi.fix_pathinfo=0
lineinfile: dest=/etc/php5/fpm/php.ini regexp='^(.*)cgi.fix_pathinfo=' line=cgi.fix_pathinfo=0
notify:
- restart php5-fpm
- restart nginx
- name: enable php5 mcrypt module
shell: php5enmod mcrypt
args:
creates: /etc/php5/cli/conf.d/20-mcrypt.ini
- name: create /var/www/ directory
file: dest=/var/www/ state=directory owner=www-data group=www-data mode=0700
- name: Clone git repository
git: >
dest=/var/www/laravel
repo=https://github.com/laravel/laravel.git
update=no
sudo: yes
sudo_user: www-data
register: cloned
- name: install composer
shell: curl -sS https://getcomposer.org/installer | php -- --install-dir=/usr/local/bin --filename=composer
args:
creates: /usr/local/bin/composer
- name: composer create-project
composer: command=create-project working_dir=/var/www/laravel optimize_autoloader=no
sudo: yes
sudo_user: www-data
when: cloned|changed
- name: set APP_DEBUG=false
lineinfile: dest=/var/www/laravel/.env regexp='^APP_DEBUG=' line=APP_DEBUG=false
- name: set APP_ENV=production
lineinfile: dest=/var/www/laravel/.env regexp='^APP_ENV=' line=APP_ENV=production
- name: Configure nginx
template: src=nginx.conf dest=/etc/nginx/sites-available/default
notify:
- restart php5-fpm
- restart nginx
handlers:
- name: restart php5-fpm
service: name=php5-fpm state=restarted
- name: restart nginx
service: name=nginx state=restarted

Сохраните и запустите плейбук.

ansible-playbook php.yml --ask-sudo-pass

Теперь вернитесь в браузер и обновите страницу. На экране должна появиться страница нового проекта Laravel.

Заключение

Теперь вы умеете писать плейбуки Ansible для развёртывания простого приложения PHP.

Все проблемы с аутентификацией помогут устранить ключи SSH. Создайте пару ключей и установите их в репозиторий. Затем используйте Ansible, чтобы скопировать и настроить их на сервере перед запуском git clone.

- name: create /var/www/.ssh/ directory
file: dest=/var/www/.ssh/ state=directory owner=www-data group=www-data mode=0700
- name: copy private ssh key
copy: src=deploykey_rsa dest=/var/www/.ssh/id_rsa owner=www-data group=www-data mode=0600

Так сервер сможет пройти аутентификацию и развернуть приложение.

Tags: , , , , ,

Добавить комментарий