Ansible实战:LNMP一键部署指南
文章目录第一步控制机环境准备安装 Ansible 与配置 SSH第二步创建基于 Roles 标准目录结构的项目第三步编写主机清单 (Inventory) 和各个 Roles 代码1. 创建主机清单 hosts.ini2. 编写 Nginx 角色拉取 Nginx 官方源并配置反向代理到 PHP3. 编写 PHP 角色从 Remi 源拉取 PHP 8.1配置参数与截图一致4. 编写 MySQL 角色拉取 MySQL 8.0 官方源第四步编写主入口 Playbook (site.yml)第五步执行部署与自主检测第六步浏览器可视化验证错误显示有错误再进行下列操作1、页面显示默认首页1.1 为什么主机名匹配不上1.2 解决步骤请按顺序执行第一步恢复带有链接的首页第二步检查 PHP 是否安装并启动关键第三步确认 PHP 测试文件是否存在第四步确认 Nginx 配置正确且已重启第五步在浏览器验证第一步控制机环境准备安装 Ansible 与配置 SSH1. 在192.168.30.198机器上安装 Ansible# 1. 安装 EPEL 源Ansible 依赖此源dnfinstallepel-release-y# 2. 安装 Ansiblednfinstallansible-y# 3. 检测安装是否成功自主检测命令ansible--version# 预期输出ansible [core 2.x.x] ...2. 配置 SSH 免密登录到目标机器192.168.30.199# 1. 生成 SSH 密钥一路回车即可ssh-keygen-trsa-b4096-f~/.ssh/id_rsa-N# 2. 将公钥发送到 199 主机需要输入一次 199 机器的 root 密码ssh-copy-id root192.168.30.199# 3. 修改目标机器主机名可选匹配后续 Playbook 的模板sshroot192.168.30.199hostnamectl set-hostname gaoxf199# 4. 测试 SSH 连通性自主检测命令sshroot192.168.30.199hostname# 预期输出gaoxf199第二步创建基于 Roles 标准目录结构的项目在192.168.30.198控制机上执行# 创建 LNMP 项目文件夹及 Roles 各级目录mkdir-p~/lnmp-roles/{roles/{nginx,mysql,php}/{tasks,templates,vars,handlers},group_vars}cd~/lnmp-roles第三步编写主机清单 (Inventory) 和各个 Roles 代码这里我们直接使用cat生成文件。请在~/lnmp-roles目录下逐条复制以下命令并执行1. 创建主机清单hosts.inicathosts.iniEOF [webserver] 192.168.30.199 ansible_userroot ansible_python_interpreter/usr/bin/python3 EOF2. 编写 Nginx 角色拉取 Nginx 官方源并配置反向代理到 PHP# 2.1 任务文件catroles/nginx/tasks/main.ymlEOF --- - name: 安装依赖包 yum: name: epel-release state: present - name: 添加 Nginx 官方 Yum 源 (Rocky 9) yum_repository: name: nginx description: Nginx Official YUM Repository baseurl: http://nginx.org/packages/centos/9/$basearch/ gpgcheck: yes gpgkey: https://nginx.org/keys/nginx_signing.key enabled: yes - name: 从官方源安装 Nginx (会自动导入 GPG 密钥) yum: name: nginx state: present - name: 部署优化版 Nginx 主配置 template: src: nginx.conf.j2 dest: /etc/nginx/nginx.conf notify: restart nginx - name: 部署虚拟主机模板 (支持PHP解析) template: src: vhost.conf.j2 dest: /etc/nginx/conf.d/www.conf notify: restart nginx - name: 启动 Nginx 并设置开机自启 systemd: name: nginx state: started enabled: yes EOF# 2.2 Nginx 主配置模板catroles/nginx/templates/nginx.conf.j2EOF user nginx; worker_processes auto; error_log /var/log/nginx/error.log; pid /run/nginx.pid; include /usr/share/nginx/modules/*.conf; events { worker_connections 1024; } http { log_format main $remote_addr - $remote_user [$time_local] $request $status $body_bytes_sent $http_referer $http_user_agent $http_x_forwarded_for; access_log /var/log/nginx/access.log main; sendfile on; tcp_nopush on; tcp_nodelay on; keepalive_timeout 65; types_hash_max_size 4096; include /etc/nginx/mime.types; default_type application/octet-stream; include /etc/nginx/conf.d/*.conf; } EOF# 2.3 Nginx 虚拟主机模板catroles/nginx/templates/vhost.conf.j2EOF server { listen 80 default_server; server_name _; root /usr/share/nginx/html; index index.php index.html index.htm; charset utf-8; # --- 关键加上这一行强制浏览器使用UTF-8 location / { } location ~ \.php$ { fastcgi_pass 127.0.0.1:9000; fastcgi_index index.php; fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name; include fastcgi_params; } } EOF# 2.4 Nginx 处理器catroles/nginx/handlers/main.ymlEOF --- - name: restart nginx systemd: name: nginx state: restarted EOF3. 编写 PHP 角色从 Remi 源拉取 PHP 8.1配置参数与截图一致# 3.1 PHP 任务文件catroles/php/tasks/main.ymlEOF --- - name: 安装 Remi 源 (针对 PHP 8.1) - 首次安装跳过 GPG 检查 yum: name: https://rpms.remirepo.net/enterprise/remi-release-9.rpm state: present disable_gpg_check: yes - name: 重置 PHP 模块流 command: dnf module reset php -y - name: 启用 PHP 8.1 模块流 command: dnf module enable php:8.1 -y - name: 安装 PHP 8.1 及 FPM 和相关扩展 yum: name: - php-fpm - php-cli - php-mysqlnd - php-gd - php-xml - php-mbstring - php-opcache state: present - name: 部署优化版 php.ini (修改内存、上传限制等) template: src: php.ini.j2 dest: /etc/php.ini notify: restart php-fpm - name: 部署优化版 www.conf (修改 max_children20 等) template: src: www.conf.j2 dest: /etc/php-fpm.d/www.conf notify: restart php-fpm - name: 创建 phpinfo 测试页 copy: content: ?php phpinfo(); ? dest: /usr/share/nginx/html/info.php - name: 启动 PHP-FPM 并设置开机自启 systemd: name: php-fpm state: started enabled: yes - name: SELinux 放行 Nginx 网络连接 (防止403/502错误) ansible.posix.seboolean: name: httpd_can_network_connect state: yes persistent: yes when: ansible_selinux.status enabled EOF# 3.2 PHP 配置模板 php.ini.j2catroles/php/templates/php.ini.j2EOF ; 优化核心参数 memory_limit 256M upload_max_filesize 50M post_max_size 50M date.timezone Asia/Shanghai EOF# 3.3 PHP-FPM 进程池模板 www.conf.j2catroles/php/templates/www.conf.j2EOF [www] user apache group apache listen 127.0.0.1:9000 pm dynamic pm.max_children 20 pm.start_servers 5 pm.min_spare_servers 5 pm.max_spare_servers 10 EOF# 3.4 PHP 处理器catroles/php/handlers/main.ymlEOF --- - name: restart php-fpm systemd: name: php-fpm state: restarted EOF4. 编写 MySQL 角色拉取 MySQL 8.0 官方源# 4.1 MySQL 任务文件catroles/mysql/tasks/main.ymlEOF --- - name: 强制导入 MySQL 官方 GPG 公钥 (解决安装包时的签名验证失败问题) shell: rpm --import https://repo.mysql.com/RPM-GPG-KEY-mysql changed_when: false ignore_errors: yes # 即使下载公钥失败也继续往下走因为有下一步的跳过 gpg 检查兜底。 - name: 配置 MySQL 8.0 官方 Yum 源 (清华镜像加速) yum_repository: name: mysql80-community description: MySQL 8.0 Community Server YUM Repo baseurl: https://mirrors.tuna.tsinghua.edu.cn/mysql/yum/mysql-8.0-community-el9-$basearch/ gpgcheck: yes gpgkey: https://repo.mysql.com/RPM-GPG-KEY-mysql enabled: yes sslverify: no - name: 从配置好的 Yum 源安装 MySQL Server (强制跳过 GPG 校验) yum: name: mysql-community-server state: present disable_gpg_check: yes # 关键这一行将彻底解决拦截问题 - name: 启动 MySQL 并设置开机自启 systemd: name: mysqld state: started enabled: yes - name: 获取 MySQL 初始临时 root 密码 shell: grep temporary password /var/log/mysqld.log | awk {print $NF} register: mysql_temp_pass changed_when: false EOF第四步编写主入口 Playbook (site.yml)catsite.ymlEOF --- - name: 部署 LNMP 生产环境至 199 服务器 hosts: webserver gather_facts: yes roles: - role: nginx - role: php - role: mysql post_tasks: - name: 端口连通性健康检查 (Nginx 80, PHP-FPM 9000) wait_for: port: {{ item }} host: 127.0.0.1 timeout: 5 loop: - 80 - 9000 - name: 输出部署成功结果Web测试地址 debug: msg: - - LNMP 部署完成 - 目标主机: gaoxf199 (192.168.30.199) - PHP 测试页: http://192.168.30.199/info.php - Nginx 主页: http://192.168.30.199 - EOF第五步执行部署与自主检测现在所有 Roles 和 Playbook 已经就绪。在~/lnmp-roles目录下执行1. 运行主 Playbook自动拉取依赖、软件源并安装ansible-playbook-ihosts.ini site.yml(执行过程中控制台会显示绿色的ok,changed等状态和您提供的截图中一样其中 PHP 会重置模块流这就是截图里的TASK [重置 PHP 模块])2. 在控制机上验证服务是否成功运行自主检测命令# 1. 检测 Ping 连通性ansible all-ihosts.ini-mping# 2. 远程在目标机查看端口监听状态 (检测 Nginx, PHP-FPM 是否正常)ansible192.168.30.199-ihosts.ini-mshell-ass -tlnp | grep -E :(80|9000|3306)# 预期输出包含 LISTEN 状态的 80, 9000, 3306# 3. 远程在目标机测试 PHP-FPM 和 Nginx 是否连接正常ansible192.168.30.199-ihosts.ini-mshell-acurl -I http://127.0.0.1/info.php# 预期输出HTTP/1.1 200 OK第六步浏览器可视化验证在您的本地电脑或任何与 198/199 网络互通的主机的浏览器地址栏输入http://192.168.30.199预期结果将显示类似您提供的图 6、7、8 中的“Welcome to gaoxf199”以及“Nginx deployed by Ansible”并带有「PHP Info」超链接。点击「PHP Info」或直接访问http://192.168.30.199/info.php预期结果显示紫色的PHP Version 8.1.32信息大表格与您的图9完全一致。在此页面搜索memory_limit能看到值为256M搜索upload_max_filesize能看到值为50M表明您的优化模板已经成功生效。错误显示有错误再进行下列操作1、页面显示默认首页建议执行完下面的操作且修改完服务器上的文件后再去控制机重新跑一遍ansible-playbook -i hosts.ini site.yml这次 MySQL 已修复应该能完全接管并推送修改的模板了。看到这个默认的 Nginx 欢迎页说明Nginx 进程已经成功启动了但是自定义虚拟主机配置文件没有生效。因为系统中原本自带了一个默认的配置文件default.conf它抢占了 IP 的访问请求。1.1 为什么主机名匹配不上在 Ansiblevhost.conf.j2模板中配置的是server_name {{ ansible_fqdn }}; # 这里是 第二台机器的主机名但在浏览器中直接输入的是 IP192.168.30.199。在 Nginx 中默认配置文件default.conf通常设置了server_name _;通配符。Nginx 只会将 IP 请求匹配给通配符配置而不会匹配给主机名配置所以默认页面就被“抢”到了。1.2 解决步骤请按顺序执行在目标机192.168.30.199上操作即可完成sshroot192.168.30.199第一步恢复带有链接的首页在目标机上执行cat/usr/share/nginx/html/index.htmlEOF h1Welcome to gaoxf199/h1 pNginx deployed by Ansible/p a href/info.phpPHP Info/a EOF第二步检查 PHP 是否安装并启动关键如果 PHP 没起来点链接会报 404 或 502 错误。请执行# 查看 PHP-FPM 状态systemctl status php-fpm# 如果显示 inactive (dead)请启动它systemctl start php-fpm systemctlenablephp-fpm第三步确认 PHP 测试文件是否存在ls-l/usr/share/nginx/html/info.php如果不存在手动创建echo?php phpinfo(); ?/usr/share/nginx/html/info.php第四步确认 Nginx 配置正确且已重启# 测试配置文件是否有语法错误nginx-t# 如果没问题重启 Nginx 让 PHP 解析生效systemctl restart nginx# 确认 PHP 转发地址匹配grepfastcgi_pass/etc/nginx/conf.d/www.conf# 必须输出fastcgi_pass 127.0.0.1:9000;第五步在浏览器验证现在访问http://192.168.30.199就能看到PHP Info的超链接了。点击进去就会显示紫色的PHP Version 8.1.32页面。如果打开了 PHP 页面说明 Nginx 到 PHP 的桥接已经彻底打通。