记录aws云服务器,宝塔nginx负载均衡通过共享目录实现
生产环境使用amazon linux2,对 GlusterFS的使用有些困难,决定使用ansible+sync+inotify-tools来完成宝塔管理的nginx负载均衡 通过ansible调用sync模块同步负载节点的配置,保证和主节点一样,用inotifywait写脚本持续监控目录,配置目录有变化则执行ansible-playbook,在宝塔的reload脚本内加入ansible剧本,实现同时触发reload操作 对新开启的服务器安装openresty服务,然后用ansible创建出必要的目录
---
- name: 同步www目录到所有服务器
hosts: nginx_upstream
become: true # 提权
tasks:
- name: 创建 www 用户
user:
name: www
comment: "Web server user"
shell: /bin/false # 禁止登录
home: /www # 指定主目录
state: present # 确保用户存在
- name: 创建 /www 目录
file:
path: /www
state: directory
owner: root
group: root
mode: '0755'
- name: 创建 /www/server/nginx 目录
file:
path: /www/server/nginx
state: directory
owner: root
group: root
mode: '0755'
- name: 创建 /www/server/nginx/conf 目录
file:
path: /www/server/nginx/conf
state: directory
owner: root
group: root
mode: '0755'
- name: 创建 /www/wwwroot 目录
file:
path: /www/wwwroot
state: directory
owner: root
group: root
mode: '0755'
- name: 创建 /www/server/panel 目录
file:
path: /www/server/panel
state: directory
owner: root
group: root
mode: '0755'
- name: 创建 /www/wwwlogs 目录
file:
path: /www/wwwlogs
state: directory
owner: www
group: www
mode: '0700'
- name: 创建 /dev/shm/nginx-cache/wp/ 目录
file:
path: /dev/shm/nginx-cache/wp/
state: directory
owner: www
group: www
mode: '0755'
- name: 创建 /www/server/nginx/logs 目录
file:
path: /www/server/nginx/logs
state: directory
owner: root
group: root
mode: '0755'
然后在写一个同步nginx所有配置目录和必要文件的剧本
---
- name: 同步www目录到所有服务器
hosts: nginx_upstream
become: true # 提权
serial: 2 # 同时对 2 台服务器执行同步
tasks:
- name: 同步 www/server/panel/vhost/ 目录到目标服务器
synchronize:
src: /www/
dest: /www/
archive: true # 保留权限、时间戳等
delete: true # 删除目标中不在源中的文件
rsync_opts:
- "--exclude=server/panel/data/"
- "--exclude=wwwlogs/"
- "--exclude=server/panel/config/"
- "--exclude=server/panel/logs/"
- "--exclude=server/nginx/nginx/logs/"
- "--exclude=server/panel/cache/thumbnail/"
- "--exclude=backup/"
--exclude是指定不同步的目录,写绝对路径会导致同步速度变慢,这里都是用相对路径 手动执行一次剧本,如果目录内文件多,第一次同步会比较慢 同步完成,然后需要解决在宝塔中保存证书或者更新配置后自动触发同步并且reload的问题 宝塔的nginx pid号默认是在nginx的配置目录中,之前我们同步过去会导致所有服务器都使用同一个pid号,所以在主节点换一个pid文件的目录,改成/run/nginx.pid 然后在同步一下,可以检查针对这次修改同步的速度和结果是否符合预期,修改了pid文件的路径,找到主节点宝塔的nginx脚本,同样要修改一下,一般是 /etc/init.d/nginx 这个路径 修改后回到宝塔reload,看看服务的线程pid是否有变化,如果变了就正常,然后写一个reload的剧本,手动测试一下可以让负载服务器的nginx正常reload
---
- name: reload
hosts: nginx_upstream
become: true # 提权
tasks:
- name: 重启 Nginx 服务(server1)
shell: openresty -s reload -c /www/server/nginx/conf/nginx.conf
执行后登陆到其他节点看下线程pid是否有变化,没什么问题需要把这个剧本加入到宝塔nginx的脚本内 我在这里添加了等待5秒后执行重启,为了给同步留一点时间,如果立马重启可能会导致数据还没同步完全,并且加了一个日志的记录 然后去宝塔可以做一个配置添加或者直接对站点修改,测试是否可以触发reload,并且观察日志 如果没有问题,之后下载使用inotify-tools inotify-tools 是一组基于 Linux 内核中的 inotify 子系统的命令行工具和库,用于监控文件系统的事件。它包含以下两个主要工具:
inotifywait:用于等待文件系统上的事件。 inotifywatch:用于收集文件系统事件的统计信息。 我们用inotifywait这个命令来监控nginx配置和资源目录,出现变动后调用ansible的剧本来执行同步,可以做到实时同步资源和配置到所有负载服务器 下载好命令后添加一个脚本
#!/bin/bash
WATCHED_DIRS=( "/www/" )
EXCLUDED_DIRS=( "/www/server/panel/data/" "/www/wwwlogs/" "/www/server/panel/config/" "/www/server/panel/logs/" "/www/server/nginx/nginx/logs/" "/www/server/panel/cache/thumbnail/" "/www/backup/" ) # 定义排除的多个目录
PLAYBOOK="/root/upstream/sync.yaml" # Ansible Playbook 的路径
INVENTORY="/etc/ansible/hosts" # Ansible Inventory 文件路径
LOGFILE="/var/log/upstream_sync.log" # 日志文件
BUFFER_FILE="/tmp/sync_inotify_buffer" # 暂存文件变化记录的缓冲区文件
DELAY=3 # 延迟执行的秒数
# 确保日志文件和缓冲文件可写
touch $LOGFILE
chmod 644 $LOGFILE
touch $BUFFER_FILE
chmod 644 $BUFFER_FILE
echo "$(date) - Starting directory watch on ${WATCHED_DIRS[*]}" >> $LOGFILE
# 定义函数来触发 Ansible Playbook 执行并清空缓冲区
run_playbook() {
echo "$(date) - Running Ansible Playbook due to changes in:" >> $LOGFILE
cat $BUFFER_FILE >> $LOGFILE
ansible-playbook -i $INVENTORY $PLAYBOOK >> $LOGFILE 2>&1
# 清空缓冲区
: > $BUFFER_FILE
}
# 将排除目录转为正则表达式,供 inotifywait 使用
EXCLUDE_REGEX=$(printf "%s|" "${EXCLUDED_DIRS[@]}" | sed 's/\/$/\//' | sed 's/|$//')
# 开始监控目录
inotifywait -m -r -e modify,create,delete --exclude "${EXCLUDE_REGEX}" "${WATCHED_DIRS[@]}" | while read path action file; do
echo "$(date) - Checking path: $path$file against exclusions: ${EXCLUDE_REGEX}" >> $LOGFILE
# 将检测到的文件变化记录到缓冲区
echo "$path$file" >> $BUFFER_FILE
# 如果没有其他进程在等待,设置一个延迟执行 Playbook 的任务
if [[ ! -f /tmp/ansible_task_scheduled ]]; then
echo "$(date) - Detected event for $path$file" >> $LOGFILE
touch /tmp/ansible_task_scheduled
# 设置延迟执行任务
(
sleep $DELAY
run_playbook
rm /tmp/ansible_task_scheduled
) &
else
echo "$(date) - Collecting event for $path$file" >> $LOGFILE
fi
done
修改这个脚本满足自己的需要,添加一个system管理,可以做到后台持续运行
cat /etc/systemd/system/monitor.service
[Unit]
Description=目录监控并触发 Ansible 的脚本
After=network.target
Requires=network.target
[Service]
Type=simple
ExecStart=/root/upstream/monitor.sh #脚本路径
Restart=always
RestartSec=5
User=root
Group=root
StandardOutput=syslog
StandardError=syslog
SyslogIdentifier=dir_watch
[Install]
WantedBy=multi-user.target
启动脚本后尝试手动对监控目录做修改,然后检查是否有同步打到想要的结果