双机热备+负载均衡线上方案(Heartbeat+DRBD+NFS+Keepalived+Lnmp)

如遇技术问题,请联系博主帮您解决QQ 452336092(添加时注明”付费技术支持”)。

文章目录
[隐藏]

我们下面来实现一个架构,heartbeat+drbd+nfs实现mysql和网站数据的同步,keepalived实现nginx的高可用,而用nginx和dns轮询实现负载均衡。

架构说明

目录规划

/usr/local/src/lnmp:用来存放源码工具等等
/data:用来存放所有数据和NFS以及DRBD的挂载
/data/shell:用来存放所有管理脚本
/data/mysql:用来挂载DRBD的mysql资源,以供mysql存放数据库
/data/wwwnfs:用来挂载DRBD生成的www资源,以供两个节点挂载到各个节点的/data/www目录,以供论坛等程序数据使用
/data/www:用来挂载NFS资源,用来存放论坛(网站)等程序数据

拓扑工作原理

内网:
1,DRBD网络存储创建出两个资源,一个mysql给mysql数据库同步用,一个www给web(论坛)数据NFS共享挂载用,虚拟出两个虚拟IP,一个是 192.168.1.100,用来连接数据库,一个是192.168.1.200,用来给节点挂载NFS
注意:NFS底下挂载了三次:DRBD挂载一次,文件系统挂载一次,客户端挂载一次
2,Heartbeat来实现DRBD的HA,同时虚拟出两个内网IP,并管理NFS,MySQL的启动和关闭

外网:
1,两个节点都用Nginx做均衡器,通过内网调度负载两个节点,实现内部均衡
2,DNS配置双IP对应一个域名的方式来实现DNS轮询,实现外网均衡
3,Keepalived使用双主(master)配置虚拟出两个虚拟IP:节点一 12.12.12.100和节点二 12.12.12.200,同时共外网访问,两个节点互为主从关系,当某个节点挂掉的时候,另外一个节点将同时是两个资源的master,同时拥有两个虚拟IP,实现资源转移。

我们知道DNS的缺点就是生效慢,分配资源不合理,理论上有可能把所有的请求都发送给同一节点,导致均衡不合理导致所有资源不可用,这里我们由于有了NGINX内部负载,就不怕DNS轮询不均衡了,因为NGINX内部有严谨的调度方式,不管那台请求有多少,在内部都能实现理想的调度,这样就能把DNS负载均衡和NGINX完美结合,是硬件资源得到合理的利用,然后利用keepalive保证了每个节点的可靠性,几乎完美!
拓扑图如下:

架构实现

LNMP架构配置

配置LNMp架构需要注意两点:
注意一:这里MYSQL都不要初始化,不要启动!后面有专门的配置的
注意二:nginx所有端口都改成 8080,因为一会还要安装nginx来做均衡器并对外提供服务,所以不要用默认的80
注意三、nginx和php-fpm运行的用户都是www。

安装配置NFS

1、安装NFS

  1. yum install nfs-utils nfs4-acl-tools portmap

2、配置/etc/exports

  1. /data/wwwnfs 192.168.1.0/24(rw,,no_root_squash,sync,anonuid=502,anongid=502)

注意:
/data/wwwnfs:就是给两个节点挂载的目录,所有网站程序都放在这里,实现论坛程序等数据的共享(同步)
anonuid=502,anongid=502:这个表示客户端上任何用户进入到挂载目录都以uid=502和gid=502身份,我这里这个代表的是www用户
3、启动

  1. service portmap start
  2. service nfs start

切忌,必须先启动portmap

  1. chkconfig  nfs off
  2. chkconfig  portmap on

注意:portmap服务器必须常驻,且不收heartbeat管理;而nfs这必须要用heartbeat来管理他的启动和关闭,所以这里要关闭nfs开机自动启动

