# Linux实战笔记:WordPress文创项目部署全流程记录

一.互联网网站架构完整演进路线

一个完整的项目并不是一蹴而就的,就像盖房子一样,要先打地基再砌砖。因此我们的项目也是从单机项目开始,然后再一步步进行功能解耦和升级。因此对于本项目的演进,我们可以进行以下规划:

1.1 单机LNMP架构(初创小型站点)

适用场景:用户量极小、低成本快速上线;

架构:单台服务器集成Nginx+PHP+MySQL;

优缺点:部署简单、成本低;存在单点故障 ,流量上涨后资源争抢严重。

流量模型:客户端→DNS→单机Web服务器(Web+DB同机)

1.2 Web与数据库分离架构(数据库解耦)

核心原理:PHP/Java应用消耗CPU,数据库读写消耗大量内存,两类服务资源需求冲突,因此我们需要对数据库进行解耦,拆分数据库独立服务器,隔离硬件资源。

架构:独立Web服务器 + 独立数据库服务器;

流量模型:客户端→DNS→Web服务器→独立DB服务器。

  • 数据库解耦,拆分数据库独立服务器

1.3 Web负载均衡集群(多Web节点分担并发)

核心组件:Nginx/Haproxy/LVS作为流量调度器;Keepalived保障调度器高可用;

解决痛点:单台Web服务器并发上限低,高峰期CPU/带宽打满。

架构:调度器集群 + Web服务器集群 + 独立数据库。

  • 通过Nginx/Haproxy代理或LVS调度实现web负载均衡
  • 增加Keepalived保持代理服务器的高效可用

1.4 动静分离架构

静态资源(图片、css、js、视频)单独Nginx静态节点部署;动态PHP/Tomcat应用单独节点;静态资源可接入CDN就近缓存,降低应用服务器压力。

  • 动态网站与静态网站分离,让服务器专注一件事(动态与静态web资源也进行分离,使用nfs分别挂载)

1.5 数据库集群架构

优化方案:主从复制、读写分离、分库分表、共享存储;

解决单机数据库查询瓶颈、数据丢失风险,支撑海量数据读写。

  • 主从数据库、分库分表、读写分离
  • 共享存储

1.6 缓存与CDN架构

静态数据可以通过varnish、squid或者nginx进行缓存,将数据缓存到距离用户更近的位置,构建CDN(内容分发网络)架构。

CDN:静态资源缓存至全国边缘节点,缩短用户访问延迟,减轻源站压力;

1.7 监控与安全架构

监控平台:Zabbix、Prometheus;

作用:全链路服务器资源、服务状态监控,故障实时告警;

实验环境规划

  1. 基础模板机批量创建9台Linux虚拟机;
  2. 代理服务器采用双网卡:VMnet1仅主机模式配置网段:192.168.4.0/24、VMnet8 NAT模式配置网段: 192.168.8.0/24;
  3. Windows宿主机使用WindTerm通过SSH远程管理所有虚拟机;
  4. 主机IP规划:

二.项目整体需求背景

项目名称:云途文创官网建设与架构迭代项目

核心载体:WordPress开源CMS建站系统,分两期迭代升级架构,贴合企业真实业务流量增长场景;

前期参考资料:《云途文创官网建设与架构迭代项目甲方需求文档.pdf》,包含业务背景、流量指标、生产环境规范。

三.ansible部署

由于本次项目体量较大,需要控制的主机较多,我们可以选择在项目开启之前先部署ansible,为后面批量操作进行铺垫,可以简化部分操作,减少工作量。本次我们选择在zop主机(即监控主机。实际可根据需要选择)部署ansible,用作控制节点

3.1hosts文件修改

配置hosts文件内容,方便后续控制:

bash 复制代码
[root@zop ansible]# 
[root@zop ansible]# vim /etc/hosts
#增加配置:
192.168.8.5 haproxy1
192.168.8.6 haproxy2
192.168.8.11 web1
192.168.8.12 web2
192.168.8.13 web3
192.168.8.30 database
192.168.4.41 nfs1
192.168.8.42 nfs2
3.2ansible主机免密配置

配置 SSH 密钥免密登录:

bash 复制代码
[root@zop ~]# ssh-keygen -f /root/.ssh/id_rsa -N ''
[root@zop ~]# for i in haproxy1 haproxy2 web1 web2 web3 database nfs1 nfs2               #for循环分发密钥
> do
> ssh-copy-id root@$i
> done
3.3ansible安装

本次采用离线 RPM 包安装,需提前将 ansible-6.3.0-1.el8.noarch.rpmansible-core-2.13.3-1.el8.x86_64.rpm 上传至 control 节点(zop主机) /root 目录,执行安装命令

bash 复制代码
[root@zop ~]# dnf -y install ansible-6.3.0-1.el8.noarch.rpm ansible-core-2.13.3-1.el8.x86_64.rpm cowsay-3.04-16.el8.noarch.rpm
3.4核心配置文件修改

创建~/ansible目录,创建ansible.cfg文件,指定inventory主机清单文件

配置ansible.cfg文件:

bash 复制代码
# 1. 创建自定义配置目录并切入
# 1. 创建自定义配置目录
[root@control ~]# mkdir ~/ansible

# 2. 编辑主配置文件,指定主机清单路径
[root@control ~]# vim ~/ansible/ansible.cfg
# 写入以下内容
[defaults]
# 全局默认配置
inventory = /root/ansible/hosts  # 指定主机清单文件路径
forks = 8                   # 可选:SSH 并发连接数量,默认5,我们要控制8台就写8

配置主机清单文件:

主机清单文件用于定义 Ansible 管理的所有主机及主机组,是 Ansible 识别被管理节点的核心文件,路径与 ansible.cfg 中 inventory 配置一致(~/ansible/hosts):

bash 复制代码
[root@zop ansible]#  vim hosts

[haserver]
haproxy[1:2]

[webserver]
web[1:3]

[dataserver]
database

