用Ansible剧本管理Ubuntu上的LNMP环境状态,核心就是通过YAML编写的Playbook,把Nginx、MySQL/MariaDB、PHP这三大组件的安装、配置、启动、状态监控全部自动化。你不需要SSH登录到每台服务器手动敲命令,只需要一台控制机、一个剧本文件,就能批量部署和持续维护整个LNMP集群。下面我从环境准备、剧本编写、模块调用、状态管理、实战优化五个维度,把这套方案彻底讲透。
一、为什么要用Ansible管理LNMP而不是Shell脚本很多运维同学习惯写Shell脚本来部署LNMP,但Shell脚本有个致命问题:它是线性执行的,没有幂等性保证。你跑两次脚本,第二次可能报错或者覆盖配置。Ansible的Playbook天然支持幂等操作,也就是说同一个剧本跑一百次,结果都是一致的——已经装好的不会重复装,已经启动的不会重复启动。而且Ansible基于SSH协议,不需要在目标机器上安装任何Agent,Ubuntu默认就支持,开箱即用。对于LNMP这种需要精确控制版本、配置文件、服务状态的场景,Ansible的模块化设计比Shell脚本高效太多。
二、控制机环境准备与主机清单配置首先在你的Ubuntu控制机上安装Ansible。Ubuntu 22.04可以直接用apt安装,但建议用pip安装最新稳定版:
sudo apt update sudo apt install python3-pip python3-venv -y python3 -m venv ~/ansible-env source ~/ansible-env/bin/activate pip install ansible
然后创建主机清单文件,假设你有三台Ubuntu服务器要部署LNMP:
[lnmp_servers] 192.168.1.101 192.168.1.102 192.168.1.103 [lnmp_servers:vars] ansible_user=deploy ansible_ssh_private_key_file=~/.ssh/id_rsa ansible_python_interpreter=/usr/bin/python3
这段配置的关键点:ansible_user指定SSH登录用户,ansible_ssh_private_key_file指定密钥路径免密登录,ansible_python_interpreter指定目标机Python解释器路径,Ubuntu 22.04自带Python3,但有些精简镜像可能没有,这个参数能避免报错。
三、LNMP安装剧本的完整编写下面是一个生产级的LNMP部署剧本,我把Nginx、MariaDB、PHP三个组件拆成独立的role来写,结构清晰、可复用:
---
- name: Deploy LNMP Environment on Ubuntu
hosts: lnmp_servers
become: yes
vars:
nginx_version: "1.24"
mysql_root_password: "YourSecurePass123!"
php_version: "8.2"
php_extensions:
- php8.2-fpm
- php8.2-mysql
- php8.2-cli
- php8.2-curl
- php8.2-gd
- php8.2-mbstring
- php8.2-xml
- php8.2-zip
roles:
- role: nginx_install
- role: mariadb_install
- role: php_install
这个主剧本非常简洁,实际工作都下放到各个role里。下面逐个讲每个role怎么写。
四、Nginx角色剧本:安装、配置与状态管理创建roles/nginx_install/tasks/main.yml:
- name: Install Nginx
apt:
name: nginx
state: present
update_cache: yes
- name: Ensure Nginx is running and enabled
service:
name: nginx
state: started
enabled: yes
- name: Deploy custom nginx.conf
template:
src: templates/nginx.conf.j2
dest: /etc/nginx/nginx.conf
owner: root
group: root
mode: '0644'
notify: Restart Nginx
- name: Deploy site configuration
template:
src: templates/site.conf.j2
dest: /etc/nginx/sites-available/default
notify: Restart Nginx
- name: Enable site configuration
file:
src: /etc/nginx/sites-available/default
dest: /etc/nginx/sites-enabled/default
state: link
notify: Restart Nginx
handlers:
- name: Restart Nginx
service:
name: nginx
state: restarted
这里有几个硬核细节要注意。第一,apt模块的update_cache: yes等价于先apt update再apt install,省了一步。第二,template模块用Jinja2模板渲染配置文件,你可以在templates目录下放nginx.conf.j2和site.conf.j2,里面用变量占位符实现差异化部署。第三,notify和handler配合,只有配置文件真正发生变化时才重启Nginx,没变化就跳过,这就是幂等性的体现。
五、MariaDB角色剧本:安全初始化与状态监控创建roles/mariadb_install/tasks/main.yml:
- name: Install MariaDB server
apt:
name:
- mariadb-server
- python3-pymysql
state: present
update_cache: yes
- name: Ensure MariaDB is running and enabled
service:
name: mariadb
state: started
enabled: yes
- name: Set MariaDB root password
mysql_user:
name: root
host: localhost
password: "{{ mysql_root_password }}"
login_unix_socket: /var/run/mysqld/mysqld.sock
- name: Remove anonymous users
mysql_user:
name: ''
host_all: yes
state: absent
login_unix_socket: /var/run/mysqld/mysqld.sock
- name: Remove test database
mysql_db:
name: test
state: absent
login_unix_socket: /var/run/mysqld/mysqld.sock
- name: Create application database
mysql_db:
name: appdb
state: present
login_unix_socket: /var/run/mysqld/mysqld.sock
- name: Create application user
mysql_user:
name: appuser
password: "AppPass456!"
priv: 'appdb.*:ALL'
state: present
login_unix_socket: /var/run/mysqld/mysqld.sock
MariaDB的安全初始化非常重要。mysql_user和mysql_db模块需要python3-pymysql这个依赖,所以apt任务里一起装了。login_unix_socket参数指定通过本地socket连接而不是TCP,更安全也更快。这套操作跑完,MariaDB就完成了从裸装到生产安全配置的全过程。
六、PHP角色剧本:FPM配置与版本管理创建roles/php_install/tasks/main.yml:
- name: Add Ondřej Surý PHP PPA
apt_repository:
repo: ppa:ondrej/php
state: present
- name: Install PHP packages
apt:
name: "{{ php_extensions }}"
state: present
update_cache: yes
- name: Configure PHP-FPM
template:
src: templates/php-fpm.conf.j2
dest: /etc/php/{{ php_version }}/fpm/pool.d/www.conf
owner: root
group: root
mode: '0644'
notify: Restart PHP-FPM
- name: Ensure PHP-FPM is running and enabled
service:
name: "php{{ php_version }}-fpm"
state: started
enabled: yes
handlers:
- name: Restart PHP-FPM
service:
name: "php{{ php_version }}-fpm"
state: restarted
Ubuntu自带的apt源里PHP版本通常比较旧,要装PHP 8.2就必须加Ondřej Surý的PPA源。apt_repository模块自动处理了add-apt-repository的工作。PHP-FPM的www.conf模板里你可以调整pm.max_children、pm.start_servers这些参数,根据服务器内存做调优。一般4G内存的机器,pm.max_children设20-30比较合理。
七、状态管理与健康检查剧本部署完不是终点,持续监控状态才是运维自动化的核心价值。创建一个独立的check_lnmp.yml:
---
- name: Check LNMP Environment Status
hosts: lnmp_servers
become: yes
tasks:
- name: Check Nginx service status
service_facts:
- name: Verify Nginx is running
assert:
that:
- "'nginx.service' in services"
- "services['nginx.service'].state == 'running'"
fail_msg: "Nginx is not running!"
success_msg: "Nginx is running properly."
- name: Check Nginx response
uri:
url: http://localhost
status_code: 200
register: nginx_check
failed_when: nginx_check.status != 200
- name: Check MariaDB service status
service_facts:
- name: Verify MariaDB is running
assert:
that:
- "'mariadb.service' in services"
- "services['mariadb.service'].state == 'running'"
fail_msg: "MariaDB is not running!"
- name: Check PHP-FPM socket
stat:
path: /run/php/php{{ php_version }}-fpm.sock
register: php_socket
- name: Verify PHP-FPM socket exists
assert:
that:
- php_socket.stat.exists
fail_msg: "PHP-FPM socket not found!"
这个检查剧本用了service_facts收集所有服务状态,用assert做断言验证,用uri模块直接发HTTP请求测试Nginx响应,用stat模块检查PHP-FPM的socket文件是否存在。任何一项检查失败,Ansible会立即报错并停止,你可以把它接入定时任务或者CI/CD流水线,实现自动化巡检。
八、实战优化建议与常见坑第一,变量分离。不要把密码、IP写死在剧本里,用group_vars/lnmp_servers/vars.yml或者Ansible Vault加密敏感数据。第二,标签控制。给任务加tags,比如nginx_config、db_security,紧急情况下可以只跑某一类任务:ansible-playbook deploy.yml --tags nginx_config。第三,重试机制。网络不稳定时apt安装可能失败,在任务里加retries: 3和delay: 10能自动重试。第四,日志输出。用-vvv参数运行能看到详细调试信息,排错时非常有用。第五,Ubuntu版本差异。20.04和22.04的包名、服务名有细微差别,比如PHP 8.1在22.04里叫php8.1-fpm,在20.04里可能需要从PPA装,剧本里要做版本判断或者统一用变量控制。
最后说一个很多人忽略的点:Ansible剧本本身也需要版本管理。把整个项目放到代码仓库里,每次修改都有记录、可回滚。配合GitLab CI或者Jenkins,代码合并后自动触发Ansible部署,这才是真正的基础设施即代码(IaC)实践。LNMP环境的状态不再是黑盒,每一行配置都有据可查、可复现。
九、总结Ansible管理Ubuntu上的LNMP环境,本质上就是把运维经验固化成可执行的YAML代码。从安装、配置、安全加固到状态巡检,每个环节都有对应的Ansible模块支撑。关键在于:结构清晰的role划分、Jinja2模板实现配置差异化、幂等操作保证多次执行安全、assert和健康检查实现自动化监控。掌握这套方法,你管理10台服务器和管理1000台服务器,工作量几乎没有区别,这就是自动化运维的真正威力。
