当前位置: 首页 > news >正文

Ansible实战:LNMP一键部署指南

文章目录

  • 第一步:控制机环境准备(安装 Ansible 与配置 SSH)
  • 第二步:创建基于 Roles 标准目录结构的项目
  • 第三步:编写主机清单 (Inventory) 和各个 Roles 代码
    • 1. 创建主机清单 `hosts.ini`
    • 2. 编写 Nginx 角色(拉取 Nginx 官方源,并配置反向代理到 PHP)
    • 3. 编写 PHP 角色(从 Remi 源拉取 PHP 8.1,配置参数与截图一致)
    • 4. 编写 MySQL 角色(拉取 MySQL 8.0 官方源)
  • 第四步:编写主入口 Playbook (`site.yml`)
  • 第五步:执行部署与自主检测
  • 第六步:浏览器可视化验证
  • 错误显示(`有错误再进行下列操作`)
    • 1、页面显示默认首页
      • 1.1 为什么主机名匹配不上?
      • 1.2 解决步骤(请按顺序执行)
        • 第一步:恢复带有链接的首页
        • 第二步:检查 PHP 是否安装并启动(关键)
        • 第三步:确认 PHP 测试文件是否存在
        • 第四步:确认 Nginx 配置正确且已重启
        • 第五步:在浏览器验证

第一步:控制机环境准备(安装 Ansible 与配置 SSH)

1. 在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 root@192.168.30.199# 3. 修改目标机器主机名(可选,匹配后续 Playbook 的模板)sshroot@192.168.30.199"hostnamectl set-hostname gaoxf199"# 4. 测试 SSH 连通性(自主检测命令)sshroot@192.168.30.199"hostname"# 预期输出: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.ini

cat>hosts.ini<<'EOF' [webserver] 192.168.30.199 ansible_user=root ansible_python_interpreter=/usr/bin/python3 EOF

2. 编写 Nginx 角色(拉取 Nginx 官方源,并配置反向代理到 PHP)

# 2.1 任务文件cat>roles/nginx/tasks/main.yml<<'EOF' --- - 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 主配置模板cat>roles/nginx/templates/nginx.conf.j2<<'EOF' 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 虚拟主机模板cat>roles/nginx/templates/vhost.conf.j2<<'EOF' 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 处理器cat>roles/nginx/handlers/main.yml<<'EOF' --- - name: restart nginx systemd: name: nginx state: restarted EOF

3. 编写 PHP 角色(从 Remi 源拉取 PHP 8.1,配置参数与截图一致)

# 3.1 PHP 任务文件cat>roles/php/tasks/main.yml<<'EOF' --- - 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_children=20 等) 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.j2cat>roles/php/templates/php.ini.j2<<'EOF' ; 优化核心参数 memory_limit = 256M upload_max_filesize = 50M post_max_size = 50M date.timezone = Asia/Shanghai EOF# 3.3 PHP-FPM 进程池模板 www.conf.j2cat>roles/php/templates/www.conf.j2<<'EOF' [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 处理器cat>roles/php/handlers/main.yml<<'EOF' --- - name: restart php-fpm systemd: name: php-fpm state: restarted EOF

4. 编写 MySQL 角色(拉取 MySQL 8.0 官方源)

# 4.1 MySQL 任务文件cat>roles/mysql/tasks/main.yml<<'EOF' --- - 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)

cat>site.yml<<'EOF' --- - 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-a"ss -tlnp | grep -E ':(80|9000|3306)'"# 预期输出包含 LISTEN 状态的 80, 9000, 3306# 3. 远程在目标机测试 PHP-FPM 和 Nginx 是否连接正常ansible192.168.30.199-ihosts.ini-mshell-a"curl -I http://127.0.0.1/info.php"# 预期输出:HTTP/1.1 200 OK

第六步:浏览器可视化验证

  1. 在您的本地电脑(或任何与 198/199 网络互通的主机)的浏览器地址栏输入:

    • http://192.168.30.199
    • 预期结果:将显示类似您提供的图 6、7、8 中的“Welcome to gaoxf199”以及“Nginx deployed by Ansible”,并带有「PHP Info」超链接。
  2. 点击「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)上操作,即可完成:

sshroot@192.168.30.199
第一步:恢复带有链接的首页

在目标机上执行:

cat>/usr/share/nginx/html/index.html<<'EOF' <h1>Welcome to gaoxf199</h1> <p>Nginx deployed by Ansible</p> <a href="/info.php">PHP 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 转发地址匹配grep"fastcgi_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 的桥接已经彻底打通。

http://www.cnnetsun.cn/news/4211951.html

相关文章:

  • 汉森制药(002412)深度研究报告
  • 理解 JWT:三段分别是什么
  • 计算机毕业设计之企业社交网络平台的设计与实现
  • HarmonyOS 性能优化工具链:从「手工排查」到「工程化治理」的全栈实战指南
  • 01-具身机器人硬件全景拆解
  • ABAP 里有没有 AI Agent 的 Progressive Disclosure,一套从封装、Released API 到 RAP 暴露层的完整对照
  • 从奈奎斯特判据到无源性:为什么只需保证逆变器导纳无源就能稳定并网?
  • 【python】条件语句
  • 【2015-03-02】《RealView编译工具汇编器指南》摘录:内置变量和常数
  • 手机玩鸣潮 3.6 版本,随时随地开荒新地图不卡顿
  • AIGC 到底是什么:从传统软件到生成式人工智能
  • 规模化养殖冰爽强甘多少钱
  • Go单例模式:sync.Once与双重检查
  • 【第9篇】 EfficientViT(ICCV 2023):基于多尺度线性注意力的高效高分辨率密集预测网络
  • 封神了!Scrapling 火了,AI 时代的数据采集神器来了
  • 经验丰富的杭州园林景观工程公司排名哪个好
  • DC/DC电源怎么选?如何在效率、体积、隔离和EMI之间做平衡?
  • 【代码评测】AI 写代码更快以后,为什么 Review 反而成为瓶颈?
  • 大宗交易折溢价因子怎么挖掘本地化Python全流程实战 IG50免费开源股票数据API接口
  • SRC挖洞变现:业务逻辑漏洞报告怎么写才能评上高危?(附5类报告模板)
  • Claude Code文档访问失败?开发者必备的版本管理与信息同步方案
  • 2026年家长必看!靠谱儿童视光及近视防控该如何选择?
  • 能写的未必能过检:从AIGC检测原理倒推,论文AI工具到底该怎么选
  • 前缀和与差分数组——从O(n²)到O(1)的降维打击
  • 快餐出海,不是把店开出去,而是把供应链搬出去!10月杭州中餐出海研讨会,快餐/简餐出海的供应链适配与本土化策略。限席!
  • 构建AI编程智能体:以DeepSeek Hermes为大脑的多工具协同工作流
  • AI大模型与数学·第49课 级数刷题集训6:泰勒级数完整实战+余项误差分析——大模型轻量化、截断近似底层数学
  • Windows局域网联机全攻略:从文件共享到游戏联机与Docker部署
  • 迷你PC构建Proxmox集群:万兆网络规划与配置实战
  • Qwen3.8本地推理性能优化实战:vLLM、量化与参数调优指南