[nfsserver]
nfs[1:2]

(注意组名不要和成员名一样)

3.5测试 Ansible 环境连通性
bash 复制代码
[root@zop ansible]# ansible all -m ping

项目一期:单机架构 + 数据库解耦架构

阶段一:单机LNMP部署WordPress(初创基础期)

  • 项目一期拓扑图
  • 业务拆分,缓解单个服务器的压力
  • DNS服务可以选做

WordPress简介

  • WordPress是一款开源免费 PHP+MySQL架构的内容管理系统(CMS,Content Management System),2003 年正式发布,基于 GPLv2 开源协议,任何人都可免费使用、修改、二次开发、商用,无需授权费。
  • 核心定位:快速搭建各类网站,无需大量代码基础,是全球占有率最高的建站程序,全球超 43% 网站基于 WordPress 搭建。
  • WordPress可演变成为:博客、企业官网、商城、资讯门户、课程网站、作品集、下载站等,需要程序员二次开发。

需求背景

  • 阶段一:初创稳定上线阶段(基础期)
  • 业务场景:企业刚完成品牌注册,仅需搭建基础官网,完成企业信息展示、基础资讯发布,无大规模推广动作。
  • 流量指标:日均独立访问300人,瞬时并发访问≤50,每日文章、图片上传量≤20条
  • 核心痛点:零架构需求,仅需低成本快速上线、服务稳定可用,满足企业基础展示需求
  • 架构要求:单机架构(Nginx/Apache+PHP+MySQL同机部署),快速完成WordPress站点搭建、基础配置、主题美化、功能插件部署。

1.部署LNMP架构

脚本的缺点是逻辑判断麻烦,但是特定操作(文本正则筛选等)简单,剧本的优点是幂等性,省去了脚本的逻辑判断,但是正则筛选方面更为麻烦。

所以这里我使用了两种快速部署LNMP的方法:

一,使用纯shell脚本,速度快,可复用性高;

二,ansible剧本结合脚本,避开了shell和剧本的缺点

方法一:使用脚本快速部署
  • web1主机操作,部署LNMP架构
    因为之前部署了ansible,这里直接使用ansible进行操作
bash 复制代码
#切入ansible目录
[root@zop ~]# cd /root/ansible/
#将nginx软件包上传到zop主机的/root目录下,使用copy模块拷贝到web1主机
[root@zop ansible]# ansible web1 -m copy -a "src=/root/nginx-1.22.1.tar.gz dest=/root/"
#编写部署nginx的脚本
[root@zop ansible]# vim nginx.sh
#########脚本内容:##########
#!/bin/bash
dnf -y install gcc make pcre-devel openssl-devel
useradd nginx
tar -xf /root/nginx-1.22.1.tar.gz
cd nginx-1.22.1
./configure --prefix=/usr/local/nginx --user=nginx --group=nginx --with-http_ssl_module --with-http_stub_status_module
#指定安装目录,运行用户,运行组,开启加密功能
make && make install
ls /usr/local/nginx

#远程运行脚本
[root@zop ansible]# ansible web1 -m script -a "./nginx.sh"
#运行完毕,使用ansible远程查看安装目录进行验证:
[root@zop ansible]# ansible web1 -m shell -a "ls /usr/local/nginx"
web1 | CHANGED | rc=0 >>
conf
html
logs
sbin

接下来使用第二个脚本快速部署mariadb和php,以及配置使nginx支持动态页面,实现动静分离:

bash 复制代码
[root@zop ansible]# vim php.sh
########脚本内容:#########
#!/bin/bash
dnf -y install php php-fpm php-mysqlnd php-json mariadb-server mariadb
systemctl  enable  mariadb   --now
sed -i '38c listen = 127.0.0.1:9000' /etc/php-fpm.d/www.conf #开启php-fpm监听9000端口
systemctl enable php-fpm --now
sed -i '45c\            index index.php  index.html index.htm;' /usr/local/nginx/conf/nginx.conf #设置index.php为默认首页
sed -i '65,71s/#//' /usr/local/nginx/conf/nginx.conf #去掉65到71行的注释
sed -i '70s/_params/.conf/' /usr/local/nginx/conf/nginx.conf
sed -i '69s/^./#/' /usr/local/nginx/conf/nginx.conf #注释掉第69行
/usr/local/nginx/sbin/nginx #启动nginx
echo "/usr/local/nginx/sbin/nginx"  >> /etc/rc.d/rc.local #设置nginx开机自启动
chmod +x /etc/rc.d/rc.local

[root@zop ansible]# ansible web1 -m script -a "./php.sh"

注意!我们的脚本本质上是简单命令的集合,没有相关的逻辑检测,一旦运行时某处出现报错,千万不要重复运行脚本

注意!脚本中sed修改配置文件的命令都是基于百分百确定对应配置准确位置的情况下,实际配置过程中,需要自行去查看自己的对应配置的位置,避免因软件版本不同等原因导致修改出现问题

方法二:使用剧本结合脚本部署

创建角色(其实本项目无需角色直接写剧本就行)

bash 复制代码
[root@zop ansible]# mkdir roles
#创建角色
[root@zop ansible]# ansible-galaxy init roles/lnmp

#编写任务文件
[root@zop ansible]# vim roles/lnmp/tasks/main.yml 

任务文件内容:

yaml 复制代码
---
# tasks file for roles/lnmp
- name: 安装软件包
  yum: 
    name:
      - gcc
      - make 
      - pcre-devel
      - openssl-devel
      - php
      - php-fpm
      - php-mysqlnd
      - php-json
      - mariadb
      - mariadb-server
      - mariadb-devel
    state: present 

- name: 拷贝nginx源码包
  copy: 
    src: /root/nginx-1.22.1.tar.gz
    dest: /root/

- name: 解压缩nginx
  unarchive: 
    src: /root/nginx-1.22.1.tar.gz
    dest: /root/

- name: 执行脚本,编译安装nginx并修改配置文件
  script: /root/nginx.sh

