在企业级Web服务部署场景中,传统的手动部署方式存在诸多痛点:配置一致性难以保证、操作步骤繁琐易错、多服务器协同困难。我最近为一个电商项目搭建了基于Ansible的自动化部署方案,实现了Nginx+PHP+MySQL集群的一键部署。这个方案将原本需要2天的手工部署时间缩短到15分钟,配置准确率达到100%。
我们采用经典的三层架构:
code复制客户端 → Nginx反向代理 → PHP应用服务器 → MySQL数据库
这种架构的优势在于:
选择Ansible作为自动化工具基于以下考虑:
所有节点采用CentOS 7.x系统,确保环境一致性。控制节点需要:
bash复制# 安装Ansible
yum install -y epel-release
yum install -y ansible
# 验证版本
ansible --version # 需要2.10+
在控制节点执行:
bash复制ssh-keygen -t rsa # 生成密钥对
for ip in 192.168.1.{10,20,21,30}; do
ssh-copy-id -i ~/.ssh/id_rsa.pub root@$ip
done
采用Roles模块化组织代码:
code复制web_cluster_deploy/
├── inventory.ini
├── site.yml
└── roles/
├── common/ # 基础配置
├── mysql/ # 数据库
├── php/ # 应用
└── nginx/ # 代理
yaml复制# roles/common/tasks/main.yml
- name: 安装基础工具包
yum:
name: "{{ common_packages }}"
state: present
- name: 配置时区
timezone:
name: Asia/Shanghai
yaml复制- name: 创建应用专用用户
user:
name: app
group: app
shell: /bin/bash
password_lock: yes # 禁用密码登录
yaml复制# roles/mysql/tasks/main.yml
- name: 设置root密码
mysql_user:
name: root
password: "{{ mysql_root_password }}"
host: "{{ item }}"
priv: "*.*:ALL,GRANT"
loop:
- localhost
- "%" # 允许远程登录
yaml复制- name: 创建应用数据库
mysql_db:
name: "{{ app_db_name }}"
encoding: utf8mb4 # 支持完整unicode
jinja复制# roles/php/templates/www.conf.j2
[www]
pm = dynamic
pm.max_children = 50 # 根据内存调整
pm.start_servers = 5
pm.min_spare_servers = 5
yaml复制- name: 部署应用代码
unarchive:
src: /tmp/web_app.tar.gz
dest: "{{ app_deploy_path }}"
owner: app
group: app
jinja复制# roles/nginx/templates/nginx.conf.j2
upstream php_app_cluster {
{% for server in php_servers %}
server {{ server }}:9000;
{% endfor %}
}
nginx复制location ~* \.(jpg|jpeg|png|gif|css|js|ico)$ {
expires 30d; # 客户端缓存30天
}
bash复制ansible-vault encrypt roles/mysql/vars/main.yml
yaml复制- name: 限制MySQL访问IP
firewalld:
rich_rule: rule family="ipv4" source address="192.168.1.0/24" port protocol="tcp" port="3306" accept
ini复制pm.max_children = (可用内存) / (单个进程内存占用)
nginx复制worker_processes auto; # 自动匹配CPU核心数
worker_connections 1024; # 每个worker最大连接数
yaml复制- name: 监控Nginx状态
uri:
url: http://localhost/nginx_status
status_code: 200
register: nginx_status
until: nginx_status.status == 200
retries: 3
nginx复制upstream php_app_cluster {
server 192.168.1.20:9000 max_fails=3 fail_timeout=30s;
server 192.168.1.21:9000 backup; # 备用服务器
}
| 现象 | 可能原因 | 解决方案 |
|---|---|---|
| SSH连接失败 | 防火墙阻止/密钥错误 | 检查22端口和authorized_keys |
| MySQL无法远程连接 | bind-address限制 | 检查my.cnf中的bind-address |
| PHP报502错误 | PHP-FPM未运行 | systemctl restart php-fpm |
bash复制# 查看请求分发情况
tail -f /var/log/nginx/access.log | awk '{print $1}'
sql复制-- 在MySQL中执行
SET GLOBAL slow_query_log = 'ON';
SET GLOBAL long_query_time = 1;
nginx复制server {
listen 443 ssl;
ssl_certificate /path/to/cert.pem;
ssl_certificate_key /path/to/key.pem;
}
通过Inventory区分环境:
ini复制[prod:children]
nginx_servers
php_servers
[test:children]
nginx_test
php_test
bash复制ansible-playbook -i inventory.ini site.yml --check
bash复制git tag v1.0-deploy
git push origin --tags
这个方案在实际项目中表现出色,特别是在应对突发流量时,通过简单增加PHP服务器节点即可快速扩展。有次大促期间,我们仅用10分钟就完成了集群扩容,平稳支撑了平时5倍的流量。