同时要启动锁机制,因为同时有两个节点要使用同一份数据,所以需要有总裁,这个尤其是在NFS给mysql用的时候是必须要用的,对于论坛或网站,要看情况,如果存在对同一文件同时修改的时候必须要启动NFS锁机制,如果没有这种情况,那么建议不要启动,启动了会降低NFS的性能:

  1. /sbin/rpc.lockd
  2. echo "/sbin/rpc.lockd" >>/etc/rc.local

4、开机自动挂载

  1. echo "sleep 20" >>/etc/rc.local
  2. echo "/bin/mount -t nfs 192.168.1.200:/data/wwwnfs /data/www" >>/etc/rc.local

为什么为延迟20秒再挂载nfs?因为如果不等待立即挂载,会发现挂载不上,这是由于heartbeat启动用的vip还没设置好的原因。
立即挂载:

  1. mount -a

安装配置DRBD

安装方法见:https://www.centos.bz/2012/02/drbd-compile-install-deploy/

配置文件

DRBD有三种配置文件:
/usr/local/drbd/etc/drbd.conf
/usr/local/drbd/etc/drbd.d/global_common.conf
/usr/local/drbd/etc/drbd.d/*.res
1、drbd.conf

  1. include "drbd.d/global_common.conf";
  2. include "drbd.d/*.res";

2、global_common.conf

  1. global {
  2.   usage-count yes;
  3. }
  4. common {
  5.   net {
  6.     protocol C;
  7.   }
  8. }

3、mysql.res和www.res
mysql.res:

  1. vi /usr/local/drbd/etc/drbd.d/mysql.res
  1. #资源组的名称
  2. resource mysql{
  3.  
  4. #定义主服务器资源
  5.         on node1{
  6. #建立块设备文件
  7.         device /dev/drbd1;
  8. #要用于复制的分区
  9.         disk /dev/sdb1;
  10. #定义侦听IP和端口
  11.         address 192.168.1.10:7788;
  12. #meta data信息存放的方式,这里为内部存储,即和真实数据放在一起存储
  13.         meta-disk internal;
  14.                    }
  15.  
  16. #定义备服务器资源
  17.         on node2{
  18.         device /dev/drbd1;
  19.         disk /dev/sdb1;
  20.         address 192.168.1.20:7788;
  21.         meta-disk internal;
  22.                    }
  23.  
  24.                 }

www.res:

  1. vi /usr/local/drbd/etc/drbd.d/www.res
  1. #资源组的名称
  2. resource www{
  3.  
  4. #定义主服务器资源
  5.         on node2{
  6. #建立块设备文件
  7.         device /dev/drbd2;
  8. #要用于复制的分区
  9.         disk /dev/sdb2;
  10. #定义侦听IP和端口
  11.         address 192.168.1.20:7789;
  12. #meta data信息存放的方式,这里为内部存储,即和真实数据放在一起存储
  13.         meta-disk internal;
  14.                    }
  15.  
  16. #定义备服务器资源
  17.         on node1{
  18.         device /dev/drbd2;
  19.         disk /dev/sdb2;
  20.         address 192.168.1.10:7789;
  21.         meta-disk internal;
  22.                    }
  23.  
  24.                 }

最后复制这些文件到node2。

初始化DRBD资源

1)在各个节点启用资源mysql和www

  1. modprobe drbd
  2. dd if=/dev/zero of=/dev/sdb1 bs=1M count=10
  3. dd if=/dev/zero of=/dev/sdb2 bs=1M count=10
  4. drbdadm create-md mysql
  5. drbdadm create-md www
  6. drbdadm up mysql
  7. drbdadm up www

2),提升各个节点上的主
在node1上:

  1. drbdadm primary --force mysql

在node2上:

  1. drbdadm primary --force www

3)格式化drbd块设备
在node1上

  1. mkfs.ext3 /dev/drbd1

在node2上

  1. mkfs.ext3 /dev/drbd2

4)挂载分区
在node1上

  1. mount /dev/drbd1 /data/mysql

在node2上

  1. mount /dev/drbd2 /data/wwwnfs

安装配置heartbeat

1、安装heartbeat

  1. yum install heartbeat

安装完后会自动建立用户hacluster和组haclient
确保两个节点上hacluster用户的的UID和GID相同
2、同步两台节点的时间

  1. rm -rf /etc/localtime
  2. \cp -f /usr/share/zoneinfo/Asia/Shanghai /etc/localtime
  3. yum install -y ntp
  4. ntpdate -d cn.pool.ntp.org

3、配置/etc/ha.d/ha.cf

  1. debugfile /var/log/ha-debug                             #打开错误日志报告
  2. keepalive 2                                             #两秒检测一次心跳线连接
  3. deadtime 10                                             #10 秒测试不到主服务器心跳线为有问题出现
  4. warntime 6                                              #警告时间(最好在 2 ~ 10 之间)
  5. initdead 120                                            #初始化启动时 120 秒无连接视为正常,或指定heartbeat
  6.                                                         #在启动时,需要等待120秒才去启动任何资源。
  7.  
  8. udpport 694                                             #用 udp 的 694 端口连接
  9. ucast eth0 192.168.1.20                                #单播方式连接(主从都写对方的 ip 进行连接)
  10. node   node1                                           #声明主服(注意是主机名uname -n不是域名)
  11. node   node2                                           #声明备服(注意是主机名uname -n不是域名)
  12. auto_failback on                                        #自动切换(主服恢复后可自动切换回来)这个不要开启
  13. respawn hacluster /usr/lib/heartbeat/ipfail           #监控ipfail进程是否挂掉,如果挂掉就重启它

4、/etc/ha.d/authkeys

  1. auth 1
  2. 1 crc

5、/etc/ha.d/haresources

  1. node1 IPaddr::192.168.1.100/24/eth0 drbddisk::mysql Filesystem::/dev/drbd1::/data/mysql::ext3 mysqld portmap
  2. node2 IPaddr::192.168.1.200/24/eth0 drbddisk::www Filesystem::/dev/drbd2::/data/wwwnfs::ext3 portmap nfs

6、创建nfs管理脚本

  1. vi /etc/ha.d/resource.d/nfs

写入:

  1. #!/bin/bash
  2.  
  3. NFSD=/etc/rc.d/init.d/nfs
  4. NFSDPID=`/sbin/pidof nfsd`
  5. case $1 in
  6. start)
  7. $NFSD start;
  8. ;;
  9. stop)
  10. $NFSD stop;
  11.         if [ "$NFSDPID" != " " ];then
  12.                 for NFSPID in $NFSDPID
  13.                 do /bin/kill -9 $NFSPID;
  14.                 done
  15.         fi
  16. ;;
  17. *)
  18. echo "Syntax incorrect. You need one of {start|stop }"
  19. ;;
  20. esac

先启动node1的heartbeat,再启动node2的heartbeat
启动成功后,这里有几项需要检查
node1:
1、执行ip a,检查是否已经设置有虚拟ip 192.168.1.100
2、执行cat /proc/drbd检查状态是否正常
3、执行df -h查看/dev/drbd1是否已经挂载到/data/mysql
4、执行service mysqld status查看mysql是否已经启动
node2:
1、执行ip a查看是否已经设置虚拟ip 192.168.1.200
2、执行cat /proc/drbd检查状态是否正常
3、执行df -h查看/dev/drbd2是否已经挂载到/data/wwwnfs和192.168.1.200:/data/wwwnfs是否已经挂载到/data/www

nginx均衡器配置

  1. user  www;
  2. worker_processes  1;
  3.  
  4. error_log  /var/log/nginx/error.log warn;
  5. pid        /var/run/nginx.pid;
  6.  
  7.  
  8. events {
  9.     worker_connections  1024;
  10. }
  11.  
  12.  
  13. http {
  14.     include       /etc/nginx/mime.types;
  15.     default_type  application/octet-stream;
  16.  
  17.     log_format  main  '$remote_addr - $remote_user [$time_local] "$request" '
  18.                       '$status $body_bytes_sent "$http_referer" '
  19.                       '"$http_user_agent" "$http_x_forwarded_for"';
  20.  
  21.     access_log  /var/log/nginx/access.log  main;
  22.  
  23.     sendfile        on;
  24.     #tcp_nopush     on;
  25.  
  26.     keepalive_timeout  65;
  27.  
  28.     #gzip  on;
  29.  upstream www.centos.bz_server
  30.   {
  31.   server 192.168.1.10:8080 weight=3 max_fails=2 fail_timeout=30s;
  32.   server 192.168.1.20:8080 weight=9 max_fails=2 fail_timeout=30s;
  33.   }
  34.   server
  35.   {
  36.     listen       80;
  37.     server_name  www.centos.bz;
  38.     location / {
  39.     root /data/www/www.centos.bz;
  40.     index index.php index.htm index.html;
  41.     proxy_redirect off;
  42.     proxy_set_header Host $host;
  43.     proxy_set_header X-Real-IP $remote_addr;
  44.     proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
  45.     proxy_pass https://www.centos.bz_server;
  46.     }
  47.     access_log  off;
  48.   }
  49. server
  50.   {
  51.     listen       8080;
  52.     server_name  www.centos.bz;
  53.     index index.html index.htm index.php;
  54.     root  /data/www/www.centos.bz;
  55.     #limit_conn   crawler  20;
  56.  location ~ \.php$ {
  57.         root           /data/www/www.centos.bz;
  58.         fastcgi_pass   127.0.0.1:9000;
  59.         fastcgi_index  index.php;
  60.         fastcgi_param  SCRIPT_FILENAME  /data/www/www.centos.bz/$fastcgi_script_name;
  61.         include        fastcgi_params;
  62.     }
  63.     location ~ .*\.(gif|jpg|jpeg|png|bmp|swf)$
  64.     {
  65.       expires      30d;
  66.     }
  67.     location ~ .*\.(js|css)?$
  68.     {
  69.       expires      1h;
  70.     }
  71.     access_log  off;
  72.       }
  73. }

这里定义了两台用于负载均衡的机子,分别是192.168.1.10:8080和192.168.1.20:8080,通过proxy_pass https://www.centos.bz_server代理循询转发到这两台机,达到负载均衡的作用。
你可以建立index.php,里面写入:

  1. <?php
  2. echo $_SERVER['SERVER_ADDR'];
  3. ?>

如果连续刷新几次,得到不同的IP,证明已经均衡负载到不同的服务器。

Keepalived实现nginx和php的HA

1、keepalived安装
安装方法见:https://www.centos.bz/2012/02/nginx-keepalived-high-availability/
2、配置
节点一node1配置如下:

  1. global_defs {
  2.    notification_email {
  3.      admin@centos.bz
  4.    }
  5.    notification_email_from keepalived@domain.com
  6.    smtp_server 127.0.0.1
  7.    smtp_connect_timeout 30
  8.    router_id LVS_DEVEL
  9. }
  10. vrrp_instance VI_1 {
  11.     state MASTER        ############ 辅机为 BACKUP
  12.     interface eth0
  13.     virtual_router_id 100
  14.     mcast_src_ip 192.168.1.10  ########### 本机IP
  15.     priority 102                  ########### 权值要比 back 高
  16.     advert_int 1
  17.     authentication {
  18.         auth_type PASS
  19.         auth_pass 1111
  20.     }
  21.     virtual_ipaddress {
  22.        12.12.12.100
  23.     }
  24. }
  25.  
  26. vrrp_instance VI_1 {
  27.     state BACKUP
  28.     interface eth0
  29.     virtual_router_id 200
  30.     mcast_src_ip 192.168.1.101 ########### 本机IP
  31.     priority 101              ##########权值 要比 master 低。。
  32.     advert_int 1
  33.     authentication {
  34.         auth_type PASS
  35.         auth_pass 1111
  36.     }
  37.     virtual_ipaddress {
  38.        12.12.12.200
  39.     }
  40. }

节点二配置:

  1. global_defs {
  2.    notification_email {
  3.      admin@centos.bz
  4.    }
  5.    notification_email_from keepalived@domain.com
  6.    smtp_server 127.0.0.1
  7.    smtp_connect_timeout 30
  8.    router_id LVS_DEVEL
  9. }
  10. vrrp_instance VI_1 {
  11.     state BACKUP
  12.     interface eth0
  13.     virtual_router_id 100
  14.     mcast_src_ip 192.168.1.20 ########### 本机IP
  15.     priority 101              ##########权值 要比 master 低。。
  16.     advert_int 1
  17.     authentication {
  18.         auth_type PASS
  19.         auth_pass 1111
  20.     }
  21.     virtual_ipaddress {
  22.        12.12.12.100
  23.     }
  24. }
  25.  
  26. vrrp_instance VI_1 {
  27.     state MASTER        ############ 辅机为 BACKUP
  28.     interface eth0
  29.     virtual_router_id 200
  30.     mcast_src_ip 192.168.1.103  ########### 本机IP
  31.     priority 102                  ########### 权值要比 back 高
  32.     advert_int 1
  33.     authentication {
  34.         auth_type PASS
  35.         auth_pass 1111
  36.     }
  37.     virtual_ipaddress {
  38.        12.12.12.200
  39.     }
  40. }

3、创建监控脚本
node1监控脚本:

  1. vi /opt/check.sh
  1. #!/bin/bash
  2. while  :
  3. do
  4. mysqlcheck=`/usr/bin/mysqladmin -uroot ping 2>&1`
  5. mysqlcode=`echo $?`
  6. heartbeat=`ps -C heartbeat --no-header | wc -l`
  7. if [ $mysqlcode -ne 0 ] ;then
  8.  if [ $heartbeat-ne 0 ];then
  9. service heartbeat stop
  10. fi
  11. fi
  12. phpcheck=`ps -C php-fpm --no-header | wc -l`
  13. nginxcheck=`ps -C nginx --no-header | wc -l`
  14. keepalivedcheck=`ps -C keepalived --no-header | wc -l`
  15. if [ $nginxcheck -eq 0 ]|| [ $phpcheck -eq 0 ];then
  16.                 if [ $keepalivedcheck -ne 0 ];then
  17.                    killall -TERM keepalived
  18.                 else
  19.                    echo "keepalived is stoped"
  20.                 fi
  21.         else
  22.                 if [ $keepalivedcheck -eq 0 ];then
  23.                    /etc/init.d/keepalived start
  24.                 else
  25.                    echo "keepalived is running"
  26.                 fi
  27. fi
  28. sleep 5
  29. done

node2监控脚本:

  1. #!/bin/bash
  2. while  :
  3. do
  4. phpcheck=`ps -C php-cgi --no-header | wc -l`
  5. nginxcheck=`ps -C nginx --no-header | wc -l`
  6. keepalivedcheck=`ps -C keepalived --no-header | wc -l`
  7. if [ $nginxcheck -eq 0 ]|| [ $phpcheck -eq 0 ];then
  8.                 if [ $keepalivedcheck -ne 0 ];then
  9.                    killall -TERM keepalived
  10.                 else
  11.                    echo "keepalived is stoped"
  12.                 fi
  13.         else
  14.                 if [ $keepalivedcheck -eq 0 ];then
  15.                    /etc/init.d/keepalived start
  16.                 else
  17.                    echo "keepalived is running"
  18.                 fi
  19. fi
  20. sleep 5
  21. done

这个监控代码实现了mysql,nginx,php-fpm的HA。
加上权限,并执行

  1. chmod +x /opt/check.sh
  2. nohup sh /opt/check.sh &

设置开机启动:
echo “nohup sh /opt/check.sh &” >> /etc/rc.local

4、测试keepalived
分别启动keepalived

  1. service keepalived start

1)执行ip a检查node1和node2是否已经存在vip:12.12.12.100和12.12.12.200
2)测试nginx和php-fpm的HA。在node1执行service nginx stop或者service php-fpm stop停止nginx或php-fpm,过几秒钟后你会发现node2已经接管了vip 12.12.12.100,并且使用vip 12.12.12.100或12.12.12.200浏览nginx网页你会发现网页显示的IP一直是192.168.1.20,表明keepalived已经成功接管node1的vip和nginx或php-fpm服务。
3)测试mysql HA。在node1执行service mysqld stop停止mysql服务,几秒后在node2查看,发现node2已经接管vip 192.168.1.100,并且已经启动mysql服务。
注意:在恢复mysql或nginx,php-fpm时,先停止监控脚本,要不heartbeat或keepalived还没实现接管又被停止。
参考:http://bbs.ywlm.net/thread-965-1-1.html

转载请保留原文链接:Linux运维日志 » 双机热备+负载均衡线上方案(Heartbeat+DRBD+NFS+Keepalived+Lnmp)

打赏

如果此文对你有所帮助,请随意打赏鼓励作者^_^

评论 15

  • 昵称 (必填)
  • 邮箱 (必填)
  • 网址
  1. 电脑天空老大 高手啊, 我太崇拜你了 ,呵呵。回复
  2. 小金金这个我要验证一下,才能说回复
  3. 小金金你写的一部分文档不错,但还有一部分不贴近线上环境,不能直接用在生产上面,比如mysql主从,tar cvf这种只能用在刚建立的新服务器上吧?已经跑了一段时间的,我觉得不应该这么用,不过还是给我一点知识上面的累积和启发,而且你的文档总体来说写的很详细。回复
  4. 小金金博主,您好,我想请问,DNS服务器上面要安装什么嘛?我理解能力差,对不起,能解释一下吗?回复
    • 朱 茂海dns可以用第三方的,不需要自己的安装,比如dnspod都可以,如果确实想自己搭建,那直接搭建bind吧回复
  5. vpsio您好 我想和您谈下关于网站投放广告的事宜 :) 我QQ:23363038回复
  6. 纪名松学习中。 :razz:回复
  7. locknode2 重启后,怎么不挂载192.168.1.200:/data/wwwnfs到/data/www下?回复
    • 朱 茂海再仔细检查一遍吧回复
      • lock@朱 茂海 在rc.local里都写过了,不自动加载,还有一个问题,两台机子重启后,都是Secondary/Secondary,只要在任一节点机上重新启动一下heartbeat,才会变成node1 mysql是主,node2 www是主,不知怎么回事~回复
      • benben@朱 茂海 另。。mcast_src_ip 192.168.1.101 ########### 本机IP 节点1、2同时出现两次‘本机IP’容易引起混绕,建议更改为节点x-第几网卡IP,如: node1-eth0 IP :smile:回复
  8. benben首先感谢博主的精彩分享^_^,顺便指出文章中两处错误: 0、安装NFS yum install nfs-utils nfs4-acl-tools portmap (portmap 最新已改为rpcbind) 1.mount /dev/drbd2 /data/wwwfs应为mount /dev/drbd2 /data/wwwnfs (wwwfs少了个n) 2.设置开机启动: echo "nohup sh /opt/check.sh &" >> /etc/rc.loal 应为: echo "nohup sh /opt/check.sh &" >> /etc/rc.local (rc.loal少了个c) :mrgreen:回复
    • 朱 茂海@benben Thanks,已修正 :cool:回复
      • benben@朱 茂海 还有哈。。 vrrp_instance VI_1 这个在每个借点keepalived配置了两个相同名称,可能会导致第一次配置的虚拟ip被覆盖,无法提供服务(我测试是这样的),不晓得是不是这样? :grin:回复
  9. losbyday我用火狐浏览器看的,怎么好多黑色小方块啊= =回复