- name: 启动mariadb服务
  service: 
    name: mariadb
    state: started
    enabled: yes

- name: 重启php服务
  service: 
    name: php-fpm
    state: restarted
    
- name: 启动nginx服务
  shell: /usr/local/nginx/sbin/nginx
  ignore_errors: true

编写脚本:

bash 复制代码
[root@zop ansible]# vim /root/nginx.sh
#####脚本内容:########
#!/bin/bash
sed -i '38c listen = 127.0.0.1:9000' /etc/php-fpm.d/www.conf #开启php-fpm监听9000端口
useradd nginx
cd /root/nginx-1.22.1
./configure --prefix=/usr/local/nginx --user=nginx --group=nginx --with-http_ssl_module --with-http_stub_status_module
make && make install
sed -i '45c\            index index.php  index.html index.htm;' /usr/local/nginx/conf/nginx.conf #设置index.php为默认首页
sed -i '65,71s/#//' /usr/local/nginx/conf/nginx.conf #去掉65到71行的注释
sed -i '70s/_params/.conf/' /usr/local/nginx/conf/nginx.conf
sed -i '69s/^./#/' /usr/local/nginx/conf/nginx.conf #注释掉第69行
echo "/usr/local/nginx/sbin/nginx"  >> /etc/rc.d/rc.local #设置nginx开机自启动
chmod +x /etc/rc.d/rc.local

编写剧本:

bash 复制代码
[root@zop ansible]# vim ansible_nginx.yml

---
- hosts: web2
  roles:
    - lnmp

运行剧本:

bash 复制代码
[root@zop ansible]# ansible-playbook ansible_nginx.yml 

2.数据库配置

  • 创建wordpress业务库
  • 授权数据库业务用户
    • 用户名:wpuser01@localhost(授权仅本机登录)
    • 密码:wordpress
bash 复制代码
[root@web1 ~]# mysql
#创建数据库wordpress,指定该数据库默认字符集为 utf8mb4
MariaDB [(none)]> CREATE DATABASE wordpress character set utf8mb4;
#创建wpuser01用户并仅授予 wordpress 数据库的全部权限(对其他数据库无权限),设置该数据库用户密码为 wordpress
MariaDB [(none)]> GRANT ALL ON wordpress.* TO wpuser01@localhost IDENTIFIED BY  'wordpress';
MariaDB [(none)]> FLUSH PRIVILEGES;        #刷新授权表

3.上线WordPress

  • wordpress-6.1.1-zh_CN.tar.gz上传至虚拟机web1的/root
  • 将代码上线至Nginx的网页根目录**/usr/local/nginx/html**
  • 注意:
    • php动态页面是由php-fpm程序处理的,它的进程所有者为apache
    • 所以上线的页面需要让apache用户有权限
bash 复制代码
[root@web1 ~]# tar -xf wordpress-6.1.1-zh_CN.tar.gz wordpress/
[root@web1 ~]# cp -r wordpress/* /usr/local/nginx/html/
[root@web1 ~]# chown -R apache:apache /usr/local/nginx/html/ #修改归属,让php-fpm服务有权限

4.WordPress初始化

填写数据库信息,指定数据库位置及连接用户

  • 一定要与之前创建的库、授权的用户保持一致

根据提示完成初始化,创建登录用户名admin,密码123456

安装完成

登录站点:

进入网站页面

可以进行以下基础业务操作:

  1. admin发布文章;
  2. 创建普通用户zhangsan,密码1234.com
  3. zhangsan登录评论文章;
  4. admin后台审核评论。
  5. 管理后台,可以修改主题风格等

阶段二:数据库解耦分离架构(性能瓶颈期)

2.1业务场景说明

线下推广曝光暴涨,日均访客5000,瞬时并发300~500,数据库日查询10万+;

单机Web与DB资源抢占,出现页面加载慢、数据库查询超时;

需求:Web、数据库进行解耦,实现资源隔离,拆分独立服务器。

2.2整体迁移流程

  1. web1单机备份wordpress数据库(mysqldump);
  2. 将备份数据库文件远程传输至database数据库主机;
  3. 在新的数据库主机(即database主机)创建同名库、授权远程访问账号;
  4. database主机导入备份的数据库数据;
  5. web1修改WordPress配置,指向远程数据库;
  6. 关闭web1本机mariadb服务。
2.2.1 web1备份数据库并传输
bash 复制代码
# 导出数据库备份文件
[root@web1 ~]# mysqldump -uroot wordpress > /root/wordpress.sql  
# scp远程拷贝至database主机
[root@web1 ~]# scp    /root/wordpress.sql   root@192.168.8.30:/root
2.2.2 database主机数据库环境初始化
  • 配置新的数据库服务器

    • 新数据库服务器database创建wordpress库
    • 授权用户:wpuser01@'%',密码:wordpress

    注意:database服务器上的数据库业务用户要允许在任意主机登录

bash 复制代码
# 安装数据库服务
[root@database ~]# dnf -y install mariadb-server mariadb
# 启动并开机自启
[root@database ~]# systemctl enable mariadb --now
# 验证3306端口
[root@database ~]# ss -nutlp | grep :3306
# 登录数据库执行建库、授权
[root@database ~]# mysql
#创建数据库并设置支持字符集
MariaDB [(none)]> CREATE DATABASE wordpress character set utf8mb4;
# 授权账号允许任意主机远程连接(@'%')
MariaDB [(none)]> GRANT ALL ON wordpress.* TO wpuser01@'%' IDENTIFIED BY  'wordpress';
#刷新授权表
MariaDB [(none)]> FLUSH PRIVILEGES;
2.2.3 database恢复备份数据
bash 复制代码
#还原数据
[root@database ~]# mysql -uroot wordpress < /root/wordpress.sql
2.2.4 web1测试远程数据库连通性

在web1进行连接测试:

bash 复制代码
[root@web1 ~]# mysql -h192.168.8.30 -uwpuser01 -p'wordpress'
MariaDB [(none)]>  SHOW TABLES FROM wordpress;  

