Автоматизация развёртывания LAMP-стека с помощью Ansible
Пошаговое руководство по автоматизации развёртывания LAMP-стека с помощью Ansible. Роли, шаблоны, секреты и production-ready практики.
Автоматизация развёртывания LAMP-стека с помощью Ansible
Современная инфраструктура требует воспроизводимости и скорости развёртывания. Ручная настройка серверов — источник ошибок и дрейфа конфигураций. Ansible, как агентлесс-система управления конфигурациями, идеально подходит для автоматизации рутинных задач. В этой статье мы рассмотрим создание playbook для развёртывания LAMP-стека (Linux, Apache, MySQL, PHP) на серверах под управлением RHEL/CentOS и Debian/Ubuntu.
Архитектура решения
Мы будем использовать роли для модульности:
common: базовые настройки безопасности и времениapache: установка и настройка веб-сервераmysql: установка СУБД и создание базыphp: установка интерпретатора и модулей
Inventory
Файл inventory/prod.yml:
all:
hosts:
webserver01:
ansible_host: 192.168.10.10
ansible_user: deploy
webserver02:
ansible_host: 192.168.10.11
ansible_user: deploy
vars:
ansible_become: true
php_version: '8.2'
mysql_root_password: !vault |
$ANSIBLE_VAULT;1.1;AES256
38376238313534323039373831313033383435313732363433353839303132343637383930313234
353637383930313234353637383930313234353637383930
Playbook: site.yml
---
- name: Deploy LAMP stack
hosts: all
vars_files:
- vars/secrets.yml
roles:
- common
- apache
- mysql
- php
Роль: common
roles/common/tasks/main.yml:
---
- name: Set timezone to UTC
timezone:
name: UTC
- name: Install basic packages
package:
name:
- vim
- wget
- curl
- git
- htop
state: present
- name: Ensure firewalld is running (RHEL)
ansible.builtin.service:
name: firewalld
state: started
enabled: true
when: ansible_facts.os_family == 'RedHat'
- name: Open HTTP/HTTPS ports
ansible.posix.firewalld:
service: "{{ item }}"
permanent: true
state: enabled
immediate: true
loop:
- http
- https
when: ansible_facts.os_family == 'RedHat'
Роль: apache
roles/apache/tasks/main.yml:
---
- name: Install Apache (RHEL)
package:
name: httpd
state: present
when: ansible_facts.os_family == 'RedHat'
- name: Install Apache (Debian)
package:
name: apache2
state: present
when: ansible_facts.os_family == 'Debian'
- name: Start and enable Apache
service:
name: "{{ 'httpd' if ansible_facts.os_family == 'RedHat' else 'apache2' }}"
state: started
enabled: true
- name: Deploy virtual host
template:
src: vhost.conf.j2
dest: "{{ '/etc/httpd/conf.d/' if ansible_facts.os_family == 'RedHat' else '/etc/apache2/sites-available/' }}{{ inventory_hostname }}.conf"
notify: Restart Apache
Роль: mysql
roles/mysql/tasks/main.yml:
---
- name: Install MySQL server (RHEL)
package:
name: mysql-server
state: present
when: ansible_facts.os_family == 'RedHat'
- name: Install MariaDB (Debian)
package:
name: mariadb-server
state: present
when: ansible_facts.os_family == 'Debian'
- name: Start и enable MySQL
service:
name: mysqld if ansible_facts.os_family == 'RedHat' else mysql
state: started
enabled: true
- name: Set root password
mysql_user:
name: root
password: "{{ mysql_root_password }}"
host_all: true
check_implicit_admin: true
- name: Create application database
mysql_db:
name: app_db
state: present
encoding: utf8mb4
collation: utf8mb4_unicode_ci
- name: Create DB user
mysql_user:
name: app_user
password: "{{ mysql_app_password }}"
priv: 'app_db.*:ALL'
state: present
Роль: php
roles/php/tasks/main.yml:
---
- name: Install PHP и modules (RHEL)
package:
name:
- php
- php-mysqlnd
- php-gd
- php-xml
- php-mbstring
- php-intl
state: present
when: ansible_facts.os_family == 'RedHat'
- name: Install PHP и modules (Debian)
package:
name:
- php{{ php_version }}
- php{{ php_version }}-mysql
- php{{ php_version }}-gd
- php{{ php_version }}-xml
- php{{ php_version }}-mbstring
- php{{ php_version }}-intl
state: present
when: ansible_facts.os_family == 'Debian'
- name: Set PHP timezone
lineinfile:
path: /etc/php.ini if ansible_facts.os_family == 'RedHat' else /etc/php/{{ php_version }}/apache2/php.ini
regexp: '^date.timezone'
line: 'date.timezone = UTC'
Templates
roles/apache/templates/vhost.conf.j2:
<VirtualHost *:80>
ServerName {{ inventory_hostname }}
DocumentRoot /var/www/{{ inventory_hostname }}
<Directory /var/www/{{ inventory_hostname }}>
AllowOverride All
Require all granted
</Directory>
ErrorLog /var/log/httpd/{{ inventory_hostname }}-error.log
CustomLog /var/log/httpd/{{ inventory_hostname }}-access.log combined
</VirtualHost>
Запуск
ansible-playbook -i inventory/prod.yml site.yml --ask-vault-pass
Заключение
Данный playbook обеспечивает идемпотентное развёртывание LAMP-стека. Вы можете расширить его, добавив роли для Redis, мониторинга или SSL/TLS (через Let’s Encrypt). Хранение секретов в Ansible Vault и использование переменных для различия ОС делает решение production-ready.
Рубрика: Автоматизация
Хештеги: #ansible #automation #lamp #devops #linux #apache #mysql #php #инфраструктура #best-practices