Shell脚本一键部署LNMP
环境
CentOS8+nginx+mysql5.7+django+uwsgi
实现反向代理,负载均衡,高可用,静态资源共享,动静分离等效果
名称 | IP | hostname | 软件 | 启动服务 |
---|---|---|---|---|
nfs备份 | 192.168.10.5 | nfs-backup | rsync-daemon | rsyncd |
nfs服务器 | 192.168.10.15 | nfs-server | nfs-utils rsync sersync | rpcbind nfs-server sersync2 |
数据库 | 192.168.10.20 | database-mysql | mysql-devel mysql-server | mysqld |
web服务器1 | 192.168.10.30 | web1 | python36 python3-devel gcc nfs-utils libjpeg-devel zlib-devel libtiff-devel net-tools | uwsgi |
web服务器2 | 192.168.10.31 | web2 | 和web1保持一致 | uwsgi |
nginx静态服务器1 | 192.168.10.40 | nginx1 | nfs-utils nginx keepalived net-tools tcpdump | nginx keepalived |
nginx静态服务器2 | 192.168.10.41 | nginx2 | 和nginx1保持一致 | nginx keepalived |
LVS负载均衡器主机 | 192.168.10.10 | lvs1 | net-tools tcpdump ipvsadm | keepalived |
LVS负载均衡器从机 | 192.168.10.11 | lvs2 | 和lvs1保持一致 | keepalived |
master | 192.168.10.110 | shell-master | sshpass(centos8需要通过压缩包安装) |
脚本作用
onekey_start.sh
远程连接,分发项目、脚本、软件包,远程执行对应脚本
server_ini.sh
初始化yum,关闭防火墙,配置时间同步,添加主机名映射
onekey_nfsbackup
配置rsync-daemon,作nfs-server的备份机器
onekey_nfsserver
二进制安装并配置sersync,配置nfs网络共享,共享静态资源,实时同步文件给备份机
onekey_database
二进制方式搭建mysql5.7
onekey_uwsgi
实现uwsgi+django的部署,使用nfs共享的静态文件
onekey_nginx
配置虚拟IP、实现对uwsgi的七层代理,使用nfs共享的静态文件
onekey_lvs1
配置虚拟IP+keepalived高可用,实现对nginx的负载均衡
onekey_lvs2
lvs1的从机,当lvs1无法正常工作时,接管对应服务和VIP
架构图
部署
准备上述机器并配置好静态IP,master要求能够上网,ssh服务正常
上传下列文件到master的:/home下
sersync二进制包
MySQL5.7二进制包
django项目
master脚本存放地址 : /home/scripts(所有脚本存放在该路径下,包括为数据库插入数据的sql脚本)
# 目录结构
/home
/scripts
onekey...
sersync2.5.4_64bit_binary_stable_final.tar.gz
mysql-5.7.43-linux-glibc2.12-x86_64.tar
/django项目
启动所有机器,进入master机
cd /home/scripts && chmod u+x /home/scripts/* && ./onekey_start.sh
脚本
onekey_start.sh
注意:
如果IP和上述配置不一致,修改为自己机器的IP
修改分发文件的名字,django项目名(本次实验的项目名:wuyu),sersync和mysql二进制包名为自己下载的名字
#!/bin/bash
# 改成自己想要在远程以什么身份登入
username="root"
password="123456"
# 改成自己机器的IP
nginx1="192.168.10.40"
nginx2="192.168.10.41"
web1="192.168.10.30"
web2="192.168.10.31"
database="192.168.10.20"
nfsserver="192.168.10.15"
nfsbackup="192.168.10.5"
lvs1="192.168.10.10"
lvs2="192.168.10.11"
# 改成自己机器的IP
ips=("192.168.10.40" "192.168.10.41" "192.168.10.30" "192.168.10.31" "192.168.10.20" "192.168.10.15" "192.168.10.5" "192.168.10.10" "192.168.10.11")
for ip in "${ips[@]}";do
#ssh-keygen
#ssh-copy-id ${ip}
# 分发redhat.repo
sshpass -p "$password" scp -o StrictHostKeyChecking=no -r /etc/yum.repos.d/redhat.repo "$username"@${ip}:/etc/yum.repos.d/
# 分发脚本
sshpass -p "$password" scp -o StrictHostKeyChecking=no -r /home/scripts "$username"@${ip}:/home/
# 执行初始化脚本
sshpass -p "$password" ssh -o StrictHostKeyChecking=no "$username@$ip" "/home/scripts/server_ini.sh"
done
# 分发sersync
sshpass -p "$password" scp -o StrictHostKeyChecking=no -r /home/sersync2.5.4_64bit_binary_stable_final.tar.gz "$username"@$nfsserver:/home
# 分发项目
sshpass -p "$password" scp -o StrictHostKeyChecking=no -r /home/wuyu "$username"@$web1:/home
sshpass -p "$password" scp -o StrictHostKeyChecking=no -r /home/wuyu "$username"@$web2:/home
# 分发静态文件
sshpass -p "$password" scp -o StrictHostKeyChecking=no -r /home/wuyu/static "$username"@$nfsserver:/static
# 分发MySQL二进制
sshpass -p "$password" scp -o StrictHostKeyChecking=no -r /home/mysql-5.7.43-linux-glibc2.12-x86_64.tar "$username"@$database:/home
# 静态资源共享备份一键部署
sshpass -p "$password" ssh -o StrictHostKeyChecking=no "$username@$nfsbackup" "/home/scripts/onekey_nfsbackup.sh"
sshpass -p "$password" ssh -o StrictHostKeyChecking=no "$username@$nfsserver" "/home/scripts/onekey_nfsserver.sh"
# 数据库一键部署
sshpass -p "$password" ssh -o StrictHostKeyChecking=no "$username@$database" "/home/scripts/onekey_database.sh"
# web服务器集群一键部署
sshpass -p "$password" ssh -o StrictHostKeyChecking=no "$username@$web1" "/home/scripts/onekey_uwsgi.sh web1 $nfsserver"
sshpass -p "$password" ssh -o StrictHostKeyChecking=no "$username@$web2" "/home/scripts/onekey_uwsgi.sh web2 $nfsserver"
sshpass -p "$password" ssh -o StrictHostKeyChecking=no "$username@$database" "/home/scripts/database_ini.sh"
# nginx集群一键部署
sshpass -p "$password" ssh -o StrictHostKeyChecking=no "$username@$nginx1" "/home/scripts/onekey_nginx.sh nginx1 $nfsserver"
sshpass -p "$password" ssh -o StrictHostKeyChecking=no "$username@$nginx2" "/home/scripts/onekey_nginx.sh nginx2 $nfsserver"
# 负载均衡主从一键部署
sshpass -p "$password" ssh -o StrictHostKeyChecking=no "$username@$lvs1" "/home/scripts/onekey_lvs.sh"
sshpass -p "$password" ssh -o StrictHostKeyChecking=no "$username@$lvs2" "/home/scripts/onekey_lvs2.sh"
server_ini.sh
#!/bin/bash
yum clean all && yum makecache && yum install -y -q epel-release && yum clean all && yum makecache && yum install -y -q wget gcc make chrony
systemctl stop firewalld && setenforce 0
# 配置时间同步
cat >> /etc/chrony.conf<<EOF
server ntp.aliyun.com iburst
EOF
systemctl enable --now chronyd
# 主机名映射
cat > /etc/hosts<<EOF
127.0.0.1 localhost localhost.localdomain localhost4 localhost4.localdomain4
::1 localhost localhost.localdomain localhost6 localhost6.localdomain6
192.168.10.5 nfs-backup
192.168.10.15 nfs-server
192.168.10.20 database-mysql
192.168.10.30 web1
192.168.10.31 web2
192.168.10.40 nginx1
192.168.10.41 nginx2
192.168.10.10 lvs1
192.168.10.11 lvs2
EOF
onekey_nfsbackup
在配置文件中将hosts allow 修改为自己的网段
#!/bin/bash
echo "--------------------------------------------------"
echo "------------开始配置nfs备份服务器------------------"
echo "--------------------------------------------------"
hostnamectl set-hostname nfs-backup
yum install -y -q rsync rsync-daemon
echo "软件安装完成"
cat > /etc/rsyncd.conf <<EOF
#--- 指定管理备份目录的用户
uid = rsync
##--- 指定管理备份目录的用户组
gid = rsync
##--- 定义rsync备份服务的监听端口
port = 873
##--- 将rsync虚拟用户伪装成为一个超级管理员用户
fake super = yes
##--- 和安全相关的配置
use chroot = no
##--- 最大连接数 同时只能有200个客户端连接到备份服务器
max connections = 200
##--- 超时时间(单位秒)
timeout = 300
##--- 记录进程号码信息 1.让程序快速停止进程 2. 判断一个服务是否正在运行
pid file = /var/run/rsyncd.pid
##--- 锁文件 防止超过最大连接数
lock file = /var/run/rsync.lock
##--- rsync服务的日志文件 用于排错分析问题
log file = /var/log/rsyncd.log
##--- 忽略传输中的简单错误
ignore errors
##--- 指定备份目录是可读可写
read only = false
##--- 使客户端可以查看服务端的模块信息
list = true
##--- 允许传输备份数据的主机(白名单);白名单和黑名单只用一个。。。
hosts allow = 192.168.10.0/24
##--- 禁止传输备份数据的主机(黑名单)
#hosts deny = 0.0.0.0/32
##--- 指定认证用户
auth users = rsync_backup
##--- 指定认证用户密码文件 用户名称:密码信息
secrets file = /etc/rsync.pwd
##--- 模块信息,支持多模块配置
[nfs_backup]
comment = "backup dir for nfs"
##--- 模块中配置参数 指定备份目录
path = /backup
[wwwlog_backup]
EOF
useradd rsync -M -s /bin/nologin && echo "rsync_backup:123456" >/etc/rsync.pwd && chmod 600 /etc/rsync.pwd && mkdir /backup && chown rsync.rsync /backup/
echo "启动rsyncd服务"
systemctl enable --now rsyncd
echo "--------------------------------------------------"
echo "------------nfs备份服务器配置结束------------------"
echo "--------------------------------------------------"
onekey_nfsserver
修改配置文件的remote的IP为backup的IP,hostip为本机IP
修改二进制包名
#!/bin/bash
# echo "-----------------记得先上传static目录---------------"
# echo "-----------------记得上传sersync的包-----------------"
# echo "-----------------记得修改配置文件理的IP-------------------"
echo "----------------------------------------------------"
echo "-----------------开始配置nfs服务器------------------------"
echo "----------------------------------------------------"
hostnamectl set-hostname nfs-server
yum install -y -q nfs-utils rsync
useradd -u 1001 www
chmod 775 /static
cat > /etc/exports <<EOF
/static 192.168.10.0/24(all_squash,async,anonuid=1001,anongid=1001)
EOF
systemctl enable --now nfs-server
#wget https://raw.githubusercontent.com/wsgzao/sersync/master/sersync2.5.4_64bit_binary_stable_final.tar.gz
cd /home && chmod 777 sersync2.5.4_64bit_binary_stable_final.tar.gz
tar -zxvf /home/sersync2.5.4_64bit_binary_stable_final.tar.gz
mv GNU-Linux-x86/ /usr/local/sersync && ln -s /usr/local/sersync/sersync2 /usr/local/bin/sersync2 && cd /usr/local/sersync
cat > confxml.xml <<EOF
<?xml version="1.0" encoding="ISO-8859-1"?>
<head version="2.5">
<host hostip="192.168.10.15" port="8008"></host>
<!-- "不开启调试模式,开启则会在sersync正在运行的控制台,打印inotify事件与rsync同步命令。" -->
<debug start="false"/>
<!-- "同步的文件系统是不是为xfs" -->
<fileSystem xfs="false"/>
<!-- "文件过滤功能,当true时,以下类型的文件将不同步" -->
<filter start="false">
<exclude expression="(.*)\.svn"></exclude>
<exclude expression="(.*)\.gz"></exclude>
<exclude expression="^info/*"></exclude>
<exclude expression="^static/*"></exclude>
</filter>
<!-- "inotify监控的事件" -->
<inotify>
<delete start="true"/>
<createFolder start="true"/>
<createFile start="true"/>
<closeWrite start="true"/>
<moveFrom start="true"/>
<moveTo start="true"/>
<attrib start="true"/>
<modify start="true"/>
</inotify>
<!-- "rsync命令的配置区" -->
<sersync>
<!-- "rsync命令src源目录" -->
<localpath watch="/static">
<!-- "rsync命令dst ip和模块;如果是ssh则表示dst目录名" -->
<remote ip="192.168.10.5" name="nfs_backup"/>
<!--<remote ip="192.168.8.39" name="tongbu"/>-->
<!--<remote ip="192.168.8.40" name="tongbu"/>-->
</localpath>
<!-- "rsync命令的参数配置" -->
<rsync>
<commonParams params="-avz"/>
<auth start="true" users="rsync_backup" passwordfile="/etc/rsync.pwd"/>
<userDefinedPort start="false" port="874"/><!-- port=874 -->
<timeout start="false" time="100"/><!-- timeout=100 -->
<!-- "默认为rsync daemon执行,true为ssh方式" -->
<ssh start="false"/>
</rsync>
<!-- "错误重传及日志文件路径" -->
<failLog path="/tmp/rsync_fail_log.sh" timeToExecute="60"/><!--default every 60mins execute once-->
<!-- "Crontab定期整体同步功能,默认600mins"-->
<!--"如果同时开启了filter与crontab,则要开启crontab的crontabfilter,并按示例设置使其与filter的过滤一一对应。"-->
<crontab start="false" schedule="600"><!--600mins-->
<crontabfilter start="false">
<exclude expression="*.php"></exclude>
<exclude expression="info/*"></exclude>
</crontabfilter>
</crontab>
<plugin start="false" name="command"/>
</sersync>
<!-- " " -->
<plugin name="command">
<param prefix="/bin/sh" suffix="" ignoreError="true"/> <!--prefix /opt/tongbu/mmm.sh suffix-->
<filter start="false">
<include expression="(.*)\.php"/>
<include expression="(.*)\.sh"/>
</filter>
</plugin>
<!-- "插件配置,不需要更改" -->
<plugin name="socket">
<localpath watch="/opt/tongbu">
<deshost ip="192.168.138.20" port="8009"/>
</localpath>
</plugin>
<plugin name="refreshCDN">
<localpath watch="/data0/htdocs/cms.xoyo.com/site/">
<cdninfo domainname="ccms.chinacache.com" port="80" username="xxxx" passwd="xxxx"/>
<sendurl base="http://pic.xoyo.com/cms"/>
<regexurl regex="false" match="cms.xoyo.com/site([/a-zA-Z0-9]*).xoyo.com/images"/>
</localpath>
</plugin>
</head>
EOF
echo "123456" > /etc/rsync.pwd
chmod 600 /etc/rsync.pwd
echo "启动sersync服务"
sersync2 -d -r -o /usr/local/sersync/confxml.xml >/dev/null 2>&1
systemctl restart rpcbind && systemctl restart nfs-server
echo "----------------------------------------------------"
echo "------------nfs服务器配置结束------------------------"
echo "----------------------------------------------------"
onekey_database
修改mysql二进制包名
修改54行的密码为自己的密码
#!/bin/bash
# 检查/home下是否存在二进制包
#存在:二进制安装
echo "------------------------------------------"
echo "------------开始配置数据库---------------"
echo "------------------------------------------"
hostnamectl set-hostname database-mysql
groupadd -r mysql && useradd mysql -r -g mysql -c "MySQL Server" -s /bin/false
echo "------------------------------------------"
echo "------------解压中---------------"
echo "------------------------------------------"
tar xf /home/mysql-5.7.43-linux-glibc2.12-x86_64.tar -C /usr/local/
tar xf /usr/local/mysql-5.7.43-linux-glibc2.12-x86_64.tar.gz -C /usr/local/
ln -sv /usr/local/mysql-5.7.43-linux-glibc2.12-x86_64 /usr/local/mysql
/usr/local/mysql/bin/mysqld --initialize-insecure --user=mysql --basedir=/usr/local/mysql/ --datadir=/usr/local/mysql/data
echo "------------------------------------------"
echo "------------安装依赖中---------------"
echo "------------------------------------------"
yum install libaio-devel ncurses-compat-libs ncurses-devel -y -q && ldconfig
mkdir /var/log/mysql && chmod 777 /var/log/mysql
cat >/etc/my.cnf<<EOF
[mysqld]
user=mysql
# mysql 程序目录
basedir=/usr/local/mysql
# mysql data目录
datadir=/usr/local/mysql/data
# mysqld 本地监听socket文件
socket=/tmp/mysql.sock
# mysqld实例id,一台机器多实例id需不一样
server_id=6
port=3306
# mysql 错误日志
log_error=/var/log/mysql/mysql3306.err
[mysql]
socket=/tmp/mysql.sock
EOF
cp /usr/local/mysql/support-files/mysql.server /etc/init.d/mysqld
chkconfig --add mysqld && chkconfig mysqld on
echo "export PATH=/usr/local/mysql/bin:\$PATH" >> /etc/profile && source /etc/profile && systemctl start mysqld
#chown mysql.mysql /app/mysql/etc/my.cnf
#chmod 777 /app/mysql && chmod 777 /app/mysql/data && chmod 777 /app/mysql/logs
#systemctl enable --now mysqld
# cat /app/mysql/logs/mysql3306.err |egrep -i "error|fail"
echo "------------------------------------------"
echo "------------初始化数据库---------------"
echo "------------------------------------------"
#mkdir /home/scripts
cat > /home/scripts/ini.sql <<EOF
use mysql;
flush privileges;
ALTER USER 'root'@'localhost' IDENTIFIED BY 'Twf:2001!';
SET character_set_server = 'utf8mb4';
SET sql_mode=(SELECT REPLACE(@@sql_mode,'ONLY_FULL_GROUP_BY',''));
update user set host='%' where user='root';
use mysql;
grant all privileges on *.* to root@'%';
flush privileges;
create database shoppingmall;
EOF
mysql -e "alter user root@'localhost' identified by '123456';"
#chmod 777 /home/scripts/*
mysql -uroot -p123456 < /home/scripts/ini.sql
echo "------------------------------------------"
echo "------------数据库配置完成---------------"
echo "------------------------------------------"
onekey_uwsgi
修改项目名和uwsgi中的项目路径:将wuyu该为自己的项目名
#!/bin/bash
echo "-----------------------------------------------------"
echo "-----------------开始部署web服务器--------------------"
echo "-----------------------------------------------------"
hostnamectl set-hostname "$1"
yum install -y -q python36 python3-devel gcc nfs-utils libjpeg-devel zlib-devel libtiff-devel
pip3 install --upgrade
chmod 775 /home/wuyu/static
echo "$2:/static /home/wuyu/static nfs _netdev 0 0" >> /etc/fstab
mount -a
pip3 install django pymysql pillow uwsgi
cd /home/wuyu
if [ "$1" == "web1" ]; then
echo "-------------------------------------------------------------"
echo "----------------生成数据迁移文件,创建数据表中------------------"
echo "-------------------------------------------------------------"
python3 manage.py makemigrations wuyu && python3 manage.py migrate
fi
cat > /home/wuyu/uwsgi.ini <<EOF
[uwsgi]
socket=$1:8000
chdir=/home/wuyu
module=wuyu.wsgi
master=true
processes=2
threads=2
max-requests=2000
chmod-socket=664
vacuum=true
daemonize=/home/wuyu/uwsgi.log
EOF
chmod u+x uwsgi.ini && uwsgi --ini uwsgi.ini
echo "-----------------------------------------------------"
echo "-----------------web服务器结束--------------------"
echo "-----------------------------------------------------"
onekey_nginx
#!/bin/bash
echo "------------------------------------"
echo "------------开始部署nginx------------"
echo "------------------------------------"
hostnamectl set-hostname $1
yum install -y -q nginx nfs-utils net-tools
echo 1 > /proc/sys/net/ipv4/conf/all/arp_ignore && echo 1 > /proc/sys/net/ipv4/conf/lo/arp_ignore
echo 2 > /proc/sys/net/ipv4/conf/all/arp_announce && echo 2 > /proc/sys/net/ipv4/conf/lo/arp_announce
ifconfig lo:1 192.168.10.100/32
mkdir /home/static && chmod 777 /home/static
echo "$2:/static /home/static nfs _netdev 0 0" >> /etc/fstab
mount -a
mkdir -p /var/nginx/mydjango
# 注意cat + EOF 时用tab不要用空格
cat > /etc/nginx/conf.d/mydjango.conf <<EOF
upstream xback {
server web1:8000;
server web2:8000;
}
server {
listen 81;
server_name www.xbacks.com;
charset utf-8;
access_log /var/nginx/mydjango/access.log;
error_log /var/nginx/mydjango/error.log;
client_max_body_size 100M;
location /static {
alias /home/static;
}
location / {
include /etc/nginx/uwsgi_params;
uwsgi_pass xback;
}
}
EOF
systemctl enable --now nginx
echo "------------------------------------"
echo "------------nginx部署结束------------"
echo "------------------------------------"
onekey_lvs
#!/bin/bash
echo "------------------------------------"
echo "------------开始部署lvs------------"
echo "------------------------------------"
hostnamectl set-hostname lvs1
yum install -y keepalived tcpdump ipvsadm net-tools
echo "net.ipv4.ip_forward=1" >> /etc/sysctl.conf && sysctl -p
ifconfig lo:1 192.168.10.100/32
cp /etc/keepalived/keepalived.conf /etc/keepalived/keepalived.conf.bak
cat > /etc/keepalived/keepalived.conf<<EOF
! Configuration File for keepalived
global_defs {
router_id LVS_DEVEL
vrrp_skip_check_adv_addr
vrrp_strict
vrrp_garp_interval 0
vrrp_gna_interval 0
}
vrrp_instance VI_1 {
state MASTER
interface ens160
virtual_router_id 51
priority 100
advert_int 1
authentication {
auth_type PASS
auth_pass 1111
}
virtual_ipaddress {
192.168.10.100
}
}
vrrp_instance VI_2 {
state BACKUP
interface ens160
virtual_router_id 52
priority 51
advert_int 1
authentication {
auth_type PASS
auth_pass 1111
}
virtual_ipaddress {
192.168.10.101
}
}
EOF
systemctl enable --now keepalived
ipvsadm -A -t 192.168.10.100:81 -s wrr
ipvsadm -a -t 192.168.10.100:81 -r 192.168.10.40 -g
ipvsadm -a -t 192.168.10.100:81 -r 192.168.10.41 -g
echo "------------------------------------"
echo "------------lvs主机配置结束------------"
echo "------------------------------------"
onekey_lvs2
#!/bin/bash
hostnamectl set-hostname lvs2
yum install -y keepalived tcpdump ipvsadm net-tools
echo "net.ipv4.ip_forward=1" >> /etc/sysctl.conf && sysctl -p
#ifconfig lo:1 192.168.10.100/32
cp /etc/keepalived/keepalived.conf /etc/keepalived/keepalived.conf.bak
cat > /etc/keepalived/keepalived.conf<<EOF
! Configuration File for keepalived
global_defs {
router_id LVS_DEVEL2
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 50
advert_int 1
authentication {
auth_type PASS
auth_pass 1111
}
virtual_ipaddress {
192.168.10.100
}
}
vrrp_instance VI_2 {
state MASTER
interface ens160
virtual_router_id 52
priority 102
advert_int 1
authentication {
auth_type PASS
auth_pass 1111
}
virtual_ipaddress {
192.168.10.101
}
}
EOF
systemctl enable --now keepalived
ipvsadm -A -t 192.168.10.100:81 -s wrr
ipvsadm -a -t 192.168.10.100:81 -r 192.168.10.40 -g
ipvsadm -a -t 192.168.10.100:81 -r 192.168.10.41 -g
echo "------------------------------------"
echo "------------lvs从机配置结束------------"
echo "------------------------------------"
测试
浏览器访问 192.168.10.100:81
存在问题:
解决高可用的裂脑问题
文件权限过高