可以看到WordPress库的表

2.2.5 修改WordPress数据库连接地址
  • 更新WordPress数据库连接
    • web服务器修改/usr/local/nginx/html/wp-config.php 文件
    • 更新数据库服务器地址:192.168.8.30
    • 停止web1本机的数据库服务
bash 复制代码
[root@web1 ~]# vim /usr/local/nginx/html/wp-config.php
 31 /** Database hostname */
 32 define( 'DB_HOST', '192.168.8.30' );              #指定数据库服务器地址
 
 #关闭本机数据库服务
 [root@web1 ~]# systemctl disable mariadb --now 

改成:

2.2.6 业务验证
  • 客户端访问测试
    • 数据库迁移之后,Windows客户端继续访问:http://192.168.8.11/
    • 编写文章,新产生的数据会存储在database数据库服务器

项目二期:负载均衡、共享存储、高可用集群

业务阶段说明

  • 阶段三:Web服务并发瓶颈阶段(负载均衡期)

    • 业务场景:线下春季文创展会预热活动开启,大量用户集中访问官网查看活动详情、预约展会名额。
    • 流量指标:日均独立访问1.2万人,高峰期瞬时并发访问2000,单节点Web服务QPS满载。
    • 核心痛点:单台Web服务器处理能力有限,高并发场景下CPU、带宽耗尽,出现页面打不开、请求超时、服务宕机等问题,无法承载峰值流量。
    • 架构要求:搭建Web负载均衡集群,新增多台Web应用节点,通过负载均衡设备实现流量分发,分担单节点压力,提升网站并发承载能力,解决高峰期服务瘫痪问题。
  • 阶段四:业务高可用保障阶段(集群高可用期)

    • 业务场景:全国文旅创意高峰论坛开启,官网开启线上门票售卖、直播预约、作品投稿功能,业务直接关联企业营收,故障零容忍。
    • 流量指标:高峰期瞬时并发访问8000,7×12小时持续高负载运行,全年无停机维护窗口期。
    • 核心痛点:单负载均衡节点、单数据库节点存在严重单点故障风险,一旦服务器宕机、服务异常,会直接导致全站瘫痪,造成门票订单丢失、品牌口碑受损、直接经济损失。
    • 架构要求搭建高可用代理集群+数据库主从架构,实现核心服务冗余备份,杜绝单点故障;实现服务故障自动切换,保障业务7×24小时稳定运行。
  • 通过Nginx/Haproxy代理或LVS调度实现web负载均衡

    • 增加Keepalived保持代理服务器的高效可用
    • 选择web1主机充当ansible的控制节点

阶段三:Web服务并发瓶颈阶段(负载均衡期)

3.1 Web站点扩展

  • 将web1主机的WordPress网站页面上传至服务器web2、web3
  • 使web2、web3也可以独立运行WordPress
  • 实际生产环境建议提前发布升级更新公告
3.1.1 web2web3部署LNMP

使用之前提前部署好的ansible批量部署web2和web3的lnmp架构:

ansible的tasks文件和脚本在前文已经写好,这里不再引用

只需要对剧本进行细微修改即可:

yaml 复制代码
---
- hosts: web2,web3
  roles:
    - lnmp
3.1.2 打包wordpress文件内容

打包web1中的wordpress文件内容并循环分发到web2web3

bash 复制代码
#打包指定目录下的数据
[root@web1 ~]# tar -zcf wordpress.tar.gz -C /usr/local/nginx/html .
#将打包页面拷贝至web2、web3
[root@web1 ~]# for i in 192.168.8.12 192.168.8.13
> do
> scp /root/wordpress.tar.gz root@$i:/root 
> done
3.1.3 批量上线WordPress

使用之前已经部署过的ansible进行远程批量部署

回到我们的控制主机zop进行操作:

bash 复制代码
#上线WordPress
[root@zop ansible]# ansible web1,web2 -m shell -a "tar -xf /root/wordpress.tar.gz -C /usr/local/nginx/html/"
#确保php-fpm有权限
[root@zop ansible]# ansible web1,web2 -m shell -a "chown -R apache:apache /usr/local/nginx/html/"
#重启php-fpm服务
[root@zop ansible]# ansible web1,web2 -m shell -a "systemctl restart php-fpm"
3.1.4 当前架构缺陷
  1. 图片、附件存储在单台Web本地,负载均衡轮询至其他节点时图片丢失;
  2. 网站代码更新需要逐台Web服务器操作,维护效率极低;
    解决方案:NFS统一共享存储,所有Web挂载同一套网站代码与上传目录。
3.1.5 小结与反思
  • 目前3台web服务器均可以独立上线WordPress
  • 但是目前如果访问http://192.168.8.11,发表含有图片的文章
  • 图片会存储在web1的**/usr/local/nginx/html/wp-content/upload/年/月/日**
  • 如果请求轮询至web1发布文章,存储图片至web1
  • 查看文章时,请求轮询至web2,有可能web2本地找不到此图片
  • 其他业务场景中,此问题必须考虑,解决方案可以考虑对象存储
  • 目前wordpress图片在数据库中存储的是一个路径,路径指向了web1,调用时还找web1
  • 但如果遇到了wordpress代码需要迭代更新,难道每一个主机都要单独更新吗?

3.2 NFS共享存储统一网站资源

  • nfs1主机搭建NFS共享服务,共享/nfs_share目录
  • 将web1主机的WordPress代码迁移至nfs1服务器的共享目录/nfs_share
  • 所有web服务器挂载nfs1服务器共享的/nfs_share
