小的网站结构
说明:如果部署在云上,比如阿里云上,不需要自己部署keepalived,直接买阿里云的slb即可,slb然后分发流量到两台haproxy机器
一、先部署两个web服务器
编译安装nginx(脚本很粗糙)
[root@007-web2 ~]# cat nginx.sh yum install -y vim lrzsz tree screen psmisc lsof tcpdump wget ntpdate gcc gcc-c++ glibc glibc-devel pcre pcre-devel openssl openssl-devel systemd-devel net-tools iotop bc zip unzip zlib-devel bash-completion nfs-utils automake libxml2 libxml2-devel libxslt libxslt-devel perl perl-ExtUtils-Embed wget https://mirrors.huaweicloud.com/nginx/nginx-1.17.5.tar.gz tar xf nginx-1.17.5.tar.gz cd nginx-1.17.5/ ./configure --prefix=/apps/nginx --user=nginx --group=nginx --with-http_ssl_module --with-http_v2_module --with-http_realip_module --with-http_stub_status_module --with-http_gzip_static_module --with-pcre --with-stream --with-stream_ssl_module --with-stream_realip_module --with-debug make -j 4 make install /usr/sbin/groupadd -g 995 -r nginx 2> /dev/null /usr/sbin/useradd -c "Nginx web server" -u 997 -g nginx -s /sbin/nologin -r -d /var/lib/nginx nginx 2> /dev/null cat > /usr/lib/systemd/system/nginx.service <<'EOF' [Unit] Description=The nginx HTTP and reverse proxy server After=network.target remote-fs.target nss-lookup.target [Service] Type=forking PIDFile=/run/nginx.pid ExecStartPre=/usr/bin/rm -f /run/nginx.pid ExecStartPre=/apps/nginx/sbin/nginx -t ExecStart=/apps/nginx/sbin/nginx ExecReload=/bin/kill -s HUP $MAINPID KillSignal=SIGQUIT TimeoutStopSec=5 KillMode=process PrivateTmp=true [Install] WantedBy=multi-user.target EOF mkdir /apps/nginx/conf.d cat > /apps/nginx/conf/nginx.conf <<'EOF' user nginx; worker_processes auto; error_log /var/log/nginx/error.log; pid /run/nginx.pid; 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 2048; include /apps/nginx/conf/mime.types; default_type application/octet-stream; include /apps/nginx/conf.d/*.conf; server { server_name _; root /apps/nginx/html; location / { } error_page 500 502 503 504 /50x.html; location = /50x.html { } } } EOF systemctl daemon-reload && systemctl enable nginx systemctl start nginx
编译php脚本
[root@007-web2 ~]# cat php.sh #!/bin/bash RED="\033[0;31m" GREEN="\033[0;32m" NO_COLOR="\033[0m" PREFIX=/usr/local/php #这个还是别改了,好多地方要改 SYSCONFDIR= SRC=/usr/src FLAG=$1 CPUS=`cat /proc/cpuinfo| grep "physical id"| sort| uniq| wc -l` CORE=`cat /proc/cpuinfo| grep "cpu cores"| uniq | awk '{print $4}'` J=$((${CPUS}*${CORE})) FILEURL='http://ftp.ntu.edu.tw/pub/php/distributions/php-7.3.10.tar.gz' # 判断是不是root judge_root() { [ $(id -u) != "0" ] && { echo -e "${RED}Error:${NO_COLOR} You must be root to run this script."; exit 1; } } # download download_source() { cd yum install wget -y wget ${FILEURL} if [ ! "$?" -eq 0 ];then echo "download failed!" exit 1 fi } # install install(){ # Add the "apache" group and user,需要的话改为nginx #/usr/sbin/groupadd -g 48 -r apache 2> /dev/null || : #/usr/sbin/useradd -c "Apache" -u 48 -g apache \ #-s /sbin/nologin -r -d /usr/share/httpd apache 2> /dev/null || : /usr/sbin/groupadd -g 995 -r nginx 2> /dev/null /usr/sbin/useradd -c "Nginx web server" -u 997 -g nginx -s /sbin/nologin -r -d /var/lib/nginx nginx 2> /dev/null # epel wget -O /etc/yum.repos.d/epel.repo http://mirrors.aliyun.com/repo/epel-7.repo yum install gcc openssl-devel pcre-devel libnghttp2-devel ncurses-devel lbzip2 bzip2 expat-devel libxml2-devel libxml2 autoconf libtool -y tar xf php-7.3.10.tar.gz -C ${SRC}/ cd ${SRC}/php-7.3.10/ ./configure --prefix=/usr/local/php --enable-mysqlnd --with-mysqli=mysqlnd --with-pdo-mysql=mysqlnd --with-openssl --with-freetype-dir --with-jpeg-dir --with-png-dir --with-zlib --with-config-file-path=/usr/loca/php/etc --with-config-file-scan-dir=/usr/local/php/etc/php.d --enable-mbstring --enable-xml --enable-sockets --enable-fpm --enable-maintainer-zts --disable-fileinfo make -j ${J} make install # config cd ${PREFIX}/etc/ cp php-fpm.conf.default php-fpm.conf cd ${PREFIX}/etc/php-fpm.d cp www.conf.default www.conf # init file cp ${SRC}/php-7.3.10/sapi/fpm/init.d.php-fpm /etc/init.d/php-fpm chmod +x /etc/init.d/php-fpm # modify config file sed -i 's@user = nobody@user = nginx@' ${PREFIX}/etc/php-fpm.d/www.conf sed -i 's@group = nobody@group = nginx@' ${PREFIX}/etc/php-fpm.d/www.conf sed -i 's@listen = 127.0.0.1:9000@listen = /var/run/php-fpm.sock@' ${PREFIX}/etc/php-fpm.d/www.conf sed -i 's@;listen.mode = 0660@listen.mode = 0666@' ${PREFIX}/etc/php-fpm.d/www.conf #reload systemctl daemon-reload && systemctl enable php-fpm } test_php(){ systemctl start php-fpm sleep 3 if ps -ef | grep php-fpm | grep -v grep;then echo -e "${GREEN}Maybe php installed successfully...${NO_COLOR}" else echo -e "${RED}Maybe php installed failed...${NO_COLOR}" fi } remove_php() { systemctl stop php-fpm sleep 3 if ps -ef | grep php-fpm | grep -v grep;then echo -e "${RED}Php uninstall failed...Killing php process failed...${NO_COLOR}" exit 2 fi rm -rf ${PREFIX} ${SRC}/php-7.3.10 /etc/init.d/php-fpm } judge_uninstall(){ if [ "$FLAG" = "uninstall" ];then remove_php exit 0 fi } main() { judge_uninstall judge_root download_source install test_php } main
nginx配置wordpress
[root@007-web1 ~]# mkdir /var/www/wordpress -p #下载wordpress [root@007-web1 ~]# unzip wordpress-5.2.3-zh_CN.zip -d /var/www/ [root@007-web1 ~]# chown nginx.nginx -R /var/www/wordpress/ [root@007-web1 ~]# cat /apps/nginx/conf.d/blog.jd.com.conf server { listen 80; server_name blog.jd.com; charset utf-8; access_log /var/log/nginx/blog.jd.com-access.log main; error_log /var/log/nginx/blog.jd.com-error.log; root /var/www/wordpress; location / { root /var/www/wordpress; index index.php index.html index.htm; } location ~ \.php$ { #fastcgi_pass 127.0.0.1:9000; fastcgi_pass unix:/var/run/php-fpm.sock; fastcgi_split_path_info ^(.+\.php)(/.+)$; fastcgi_index index.php; fastcgi_buffer_size 128k; fastcgi_buffers 64 128k; fastcgi_intercept_errors on; fastcgi_param PATH_INFO $fastcgi_path_info; fastcgi_param HTTP_AUTHORIZATION $http_authorization; fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name; include fastcgi_params; fastcgi_connect_timeout 300; fastcgi_read_timeout 300; fastcgi_send_timeout 300; client_max_body_size 100m; } location ~ /.git { deny all; } }
测试当前服务器是否正常
[root@007-web1 ~]# /apps/nginx/sbin/nginx -t nginx: the configuration file /apps/nginx/conf/nginx.conf syntax is ok nginx: configuration file /apps/nginx/conf/nginx.conf test is successful [root@007-web1 ~]# systemctl restart nginx [root@007-web1 ~]# curl -vLH 'blog.jd.com' 127.0.0.1 * About to connect() to 127.0.0.1 port 80 (#0) * Trying 127.0.0.1... * Connected to 127.0.0.1 (127.0.0.1) port 80 (#0) > GET / HTTP/1.1 > User-Agent: curl/7.29.0 > Host: 127.0.0.1 > Accept: */* > < HTTP/1.1 302 Found < Server: nginx/1.17.5 ... 显示了中文的配置wordpress即为ok
同步代码到web2
[root@007-web1 ~]# scp -p /apps/nginx/conf.d/blog.jd.com.conf 192.168.38.136:/apps/nginx/conf.d/ [root@007-web1 ~]# ssh 192.168.38.136 'mkdir -p /var/www/wordpress/' [root@007-web1 ~]# scp -p -r /var/www/wordpress 192.168.38.136:/var/www/ [root@007-web1 ~]# ssh 192.168.38.136 'chown nginx.nginx -R /var/www/wordpress' [root@007-web1 ~]# ssh 192.168.38.136 'systemctl restart nginx' #测试 [root@007-web1 ~]# curl -vLH 'blog.jd.com' 192.168.38.136
二、部署数据库主从
二进制安装脚本
[root@007-mysql-master mysql-5.7-onekey-install]# cat mysql-install.sh #!/bin/bash CURRENTDIR=`pwd` NAME="mysql-5.7.28-linux-glibc2.12-x86_64.tar.gz" FULL_NAME=${CURRENTDIR}/${NAME} DATA_DIR="/data/mysql/" StandardOutput(){ echo -e "\033[1;32m$1 ... \033[0m" } ErrorOutput(){ echo -e "\033[1;31m$1 ... \033[0m" } is_empty_dir(){ return `ls -A $1 2>/dev/null | wc -l` } judge_mysql(){ if [ -e /usr/local/mysql ];then ErrorOutput "/usr/local/mysql目录存在...Mysql 似乎已经安装...终止安装..." exit 10 fi which mysqld &>/dev/null if [ "$?" -eq 0 ];then ErrorOutput "mysqld命令存在...Mysql 似乎已经安装...终止安装..." exit 20 fi if ss -ltn | grep 3306 -q;then ErrorOutput "3306端口被占用...Mysql 似乎已经安装...终止安装..." exit 30 fi is_empty_dir $DATA_DIR if [ ! "$?" -eq 0 ];then ErrorOutput "$DATA_DIR 不为空...终止安装..." exit 40 fi } download_mysql(){ if [ -f ${FULL_NAME} ];then StandardOutput "Mysql安装文件存在,开始安装..." else StandardOutput "Mysql安装文件不存在...开始下载..." curl -o ${NAME} https://mirrors.huaweicloud.com/mysql/Downloads/MySQL-5.7/${NAME} if [ ! "$?" -eq 0 ];then ErrorOutput "下载失败...终止安装..." && exit 50 fi fi } mysql_install(){ # install dependence yum install -y libaio-devel if id mysql &>/dev/null;then StandardOutput "mysql 用户已经存在,跳过创建用户过程..." else useradd -r -s /sbin/nologin mysql fi tar xf ${FULL_NAME} -C /usr/local/ ln -sv /usr/local/mysql-5* /usr/local/mysql chown -R mysql.mysql /usr/local/mysql/ if [ ! -d $DATA_DIR ];then mkdir -pv $DATA_DIR && chown -R mysql.mysql $DATA_DIR -R fi /usr/local/mysql/bin/mysqld --initialize --datadir=$DATA_DIR --user=mysql &>mysql_install.log cp /usr/local/mysql-5.*-x86_64/support-files/mysql.server /etc/init.d/mysqld chmod a+x /etc/init.d/mysqld cp ${CURRENTDIR}/my.cnf /etc/my.cnf echo 'export PATH=/usr/local/mysql/bin/:$PATH' > /etc/profile.d/mysql.sh source /etc/profile.d/mysql.sh # /etc/init.d/mysqld start mkdir /var/lib/mysql /var/run/mysqld chown mysql.mysql /var/lib/mysql/ /var/run/mysqld systemctl daemon-reload } mysql_check(){ systemctl start mysqld if ss -ltn | grep 3306 -q ;then StandardOutput "VERY GOOD..." rm -f ${CURRENTDIR}/${NAME} fi echo -e "请手动执行:\033[1;32msource /etc/profile\033[0m" echo -e "当前mysql数据库密码为:\033[1;32m$( grep "temporary password" ${CURRENTDIR}/mysql_install.log | awk '{print $NF}')\033[0m" } main(){ judge_mysql download_mysql mysql_install mysql_check } main
数据库密码
[root@007-mysql-master mysql-5.7-onekey-install]# 当前mysql数据库密码为:fO:Qd.jsl9GU [root@007-mysql-master mysql-5.7-onekey-install]# mysqladmin -uroot -p$(grep " temporary password" mysql_install.log | awk '{print $NF}') password 123456 [root@007-slave mysql-5.7-onekey-install]# 当前mysql数据库密码为:le*gu=x4Emoi [root@007-slave mysql-5.7-onekey-install]# mysqladmin -uroot -p$(grep " temporary password" mysql_install.log | awk '{print $NF}') password 123456
主数据库配置:
[root@007-mysql-master mysql-5.7-onekey-install]# cat /etc/my.cnf # For advice on how to change settings please see # http://dev.mysql.com/doc/refman/5.7/en/server-configuration-defaults.html [mysqld] datadir=/data/mysql socket=/var/lib/mysql/mysql.sock log-bin server-id=1 expire-logs-days=15 binlog-format=row gtid_mode=on enforce_gtid_consistency=on skip_name_resolve # Disabling symbolic-links is recommended to prevent assorted security risks symbolic-links=0 log-error=/var/log/mysqld.log pid-file=/var/run/mysqld/mysqld.pid [client] socket = /var/lib/mysql/mysql.sock port = 3306
[root@007-mysql-master ~]# systemctl restart mysqld && systemctl enable mysqld mysqld.service is not a native service, redirecting to /sbin/chkconfig. Executing /sbin/chkconfig mysqld on [root@007-mysql-master ~]# /sbin/chkconfig mysqld on
mysql> grant replication slave on *.* to 'repluser'@'192.168.38.147' identified by 'WWQD88OYrqSxLg'; mysql> create database wordpress character set utf8 collate utf8_bin; mysql> grant all privileges on wordpress.* to 'wordpress'@'192.168.38.%' identified by 'j9DtO2Bf1DvRANQr';
从数据库配置
[root@007-slave mysql-5.7-onekey-install]# cat /etc/my.cnf # For advice on how to change settings please see # http://dev.mysql.com/doc/refman/5.7/en/server-configuration-defaults.html [mysqld] datadir=/data/mysql socket=/var/lib/mysql/mysql.sock server-id=2 gtid_mode=on enforce_gtid_consistency=on skip_name_resolve # Disabling symbolic-links is recommended to prevent assorted security risks symbolic-links=0 log-error=/var/log/mysqld.log pid-file=/var/run/mysqld/mysqld.pid [client] socket = /var/lib/mysql/mysql.sock port = 3306 [root@007-slave mysql-5.7-onekey-install]# systemctl restart mysqld && systemctl enable mysqld [root@007-slave mysql-5.7-onekey-install]# /sbin/chkconfig mysqld on
mysql> CHANGE MASTER TO MASTER_HOST='192.168.38.138',MASTER_USER='repluser',MASTER_PASSWORD='WWQD88OYrqSxLg',MASTER_PORT=3306,MASTER_AUTO_POSITION=1; mysql> start slave; mysql> show slave status\G ...两个yes就OK...
三、mysql服务器充当NFS服务器
配置主NFS
[root@007-mysql-master ~]# yum install nfs-utils -y [root@007-mysql-master ~]# mkdir /data/wordpress -p [root@007-mysql-master ~]# cat /etc/exports /data/wordpress 192.168.38.*(rw,sync,no_subtree_check,no_root_squash [root@007-mysql-master ~]# systemctl restart nfs [root@007-mysql-master ~]# systemctl enable nfs
007-web1挂载测试
[root@007-web1 ~]# yum install nfs-utils autofs -y [root@007-web1 ~]# showmount -e 192.168.38.138 Export list for 192.168.38.138: /data/wordpress 192.168.38.* [root@007-web1 ~]# grep wordpress /etc/auto.master/- /etc/auto.wordpress [root@007-web1 ~]# cat /etc/auto.wordpress /var/www/wordpress/wp-content/uploads 192.168.38.138:/data/wordpress [root@007-web1 ~]# systemctl restart autofs
测试没问题同步到web2
[root@007-web1 ~]# ssh 192.168.38.136 ' yum install nfs-utils autofs -y' [root@007-web1 ~]# scp /etc/auto.{master,wordpress} 192.168.38.136:/etc/ [root@007-web1 ~]# ssh 192.168.38.136 'systemctl restart autofs'#测试没问题
配置自动同步
[root@007-mysql-master ~]# yum install rsync inotify-tools -y [root@007-mysql-master ~]# ssh 192.168.38.147 'yum install rsync -y' [root@007-mysql-master ~]# ssh 192.168.38.147 'mkdir /data/wordpress -p' #密钥分发 [root@007-mysql-master ~]# ssh-keygen -f ~/.ssh/id_rsa -P '' [root@007-mysql-master ~]# ssh-copy-id 192.168.38.147 #同步脚本 [root@007-mysql-master ~]# mkdir /scripts/ [root@007-mysql-master ~]# cat /scripts/inotify-data2.sh [root@007-mysql-master wordpress]# cat /scripts/inotify-data2.sh #!/bin/bash SRC=/data/wordpress DEST='root@192.168.38.147:/data' # BACKDIR=/tmp/backup/ /usr/bin/inotifywait -mrq --timefmt '%Y-%m-%d %H:%M' --format '%T %w %f %,e' -e delete,moved_to,moved_from,close_write,isdir,attrib ${SRC} | \ while read DATE TIME DIR FILE EVENT;do FILEPATH=${DIR}${FILE} # if echo $EVENT | grep -i delete;then # mkdir $BACKDIR -p && \cp -a $FILEPATH $BACKDIR # rsync -avz --delete ${SRC} ${DEST} \ # && echo "At ${TIME} on ${DATE}, file $FILEPATH was deleted via rsync" >> /var/log/deletelist.log # else rsync -avz --delete ${SRC} ${DEST} \ && echo "At ${TIME} on ${DATE}, file $FILEPATH was backuped up via rsync" >> /var/log/changelist.log # fi done #screen运行 [root@007-mysql-master ~]# yum install screen -y [root@007-mysql-master ~]# screen -S rsync [root@007-mysql-master ~]# bash /scripts/inotify-data2.sh
四、配置haproxy
编译安装haproxy(粗糙的脚本)
[root@007-lb1 ~]# cat haproxy.sh #!/bin/bash yum install -y gcc gcc-c++ glibc glibc-devel pcre pcre-devel openssl openssl-devel systemd-devel net-tools vim iotop bc zip unzip zlib-devel lrzsz tree screen lsof tcpdump wget chrony readline-devel if ! getent passwd haproxy >/dev/null ; then if ! getent passwd 188 >/dev/null ; then useradd -r -u 188 -g haproxy -d /var/lib/haproxy -s /sbin/nologin -c "haproxy" haproxy else useradd -r -g haproxy -d /var/lib/haproxy -s /sbin/nologin -c "haproxy" haproxy fi fi wget https://ftp.osuosl.org/pub/blfs/conglomeration/lua/lua-5.3.5.tar.gz tar xf lua-5.3.5.tar.gz cd lua-5.3.5/ make linux test src/lua -v cd wget https://mirrors.huaweicloud.com/haproxy/2.0/src/haproxy-2.0.8.tar.gz tar xf haproxy-2.0.8.tar.gz cd haproxy-2.0.8/ make ARCH=x86_64 TARGET=linux-glibc USE_PCRE=1 USE_OPENSSL=1 USE_ZLIB=1 USE_SYSTEMD=1 USE_CPU_AFFINITY=1 USE_LUA=1 LUA_INC=/root/lua-5.3.5/src/ LUA_LIB=/root/lua-5.3.5/src/ PREFIX=/usr/local/haproxy make install PREFIX=/usr/local/haproxy /usr/local/haproxy/sbin/haproxy -v cat > /usr/lib/systemd/system/haproxy.service <<'EOF' [Unit] Description=HAProxy Load Balancer After=syslog.target network.target [Service] ExecStartPre=/usr/local/haproxy/sbin/haproxy -f /etc/haproxy/haproxy.cfg -c -q ExecStart=/usr/local/haproxy/sbin/haproxy -Ws -f /etc/haproxy/haproxy.cfg -p /var/lib/haproxy/haproxy.pid ExecReload=/bin/kill -USR2 $MAINPID [Install] WantedBy=multi-user.target EOF mkdir /etc/haproxy cat > /etc/haproxy/haproxy.cfg <<'EOF' global log 127.0.0.1 local2 chroot /var/lib/haproxy pidfile /var/run/haproxy.pid maxconn 4000 uid haproxy uid haproxy daemon stats socket /var/lib/haproxy/stats defaults mode http log global option httplog option dontlognull option http-server-close option forwardfor except 127.0.0.0/8 option redispatch retries 3 timeout http-request 10s timeout queue 1m timeout connect 10s timeout client 1m timeout server 1m timeout http-keep-alive 10s timeout check 10s maxconn 3000 listen web_port bind *:9999 stats enable log global stats uri /haproxy-status stats auth haadmin:2NweRqCs EOF mkdir /var/lib/haproxy/ systemctl daemon-reload systemctl enable haproxy systemctl start haproxy
配置文件的书写(不写stat就完全一样)
[root@007-lb1 ~]# cat /etc/haproxy/haproxy.cfg global log 127.0.0.1 local2 chroot /var/lib/haproxy pidfile /var/run/haproxy.pid maxconn 4000 user haproxy group haproxy daemon stats socket /var/lib/haproxy/stats defaults mode http log global option httplog option dontlognull option http-server-close option forwardfor except 127.0.0.0/8 option redispatch retries 3 timeout http-request 10s timeout queue 1m timeout connect 10s timeout client 1m timeout server 1m timeout http-keep-alive 10s timeout check 10s maxconn 3000 listen web_port bind 192.168.38.131:9999 stats enable log global stats uri /haproxy-status stats auth haadmin:2NweRqCs frontend 007-web bind *:80 mode http default_backend bk_web backend bk_web mode http balance source cookie SERVERID insert indirect nocache option forwardfor #转发客户IP到后端服务器 server 007-web1 192.168.38.133:80 cookie 007-web1 check inter 10000 rise 2 fall 5 weight 20 server 007-web2 192.168.38.136:80 cookie 007-web2 check inter 10000 rise 2 fall 5 weight 20
五、配置keepalived
VIP用192.168.38.188
邮件配置
yum install mailx -y cat >> /etc/mail.rc <<'EOF' set from=m17114517139_2@163.com set smtp=smtps://smtp.163.com:465 set smtp-auth-user=m17114517139_2@163.com set smtp-auth-password=zhj6b266 set smtp-auth=login set nss-config-dir=/root/.certs set ssl-verify=ignore EOF mkdir -p /root/.certs/ echo -n | openssl s_client -connect smtp.163.com:465 | sed -ne '/-BEGIN CERTIFICATE-/,/-END CERTIFICATE-/p' > ~/.certs/163.crt certutil -A -n "GeoTrust SSL CA" -t "C,," -d ~/.certs -i ~/.certs/163.crt certutil -A -n "GeoTrust Global CA" -t "C,," -d ~/.certs -i ~/.certs/163.crt certutil -L -d /root/.certs cd /root/.certs/ certutil -A -n "GeoTrust SSL CA - G3" -t "Pu,Pu,Pu" -d ./ -i 163.crt
编译安装keepalived
[root@007-lb1 ~]# cat keepalived.sh #!/bin/bash yum install -y libnfnetlink-devel libnfnetlink ipvsadm libnl libnl-devel libnl3 libnl3-devel lm_sensors-libs net-snmp-agent-libs net-snmp-libs openssh-server openssh-clients openssl openssl-devel automake iproute gcc pcre pcre-devel openssl openssl-devel wget https://mirrors.sjtug.sjtu.edu.cn/archlinux/sources/community/keepalived-2.0.19-1.src.tar.gz tar xf keepalived-2.0.19-1.src.tar.gz tar xf keepalived/keepalived-2.0.19.tar.gz -C /usr/local/src/ cd /usr/local/src/keepalived-2.0.19/ ./configure --prefix=/usr/local/keepalived --disable-fwmark make && make install cat > /usr/lib/systemd/system/keepalived.service <<'EOF' [Unit] Description=LVS and VRRP High Availability Monitor After=network-online.target syslog.target Wants=network-online.target [Service] Type=forking PIDFile=/run/keepalived.pid KillMode=process EnvironmentFile=-/usr/local/keepalived/etc/sysconfig/keepalived ExecStart=/usr/local/keepalived/sbin/keepalived $KEEPALIVED_OPTIONS ExecReload=/bin/kill -HUP $MAINPID [Install] WantedBy=multi-user.target EOF cp bin/keepalived /usr/sbin/ mkdir /etc/keepalived cat > /etc/keepalived/keepalived.conf <<'EOF' global_defs { router_id LVS_DEVEL } vrrp_instance VI_1 { state MASTER interface eth0 virtual_router_id 80 priority 100 advert_int 1 unicast_src_ip 192.168.38.131 unicast_peer { 192.168.38.130 } authentication { auth_type PASS auth_pass 1111 } virtual_ipaddress { 192.168.38.172 dev eth0 label eth0:0 } } EOF systemctl deamon-reload systemctl start keepalived ps -ef | grep keepalived
发邮件脚本
[root@007-lb1 keepalived]# cat notify.sh #!/bin/bash # #contact='root@localhost' contact='admin@jd.com' notify() { local mailsubject="$(hostname) to be $1, vip floating" local mailbody="$(date +'%F %T'): vrrp transition, $(hostname) changed to be $1" echo "$mailbody" | mail -s "$mailsubject" $contact } case $1 in master) notify master ;; backup) notify backup ;; fault) notify fault ;; *) echo "Usage: $(basename $0) {master|backup|fault}" exit 1 ;; esac
nginx检查脚本
[root@007-lb1 keepalived]# cat check_nginx.sh #!/bin/bash GREP_OPTIONS="" Count1=`netstat -antp |grep -v grep |grep haproxy |wc -l` if [ $Count1 -eq 0 ]; then exit 1 fi exit 0
lb1的keepalived.conf
[root@007-lb1 keepalived]# cat /etc/keepalived/keepalived.conf ! Configuration File for keepalived global_defs { router_id node1 vrrp_mcast_group4 224.123.0.18 } vrrp_script chk_nginx { script "/etc/keepalived/check_nginx.sh" interval 2 } vrrp_instance VI_1 { state MASTER interface eth0 virtual_router_id 51 priority 100 advert_int 1 authentication { auth_type PASS auth_pass 1dadcvsd } virtual_ipaddress { 192.168.38.188/16 dev eth0 } track_script { chk_nginx } notify_master "/etc/keepalived/notify.sh master" notify_backup "/etc/keepalived/notify.sh backup" notify_fault "/etc/keepalived/notify.sh fault" }
lb2的keepalived.conf
[root@007-lb2 keepalived]# cat keepalived.conf ! Configuration File for keepalived global_defs { router_id node1 vrrp_mcast_group4 224.123.0.18 } vrrp_script chk_nginx { script "/etc/keepalived/check_nginx.sh" interval 2 } vrrp_instance VI_1 { state BACKUP interface eth0 virtual_router_id 51 priority 99 advert_int 1 authentication { auth_type PASS auth_pass 1dadcvsd } virtual_ipaddress { 192.168.38.188/16 dev eth0 } track_script { chk_nginx } notify_master "/etc/keepalived/notify.sh master" notify_backup "/etc/keepalived/notify.sh backup" notify_fault "/etc/keepalived/notify.sh fault" }
测试VIP转移
[root@007-lb1 ~]# pkill haproxy #vip转移 [root@007-lb2 keepalived]# ip addr show dev eth0 2: eth0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UP group default qlen 1000 link/ether 00:0c:29:5c:b9:ce brd ff:ff:ff:ff:ff:ff inet 192.168.38.132/24 brd 192.168.38.255 scope global noprefixroute dynamic eth0 valid_lft 2586860sec preferred_lft 2586860sec inet6 fe80::20c:29ff:fe5c:b9ce/64 scope link noprefixroute valid_lft forever preferred_lft forever
六、域名解析后就可以了,解析到vip
安装wordpress即可
七、将haproxy+keepalived换成keepalived+LVS
lvs1:192.168.38.134
lvs2:192.168.38.135
VIP:192.168.38.189
说明:如果部署在云上,比如阿里云上,不需要自己部署lvs,直接买阿里云的slb即可,slb然后分发流量到两台web机器,不过这种不推荐,推荐slb走自己的haproxy,进行7层反代
编译安装keepalived同上
邮件服务配置同上
notify脚本同上
check脚本
#!/bin/bash GREP_OPTIONS="" Count1=`ps -ef |grep keepalived | grep -v grep |wc -l` if [ $Count1 -eq 0 ]; then exit 1 fi exit 0
lvs1的keepalived.conf
[root@lvs1 keepalived]# cat keepalived.conf ! Configuration File for keepalived global_defs { router_id node1 vrrp_mcast_group4 224.123.0.19 } vrrp_script chk_nginx { script "/etc/keepalived/check_keepalived.sh" interval 2 } vrrp_instance VI_1 { state MASTER interface eth0 virtual_router_id 52 priority 100 advert_int 1 authentication { auth_type PASS auth_pass 1dadcvsd2 } virtual_ipaddress { 192.168.38.189/16 dev eth0 } track_script { chk_nginx } notify_master "/etc/keepalived/notify.sh master" notify_backup "/etc/keepalived/notify.sh backup" notify_fault "/etc/keepalived/notify.sh fault" } virtual_server 192.168.38.189 80 { delay_loop 3 lb_algo sh lb_kind DR protocol TCP real_server 192.168.38.133 80 { weight 1 HTTP_GET { url { path / status_code 200 } connect_timeout 1 nb_get_retry 3 delay_before_retry 1 } } real_server 192.168.38.136 80 { weight 1 HTTP_GET { url { path / status_code 200 } connect_timeout 1 nb_get_retry 3 delay_before_retry 1 } } }
lvs2的keepalivbed.conf
[root@lvs2 keepalived]# cat keepalived.conf [root@lvs1 keepalived]# cat keepalived.conf ! Configuration File for keepalived global_defs { router_id node1 vrrp_mcast_group4 224.123.0.19 } vrrp_script chk_nginx { script "/etc/keepalived/check_keepalived.sh" interval 2 } vrrp_instance VI_1 { state BACKUP interface eth0 virtual_router_id 52 priority 99 advert_int 1 authentication { auth_type PASS auth_pass 1dadcvsd2 } virtual_ipaddress { 192.168.38.189/16 dev eth0 } track_script { chk_nginx } notify_master "/etc/keepalived/notify.sh master" notify_backup "/etc/keepalived/notify.sh backup" notify_fault "/etc/keepalived/notify.sh fault" } virtual_server 192.168.38.189 80 { delay_loop 3 lb_algo sh lb_kind DR protocol TCP real_server 192.168.38.133 80 { weight 1 HTTP_GET { url { path / status_code 200 } connect_timeout 1 nb_get_retry 3 delay_before_retry 1 } } real_server 192.168.38.136 80 { weight 1 HTTP_GET { url { path / status_code 200 } connect_timeout 1 nb_get_retry 3 delay_before_retry 1 } } }
测试VIP转移
[root@lvs1 keepalived]# systemctl stop keepalived [root@lvs2 keepalived]# ip a show dev eth0 2: eth0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UP group default qlen 1000 link/ether 00:0c:29:d3:0f:22 brd ff:ff:ff:ff:ff:ff inet 192.168.38.135/24 brd 192.168.38.255 scope global noprefixroute dynamic eth0 valid_lft 2591783sec preferred_lft 2591783sec inet 192.168.38.189/16 scope global eth0 valid_lft forever preferred_lft forever inet6 fe80::20c:29ff:fed3:f22/64 scope link noprefixroute valid_lft forever preferred_lft forever
web1和web2绑定VIP
[root@007-web1 ~]# cat lvs-dr.sh #!/bin/sh #LVS DR模式初始化脚本 #Zhang Shijie:2017-08-18 LVS_VIP=192.168.38.189 source /etc/rc.d/init.d/functions case "$1" in start) /sbin/ifconfig lo:0 $LVS_VIP netmask 255.255.255.255 broadcast $LVS_VIP /sbin/route add -host $LVS_VIP dev lo:0 echo "1" >/proc/sys/net/ipv4/conf/lo/arp_ignore echo "2" >/proc/sys/net/ipv4/conf/lo/arp_announce echo "1" >/proc/sys/net/ipv4/conf/all/arp_ignore echo "2" >/proc/sys/net/ipv4/conf/all/arp_announce echo "RealServer Start OK" ;; stop) /sbin/ifconfig lo:0 down /sbin/route del $LVS_VIP >/dev/null 2>&1 echo "0" >/proc/sys/net/ipv4/conf/lo/arp_ignore echo "0" >/proc/sys/net/ipv4/conf/lo/arp_announce echo "0" >/proc/sys/net/ipv4/conf/all/arp_ignore echo "0" >/proc/sys/net/ipv4/conf/all/arp_announce echo "RealServer Stoped" ;; *) echo "Usage: $0 {start|stop}" exit 1 esac exit 0 [root@007-web1 ~]# bash lvs-dr.sh start RealServer Start OK #web2同理
八、排查、lvs不显示后端服务器
[root@lvs1 keepalived]# ipvsadm -ln IP Virtual Server version 1.2.1 (size=4096) Prot LocalAddress:Port Scheduler Flags -> RemoteAddress:Port Forward Weight ActiveConn InActConn TCP 192.168.38.189:80 sh
手动curl发现返回302
[root@lvs1 keepalived]# curl 192.168.38.133 -I HTTP/1.1 302 Found Server: nginx/1.17.5 Date: Mon, 11 Nov 2019 03:39:12 GMT Content-Type: text/html; charset=UTF-8 Connection: keep-alive X-Powered-By: PHP/7.3.10 Location: http://192.168.38.133/wp-admin/setup-config.php
解决:web服务器创建test.html测试页面做健康检查
[root@007-web1 wordpress]# echo test > test.html [root@007-web1 wordpress]# scp test.html 192.168.38.136:/va/www/wordpress/
两个lvs修改健康检查
[root@lvs2 keepalived]# vim /etc/keepalived/keepalived.conf ....... real_server 192.168.38.133 80 { weight 1 HTTP_GET { url { path /test.html status_code 200 } connect_timeout 1 nb_get_retry 3 delay_before_retry 1 } } real_server 192.168.38.136 80 { weight 1 HTTP_GET { url { path /test.html status_code 200 } connect_timeout 1 nb_get_retry 3 delay_before_retry 1 } } ......
随后停止并启动keepalived,就好了
[root@lvs2 keepalived]# ipvsadm -ln IP Virtual Server version 1.2.1 (size=4096) Prot LocalAddress:Port Scheduler Flags -> RemoteAddress:Port Forward Weight ActiveConn InActConn TCP 192.168.38.189:80 sh -> 192.168.38.133:80 Route 1 0 0 -> 192.168.38.136:80 Route 1 0 0
另外wordpress的图片目录为uploads不是upload
九、优化
各个服务优化 NFS设置好权限控制,不能777 wordpress测试好友一些东西可以放到NFS,或者同步web1的网站数据到web2,主要是一些主题什么的
NFS权限限制
权限改成755还是成功了
[root@007-mysql-master ~]# chmod 755 -R /data/wordpress/ [root@007-mysql-master ~]# ll /data/wordpress/2019/11/total 292 -rwxr-xr-x 1 mysql mysql 98728 Nov 11 20:18 89a9f78ed9a0e3a9d0ad9a4836a79c7f.png -rw-r--r-- 1 mysql mysql 5101 Nov 11 20:20 9ad3c6f0d10514c88930974484e7a143.png -rwxr-xr-x 1 mysql mysql 186355 Nov 11 20:17 da7999e9b9174995d894cab24e20565a.png
问什么呢?为啥能上传成功,且用户为mysql
原因:web客户端的nginx用户ID为995
[root@007-web2 ~]# id nginx uid=997(nginx) gid=995(nginx) groups=995(nginx)
NFS这边mysql用户的id也是995
[root@007-mysql-master ~]# id mysql uid=997(mysql) gid=995(mysql) groups=995(mysql)
/data/wordpress/2019是已经生成的,属主为mysql(id995)
[root@007-mysql-master ~]# ls -l /data/wordpress/total 0 drwxr-xr-x 3 mysql mysql 16 Nov 11 20:17 2019
但是wordpress无法在/data/wordpress目录下生成新目录,可以设置acl权限给id为995用户(最好手动创建一个id为995的用户)
[root@007-mysql-master ~]# setfacl -m u:mysql:rwx /data/wordpress/ [root@007-mysql-master ~]# getfacl /data/wordpress/ getfacl: Removing leading '/' from absolute path names # file: data/wordpress/ # owner: root # group: root user::rwx user:mysql:rwx group::r-x mask::rwx other::r-x
或者NFS设置权限,类似于下面这样:
web1和web2的网站数据同步是比较困难的,wordpress变化的数据比较多,主题,图片等等,不只是uploads目录,最好都放NFS吧