3.2.1 nfs1部署NFS服务端
bash 复制代码
#下载软件包
[root@nfs1 ~]# dnf -y install nfs-utils rpcbind
#共享/nfs_share目录
[root@nfs1 ~]# vim /etc/exports
/nfs_share  192.168.8.0/24(rw,no_root_squash,sync)
#启动服务并设置开启自启
[root@nfs1 ~]# systemctl enable rpcbind --now
[root@nfs1 ~]# systemctl enable nfs-server --now
#查看nfs共享清单
[root@nfs1 ~]# showmount -e
Export list for nfs1:
/nfs_share 192.168.8.0/24
3.2.2 web1网站代码迁移至NFS共享
bash 复制代码
# 打包站点代码。之前做过可以不做
[root@web1 ~]# tar -zcf wordpress.tar.gz -C /usr/local/nginx/html .  
# 传输至nfs1
[root@web1 ~]# scp wordpress.tar.gz  root@192.168.8.41:/root

nfs1将web文件解压至共享目录:

bash 复制代码
[root@nfs1 ~]# tar -xf wordpress.tar.gz -C /nfs_share/
3.2.3 三台Web服务器永久挂载NFS共享

下一步需要将NFS共享的目录分别挂载至三个web主机

因为三台主机操作完全一致,所以可以使用ansible批量一键部署。

回到zop主机操作:

bash 复制代码
#删除现有本地页面文件
[root@zop ansible]# ansible webserver -m shell -a "rm -rf /usr/local/nginx/html/*  "
#安装nfs文件系统
[root@zop ansible]# ansible webserver -m shell -a "dnf -y install nfs-utils"
#永久挂载共享数据
[root@zop ansible]# ansible webserver -m lineinfile -a "path=/etc/fstab line='192.168.8.41:/nfs_share   /usr/local/nginx/html   nfs    defaults,_netdev   0   0' state=present"
#刷新挂载
[root@zop ansible]# ansible webserver -m shell -a "mount -a"
#查看挂载验证
[root@zop ansible]# ansible webserver -m shell -a "df -h"

NFS架构优势:

  1. 所有Web节点共用一套网站代码,统一更新,无需逐台发布;
  2. 文章上传图片统一存放在共享存储,任意Web节点访问均可加载图片;

阶段四:业务高可用保障阶段(集群高可用期)

4.1 负载均衡选型对比

  • 可选方案:
    • Nginx
    • LVS
    • Haproxy
      本项目选用Haproxy适配7层Web业务
      配合Keepalived实现双机热备,消除负载均衡单点故障。
4.1.1 搭建负载均衡集群

两台haproxy主机的配置操作过程一模一样,因此我们可以结合ansible简化批量操作

在zop主机批量安装haproxy:

bash 复制代码
[root@zop ansible]# ansible haserver -m shell -a "dnf -y install haproxy"

编辑haproxy1的配置文件:

bash 复制代码
[root@haproxy1 ~]# vim  /etc/haproxy/haproxy.cfg 
......删除64行之后的内容,并加入以下内容......
listen websrv
   bind *:80
   balance roundrobin
   server web1 192.168.8.11:80 check inter 2000 rise 2 fall 5
   server web2 192.168.8.12:80 check inter 2000 rise 2 fall 5
   server web3 192.168.8.13:80 check inter 2000 rise 2 fall 5

编辑haproxy2的配置文件:

bash 复制代码
[root@haproxy2 ~]# vim  /etc/haproxy/haproxy.cfg 
......删除64行之后的内容,并加入以下内容......
listen websrv
   bind *:80
   balance roundrobin
   server web1 192.168.8.11:80 check inter 2000 rise 2 fall 5
   server web2 192.168.8.12:80 check inter 2000 rise 2 fall 5
   server web3 192.168.8.13:80 check inter 2000 rise 2 fall 5

在控制节点zop主机批量启动服务:

bash 复制代码
[root@zop ansible]# ansible haserver -m shell -a "systemctl enable haproxy --now  "

4.2 搭建keepalived服务

因为搭建keepalive需要进行的配置有所差异,我们需要分别进行配置

4.2.1haproxy1主机搭建keepalived服务:

设置浮动IP(VIP):192.168.4.50

bash 复制代码
[root@haproxy1 ~]# dnf -y install keepalived
[root@haproxy1 ~]# vim /etc/keepalived/keepalived.conf

修改文件内容:

bash 复制代码
! Configuration File for keepalived

global_defs {
   notification_email {
     kisaki@gmail.com                       #设置邮箱。发生故障时会给这个邮箱发邮件
   }
   notification_email_from root@localhost   #设置发件人邮箱
   smtp_server 192.168.8.5                  #邮箱服务器的地址
   smtp_connect_timeout 30
   router_id LVS_1                          #路由ID,两台主机不能相同
   vrrp_skip_check_adv_addr
   vrrp_strict
   vrrp_garp_interval 0
   vrrp_gna_interval 0
}

vrrp_instance VI_1 {
    state MASTER                             #角色为:主
    interface ens160                         #VIP的绑定网卡
    virtual_router_id 51                     #集群ID,主备必须一致
    priority 100                             #优先级
    advert_int 1
    authentication {
        auth_type PASS
        auth_pass 1111
    }
    virtual_ipaddress {
        192.168.4.50                          #VIP
    }
}
......因为我们不配置LVS,后面的内容可以全部删除......

关于keepalive配置文件本处不作过多解释,若有需要可以前往:# Linux运维Day05:Keepalived热备基础,Keepalived+LVS实现负载均衡

启动服务并验证VIP:

bash 复制代码
[root@haproxy1 ~]# systemctl enable keepalived --now
[root@haproxy1 ~]# ip a s ens160

可以看到VIP4.50已经绑定到ens160网卡上

4.2.2haproxy2主机搭建keepalived服务:

设置浮动IP(VIP):192.168.4.50

bash 复制代码
[root@haproxy2 ~]# dnf -y install keepalived
[root@haproxy2 ~]# vim /etc/keepalived/keepalived.conf

修改文件内容:

bash 复制代码
! Configuration File for keepalived

global_defs {
   notification_email {
     kisaki@gmail.com
   }
   notification_email_from root@localhost
   smtp_server 192.168.8.6
   smtp_connect_timeout 30
   router_id LVS_2
   vrrp_skip_check_adv_addr
   vrrp_strict
   vrrp_garp_interval 0
   vrrp_gna_interval 0
}

vrrp_instance VI_1 {
    state BACKUP
    interface ens160
    virtual_router_id 51
    priority 80
    advert_int 1
    authentication {
        auth_type PASS
        auth_pass 1111
    }
    virtual_ipaddress {
        192.168.4.50
    }
}

启动服务并验证VIP:

bash 复制代码
[root@haproxy2 ~]# systemctl enable keepalived --now
[root@haproxy1 ~]# ip a s ens160

这里是看不到ens160网卡上的VIP的。因为VIP现在在nfs1主机。当nfs1宕机/出故障,VIP将会飘到nfs2主机

4.3 业务验证与故障测试

  1. 客户端访问统一入口 http://192.168.4.50(VIP);
  2. 三台Web执行 tail -f /usr/local/nginx/log/access.log,刷新页面可见流量轮询分发;
  3. 模拟haproxy1主节点宕机,VIP自动漂移至haproxy2,客户端访问无中断。

项目三期:数据库集群与Zabbix监控平台

阶段五:数据库集群(NFS实时备份,数据库主从同步)与Zabbix监控

  • NFS升级可以考虑Ceph分布式存储平台,但由于资源有限采用现有办法升级
  • 数据库从业务层面也有很多升级方案,后续学习,这里做主从同步即可

5.1 NFS实时备份

NFS数据同步我们采用:Inotifywait + rsync结合shell脚本完成

inotify-tools-3.13.tar.gz源码包上传至虚拟机nfs1的/root

bash 复制代码
#安装依赖和rsync
[root@nfs1 ~]# dnf  -y  install gcc  gcc-c++  make rsync
#释放源码包
[root@nfs1 ~]# tar    -xf    inotify-tools-3.13.tar.gz    -C    /usr/src/
#切入目录,进行初始化
[root@nfs1 ~]# cd /usr/src/inotify-tools-3.13/
[root@nfs1 inotify-tools-3.13]# ./configure 
#编译并安装
[root@nfs1 inotify-tools-3.13]# make
[root@nfs1 inotify-tools-3.13]# make install
5.1.1 编写实时备份脚本

nfs1服务器实现无密码管理nfs2服务器

bash 复制代码
#生成密钥对
[root@nfs1 ~]# ssh-keygen  -f '/root/.ssh/id_rsa'  -N '' 
#分发密钥对
[root@nfs1 ~]# ssh-copy-id root@192.168.8.42

编写同步脚本:

bash 复制代码
[root@nfs1 ~]# vim /opt/nfsrsync.sh
#!/bin/bash
while  inotifywait -rqq /nfs_share/
do
  rsync -az --delete /nfs_share/ root@192.168.8.42:/nfs_share/
  #要注意目录结尾的斜杠:/ 
done
#赋予权限
[root@nfs1 ~]# chmod +x /opt/nfsrsync.sh
#后台执行脚本
[root@nfs1 ~]# /opt/nfsrsync.sh &
5.1.2 nfs同步验证

回到nfs2主机上,也要安装rsync软件:

bash 复制代码
[root@nfs2 ~]# dnf -y install rsync

验证nfs同步:

bash 复制代码
#在nfs1主机对/nfs_share/目录进行查看操作
[root@nfs1 ~]# ls /nfs_share/
#回到nfs2主机,查看根目录,发现/nfs_share目录已经被同步
[root@nfs2 ~]# ls /
bin   dev  home  lib64  mnt    nfs_share  proc  run   srv  tmp  var
boot  etc  lib   media  mydvd  opt        root  sbin  sys  usr

5.2 数据库主从同步

  • 数据库主从同步是一项自动备份数据的技术,可实现从库实时备份主库数据
  • database主机备份数据,授权主从用户,备份数据 将nfs2 兼为从数据库服务器(性能允许的情况下也可以单独开一个新的虚拟机)
  • database主机指定开启binlog日志,指定server_id
  • 授权主从同步用户:repluer ,密码:1234.com
5.2.1 database主机指定开启binlog日志,指定server_id
bash 复制代码
[root@database ~]# vim /etc/my.cnf.d/mariadb-server.cnf
#在配置文件[mysql]之下添加两行配置
16 [mysqld]
#开启二进制日志,用于主从,还能做数据恢复。开启log-bin是搭建主从同步的前提条件
17 log-bin=master
#给当前 MySQL 实例分配唯一服务 ID,是主从复制强制要求的参数
18 server_id=30 

#重启服务
[root@database ~]# systemctl restart mariadb

5.3 搭建Zabbix监控平台

搭建Zabbix监控平台具体分为两步:

  1. 配置LNMP
  2. 部署Zabbix

由于Zabbix对nginx的配置,php和mariadb的版本有特殊要求,所以无法使用之前的一键部署LNMP平台的脚本和剧本,需要进行更细化的配置,并且准备好安装包

5.3.1 部署nginx

使用之前部署nginx的脚本快速部署nginx

脚本内容:

bash 复制代码
#!/bin/bash
dnf -y install gcc make pcre-devel openssl-devel
useradd nginx
tar -xf /root/nginx-1.22.1.tar.gz
cd nginx-1.22.1
./configure --prefix=/usr/local/nginx --user=nginx --group=nginx --with-http_ssl_module --with-http_stub_status_module
make && make install
ls /usr/local/nginx

nginx-1.22.1.tar.gz提前上传至zop主机的/root目录

运行脚本:

bash 复制代码
[root@zop ~]# . /root/ansible/nginx.sh 

修改nginx.conf配置文件,支持 PHP 动态请求:

bash 复制代码
[root@zop ~]# vim /usr/local/nginx/conf/nginx.conf

[root@zop ~]# vim /usr/local/nginx/conf/nginx.conf
...略...
http{
...略...
  fastcgi_buffers 8 16k;                #缓存php生成的页面内容,8个16k
  fastcgi_buffer_size 32k;              #缓存php生产的头部信息
  fastcgi_connect_timeout 300;          #连接PHP的超时时间
  fastcgi_send_timeout 300;             #发送请求的超时时间
  fastcgi_read_timeout 300;             #读取请求的超时时间
  ...略...
  server {
  ...略...
  location ~ \.php$ {                   #配置nginx支持php动态请求
              root           html;
              fastcgi_pass   127.0.0.1:9000;
              fastcgi_index  index.php;
              #注释此行
              #fastcgi_param  SCRIPT_FILENAME  /scripts$fastcgi_script_name;
              #修改为fastcgi.conf
              include        fastcgi.conf;
        }
  ...略...
}
5.3.2 配置php

安装php相关软件:zabbix要求php-7.4以上版本,所以采用离线安装

将php7.4.tar.gz上传至zop主机的/root

bash 复制代码
[root@zop ~]# tar -xf php7.4.tar.gz            #解压压缩包
[root@zop ~]# cd php74/                        #切换至工作目录
[root@zop php74]# dnf -y localinstall *.rpm    #安装php相关软件
[root@zop php74]# vim /etc/php-fpm.d/www.conf  #修改php-fpm配置文件,支持9000端口
...约第38行...
#注释这一行
38 ;listen = /run/php-fpm/www.sock
#添加此行
39 listen = 127.0.0.1:9000
...略...
[root@zop php74]# php -v                        #查看php版本为7.4.19
PHP 7.4.19 (cli) (built: May  4 2021 11:06:37) ( NTS )
Copyright (c) The PHP Group
Zend Engine v3.4.0, Copyright (c) Zend Technologies
    with Zend OPcache v7.4.19, Copyright (c), by Zend Technologies
5.3.3 配置mariadb

Zabbix 6.4.7 要求 MariaDB 版本 ≥ 10.6,但内置的版本不满足条件,因此同样采用离线安装。将 mariadb10.6.tar.gz 上传至zop主机的 /root 目录:

bash 复制代码
#解压软件包
[root@zop ~]# tar -xf  mariadb10.6.tar.gz 
#切入mariadb目录
[root@zop ~]# cd mariadb10.6/
#安装mariadb相关软件 
[root@zop mariadb10.6]# dnf -y localinstall *.rpm 
5.3.4 启动服务

启动LNMP相关服务,并编写测试页面

bash 复制代码
#启动mariadb
[root@zop mariadb10.6]# systemctl enable  mariadb --now  
#启动php-fpm
[root@zop mariadb10.6]# systemctl enable  php-fpm --now
#启动nginx。可以写service文件实现systemctl控制
[root@zop mariadb10.6]# /usr/local/nginx/sbin/nginx
#编写测试页面:
[root@zop mariadb10.6]# vim   /usr/local/nginx/html/test.php
<?php
$i=33;
echo $i;
?>
#访问测试:
[root@zop mariadb10.6]# curl 192.168.8.100/test.php
33[root@zop mariadb10.6]# 
5.3.5 zabbix监控端部署
bash 复制代码
#安装依赖
[root@zop ~]# dnf -y install net-snmp-devel libcurl-devel libevent-devel libxml2-devel  
#创建zabbix启动用户
[root@zop ~]# useradd -s /sbin/nologin zabbix
#解压:
[root@zop ~]# tar -xf zabbix-6.4.7.tar.gz  
#切入软件包目录
[root@zop ~]# cd zabbix-6.4.7/
#初始化编译
[root@zop zabbix-6.4.7]# ./configure \  #配置zabbix,初始化zabbix
> --enable-server \        #支持zabbix监控功能(服务端)
> --enable-agent \        #支持zabbix被监控功能(客户端)
> --with-mysql \          #让zabbix支持mysql/mariadb数据库
> --with-net-snmp \       #支持 SNMP 监控(用于网络设备、服务器硬件)
> --with-libcurl \        #支持 Web 监控、API 监控、HTTPS
> --with-libxml2          #支持 XML 数据解析(配合监控使用)

#安装zabbix
[root@zop zabbix-6.4.7]# make install
#查看配置文件验证:
[root@zop zabbix-6.4.7]# ls /usr/local/etc/
zabbix_agentd.conf    zabbix_server.conf
zabbix_agentd.conf.d  zabbix_server.conf.d
[root@zop zabbix-6.4.7]# ls /usr/local/bin/
zabbix_get  zabbix_js  zabbix_sender
[root@zop zabbix-6.4.7]# ls /usr/local/sbin/
zabbix_agentd  zabbix_server
5.3.6 Zabbix数据库配置
  • 创建zabbix服务存储监控数据的数据库:zabbix库
  • 授权php网页使用的连接用户:zabbix ,密码:zabbix
bash 复制代码
#进入数据库
[root@zop ~]# mysql
#创建zabbix数据库,支持中文字符集
MariaDB [(none)]> CREATE DATABASE zabbix CHARACTER SET utf8 COLLATE utf8_bin;
#授权用户zabbix,密码为zabbix
MariaDB [(none)]> GRANT ALL  ON zabbix.*  to zabbix@"localhost" IDENTIFIED BY 'zabbix';
#刷新授权表立即生效
MariaDB [(none)]> FLUSH PRIVILEGES ;
#退出数据库
MariaDB [(none)]> exit

使用zabbix模板文件还原数据库(zabbix自带)

导入 Zabbix 数据库模板文件(注意顺序不能颠倒):

bash 复制代码
#切入存放数据库文件的目录
[root@zop ~]# cd zabbix-6.4.7/database/mysql/
#恢复数据,注意顺序
[root@zop mysql]# mysql -uzabbix -pzabbix zabbix < schema.sql
[root@zop mysql]# mysql -uzabbix -pzabbix zabbix < images.sql
[root@zop mysql]# mysql -uzabbix -pzabbix zabbix < data.sql
5.3.7 初始化zabbix

将zabbix的php监控页面发布至Nginx的网页根目录

bash 复制代码
#切入web目录
[root@zop mysql]# cd /root/zabbix-6.4.7/ui/
#将页面递归拷贝放到web根目录
[root@zop ui]# cp -r * /usr/local/nginx/html/ 
#授予权限,实验环境临时赋权方便排错,生产环境不建议使用777最大权限
[root@zop ui]# chmod  -R 777 /usr/local/nginx/html/

为满足zabbix初始化,需要修改php相关配置,否则在初始化的时候会提示异常

修改配置文件:/etc/php.ini

bash 复制代码
[root@zop ui]# vim /etc/php.ini            #修改配置文件,不要抄行号,以实际情况为主
923 date.timezone = Asia/Shanghai          #时区调整为 Asia/Shanghai
694 post_max_size = 32M                    #最大执行时间,秒
388 max_execution_time = 300               #POST(上传提交)数据最大容量
398 max_input_time = 300                   #服务器接收数据的时间限制
# 重启 PHP-FPM 使配置生效
[root@zop ui]# systemctl restart php-fpm

在 Windows 浏览器中访问 http://192.168.8.100/index.php,按照以下步骤完成初始化:

配置zabbix连接mariadb数据库,用户名:zabbix ,密码zabbix(我们之前授权的数据库用户密码)

设置zabbix服务器的名字:zabbix-server

汇总信息确认,点击下一步

初始化成功

  • 登录zabbix管理页面
    • 用户名:Admin
    • 密码:zabbix

会发现全是红色,这是因为系统(Linux 系统)缺少 en_US.UTF-8 语言区域配置

点击左下角用户头像 → "User settings" → "Language" 选择 "Chinese (zh_CN)",点击 "Update" 即可切换为中文界面。

再返回首页,已经可以正常显示

5.3.8 启动zabbix服务
  • 配置数据库:修改zabbix_server服务端配置文件,启动zabbix_server服务
bash 复制代码
[root@zop ui]# vim /usr/local/etc/zabbix_server.conf
87 DBHost=localhost                               #数据库主机(去掉注释顶格写)
99 DBName=zabbix                                  #设置数据库名称
115 DBUser=zabbix                                 #设置数据库账户
123 DBPassword=zabbix                             #设置数据库密码(去掉注释顶格写))
38 LogFile=/tmp/zabbix_server.log                 #设置日志
  • 启动zabbix相关服务
    • 启动zabbix_server服务,端口号:10051
    • 启动zabbix_agent服务,端口号:10050
bash 复制代码
#启动服务端
[root@zop ui]# zabbix_server 
[root@zop ui]# ss -nutlp | grep :10051 
#启动客户端
[root@zop ui]# zabbix_agentd 
[root@zop ui]# ss -nutlp | grep :10050

#将服务设置为开启自启
[root@zop ui]# echo zabbix_server >> /etc/rc.d/rc.local
[root@zop ui]# echo zabbix_agentd >> /etc/rc.d/rc.local
[root@zop ui]# chmod +x /etc/rc.d/rc.local
5.3.9 zabbix被监控端部署

所有的被监控主机均需要进行源码编译安装zabbix_agent。所以我们可以结合ansible使用剧本快速批量部署zabbix。

被监控端具体操作分为三步:

  1. 编写批量部署的剧本
  2. 事先将zabbix-6.4.7.tar.gz上传至虚拟机zop(即ansible控制节点)的/root目录
  3. 修改被监控端配置文件

编写剧本zabbix.yml:

yaml 复制代码
- hosts: web1  #先在web1上部署
  become: yes
  tasks:
    #  拷贝文件 
    - name: 拷贝压缩包
      copy:
        src: /root/zabbix-6.4.7.tar.gz
        dest: /opt/zabbix-6.4.7.tar.gz

    #  安装依赖
    - name: 安装依赖
      dnf:
        name:
          - gcc
          - pcre-devel
          - autoconf
          - make
          - zlib-devel
        state: present

    #  解压文件
    - name: 解压
      unarchive:
        src: /opt/zabbix-6.4.7.tar.gz
        dest: /opt
        remote_src: yes

    #  编译安装
    - name: 编译安装
      shell: |
        ./configure --enable-agent
        make install
      args:
        chdir: /opt/zabbix-6.4.7

运行剧本:

bash 复制代码
[root@zop ansible]# ansible-playbook zabbix.yml

修改被监控端配置文件

  • web1主机操作
bash 复制代码
[root@web1 ~]# vim /usr/local/etc/zabbix_agentd.conf
113 Server=127.0.0.1,192.168.8.100                #允许访问服务地址列表,即允许谁监控我
167 ServerActive=192.168.8.100:10051              #监控服务器ip地址和端口
30 LogFile=/tmp/zabbix_agentd.log                 #日志文件
#创建启动用户
[root@web1 ~]# useradd -s /sbin/nologin zabbix
#启动服务:
[root@web1 ~]# zabbix_agentd  
#查看端口
[root@web1 ~]# ss -nutlp | grep :10050 
 #将服务设置为开机自启
[root@web1 ~]# echo zabbix_agentd >> /etc/rc.d/rc.local
#赋予文件执行权限
[root@web1 ~]# chmod +x /etc/rc.d/rc.local  
5.3.10 基础监控配置

登录 Zabbix Web 界面,点击左侧菜单栏 监测 → 主机 → 创建主机

填写主机信息:

主机名称:web1 (尽可能与真实主机名保持一致)

可见的名称:web1

主机群组:选择 Linux servers

接口:类型选择 Agent ,IP 地址填写 192.168.8.11 (即被监控主机web1的IP地址),端口保持 10050

在模板框搜索并添加 Linux by Zabbix agent 模板,选择完毕点击添加

添加完毕,点击监测 → 主机 → 最新数据

在这里就可以查看当前所有的监控项了

至此,本项目框架已经部署完毕。

当然,对于真正的上线项目而言,本项目还有待优化的地方,优化项将于后续在本文更新