雙機熱備+負載均衡線上方案(Heartbeat+DRBD+NFS+Keepalived+Lnmp)

火星人 @ 2014-03-04 , reply:0


雙機熱備+負載均衡線上方案(Heartbeat+DRBD+NFS+Keepalived+Lnmp)

我們下面來實現一個架構,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保證了每個節點的可靠性,幾乎完美!
拓撲圖如下:
http://www.centos.bz/wp-content/uploads/2012/03/heartbeat-drbd-nfs-keepalived-lnmp.jpg
架構實現LNMP架構配置配置LNMp架構需要注意兩點:
注意一:這裡MYSQL都不要初始化,不要啟動!後面有專門的配置的
注意二:nginx所有埠都改成 8080,因為一會還要安裝nginx來做均衡器並對外提供服務,所以不要用默認的80
注意三、nginx和php-fpm運行的用戶都是www。
安裝配置NFS1、安裝NFS

[*]yum install nfs-utils nfs4-acl-tools portmap

2、配置/etc/exports

[*]/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、啟動

[*]service portmap start
[*]service nfs start

切忌,必須先啟動portmap

[*]chkconfig  nfs off
[*]chkconfig  portmap on

注意:portmap伺服器必須常駐,且不收heartbeat管理;而nfs這必須要用heartbeat來管理他的啟動和關閉,所以這裡要關閉nfs開機自動啟動
同時要啟動鎖機制,因為同時有兩個節點要使用同一份數據,所以需要有總裁,這個尤其是在NFS給mysql用的時候是必須要用的,對於論壇或網站,要看情況,如果存在對同一文件同時修改的時候必須要啟動NFS鎖機制,如果沒有這種情況,那麼建議不要啟動,啟動了會降低NFS的性能:

[*]/sbin/rpc.lockd
[*]echo "/sbin/rpc.lockd" >>/etc/rc.local

4、開機自動掛載

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

為什麼為延遲20秒再掛載nfs?因為如果不等待立即掛載,會發現掛載不上,這是由於heartbeat啟動用的vip還沒設置好的原因。
立即掛載:

[*]mount -a

安裝配置DRBD安裝方法見:http://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

[*]include "drbd.d/global_common.conf";
[*]include "drbd.d/*.res";

2、global_common.conf

[*]global {
[*]  usage-count yes;
[*]}
[*]common {
[*]  net {
[*]    protocol C;
[*]  }
[*]}

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

[*]vi /usr/local/drbd/etc/drbd.d/mysql.res


[*]#資源組的名稱
[*]resource mysql{
[*]
[*]#定義主伺服器資源
[*]        on node1{
[*]#建立塊設備文件
[*]        device /dev/drbd1;
[*]#要用於複製的分區
[*]        disk /dev/sdb1;
[*]#定義偵聽IP和埠
[*]        address 192.168.1.10:7788;
[*]#meta data信息存放的方式,這裡為內部存儲,即和真實數據放在一起存儲
[*]        meta-disk internal;
[*]                   }
[*]
[*]#定義備伺服器資源
[*]        on node2{
[*]        device /dev/drbd1;
[*]        disk /dev/sdb1;
[*]        address 192.168.1.20:7788;
[*]        meta-disk internal;
[*]                   }
[*]
[*]                }

www.res:

[*]vi /usr/local/drbd/etc/drbd.d/www.res


[*]#資源組的名稱
[*]resource www{
[*]
[*]#定義主伺服器資源
[*]        on node2{
[*]#建立塊設備文件
[*]        device /dev/drbd2;
[*]#要用於複製的分區
[*]        disk /dev/sdb2;
[*]#定義偵聽IP和埠
[*]        address 192.168.1.20:7789;
[*]#meta data信息存放的方式,這裡為內部存儲,即和真實數據放在一起存儲
[*]        meta-disk internal;
[*]                   }
[*]
[*]#定義備伺服器資源
[*]        on node1{
[*]        device /dev/drbd2;
[*]        disk /dev/sdb2;
[*]        address 192.168.1.10:7789;
[*]        meta-disk internal;
[*]                   }
[*]
[*]                }

最後複製這些文件到node2。
初始化DRBD資源1)在各個節點啟用資源mysql和www

[*]modprobe drbd
[*]dd if=/dev/zero of=/dev/sdb1 bs=1M count=10
[*]dd if=/dev/zero of=/dev/sdb2 bs=1M count=10
[*]drbdadm create-md mysql
[*]drbdadm create-md www
[*]drbdadm up mysql
[*]drbdadm up www

2),提升各個節點上的主
在node1上:

[*]drbdadm primary --force mysql

在node2上:

[*]drbdadm primary --force www

3)格式化drbd塊設備
在node1上

[*]mkfs.ext3 /dev/drbd1

在node2上

[*]mkfs.ext3 /dev/drbd2

4)掛載分區
在node1上

[*]mount /dev/drbd1 /data/mysql

在node2上

[*]mount /dev/drbd2 /data/wwwfs

安裝配置heartbeat1、安裝heartbeat

[*]yum install heartbeat

安裝完後會自動建立用戶hacluster和組haclient
確保兩個節點上hacluster用戶的的UID和GID相同
2、同步兩台節點的時間

[*]rm -rf /etc/localtime
[*]\cp -f /usr/share/zoneinfo/Asia/Shanghai /etc/localtime
[*]yum install -y ntp
[*]ntpdate -d cn.pool.ntp.org

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

[*]debugfile /var/log/ha-debug                             #打開錯誤日誌報告
[*]keepalive 2                                             #兩秒檢測一次心跳線連接
[*]deadtime 10                                             #10 秒測試不到主伺服器心跳線為有問題出現
[*]warntime 6                                              #警告時間(最好在 2 ~ 10 之間)
[*]initdead 120                                            #初始化啟動時 120 秒無連接視為正常,或指定heartbeat
[*]                                                        #在啟動時,需要等待120秒才去啟動任何資源。
[*]
[*]udpport 694                                             #用 udp 的 694 埠連接
[*]ucast eth0 192.168.1.20                                #單播方式連接(主從都寫對方的 ip 進行連接)
[*]node   node1                                           #聲明主服(注意是主機名uname -n不是域名)
[*]node   node2                                           #聲明備服(注意是主機名uname -n不是域名)
[*]auto_failback on                                        #自動切換(主服恢復后可自動切換回來)這個不要開啟
[*]respawn hacluster /usr/lib/heartbeat/ipfail           #監控ipfail進程是否掛掉,如果掛掉就重啟它

4、/etc/ha.d/authkeys

[*]auth 1
[*]1 crc

5、/etc/ha.d/haresources

[*]node1 IPaddr::192.168.1.100/24/eth0 drbddisk::mysql Filesystem::/dev/drbd1::/data/mysql::ext3 mysqld portmap
[*]node2 IPaddr::192.168.1.200/24/eth0 drbddisk::www Filesystem::/dev/drbd2::/data/wwwnfs::ext3 portmap nfs

6、創建nfs管理腳本

[*]vi /etc/ha.d/resource.d/nfs

寫入:

[*]#!/bin/bash
[*]
[*]NFSD=/etc/rc.d/init.d/nfs
[*]NFSDPID=`/sbin/pidof nfsd`
[*]case $1 in
[*]start)
[*]$NFSD start;
[*];;
[*]stop)
[*]$NFSD stop;
[*]        if [ "$NFSDPID" != " " ];then
[*]                for NFSPID in $NFSDPID
[*]                do /bin/kill -9 $NFSPID;
[*]                done
[*]        fi
[*];;
[*]*)
[*]echo "Syntax incorrect. You need one of {start|stop }"
[*];;
[*]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均衡器配置
[*]user  www;
[*]worker_processes  1;
[*]
[*]error_log  /var/log/nginx/error.log warn;
[*]pid        /var/run/nginx.pid;
[*]
[*]
[*]events {
[*]    worker_connections  1024;
[*]}
[*]
[*]
[*]http {
[*]    include       /etc/nginx/mime.types;
[*]    default_type  application/octet-stream;
[*]
[*]    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;
[*]
[*]    keepalive_timeout  65;
[*]
[*]    #gzip  on;
[*] upstream www.centos.bz_server
[*]  {
[*]  server 192.168.1.10:8080 weight=3 max_fails=2 fail_timeout=30s;
[*]  server 192.168.1.20:8080 weight=9 max_fails=2 fail_timeout=30s;
[*]  }
[*]  server
[*]  {
[*]    listen       80;
[*]    server_name  www.centos.bz;
[*]    location / {
[*]    root /data/www/www.centos.bz;
[*]    index index.php index.htm index.html;
[*]    proxy_redirect off;
[*]    proxy_set_header Host $host;
[*]    proxy_set_header X-Real-IP $remote_addr;
[*]    proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
[*]    proxy_pass http://www.centos.bz_server;
[*]    }
[*]    access_log  off;
[*]  }
[*]server
[*]  {
[*]    listen       8080;
[*]    server_name  www.centos.bz;
[*]    index index.html index.htm index.php;
[*]    root  /data/www/www.centos.bz;
[*]    #limit_conn   crawler  20;
[*] location ~ \.php$ {
[*]        root           /data/www/www.centos.bz;
[*]        fastcgi_pass   127.0.0.1:9000;
[*]        fastcgi_index  index.php;
[*]        fastcgi_param  SCRIPT_FILENAME  /data/www/www.centos.bz/$fastcgi_script_name;
[*]        include        fastcgi_params;
[*]    }
[*]    location ~ .*\.(gif|jpg|jpeg|png|bmp|swf)$
[*]    {
[*]      expires      30d;
[*]    }
[*]    location ~ .*\.(js|css)?$
[*]    {
[*]      expires      1h;
[*]    }
[*]    access_log  off;
[*]      }
[*]}

這裡定義了兩台用於負載均衡的機子,分別是192.168.1.10:8080和192.168.1.20:8080,通過proxy_pass http://www.centos.bz_server代理循詢轉發到這兩台機,達到負載均衡的作用。
你可以建立index.php,裡面寫入:

[*]<?php
[*]echo $_SERVER['SERVER_ADDR'];
[*]?>

如果連續刷新幾次,得到不同的IP,證明已經均衡負載到不同的伺服器。
Keepalived實現nginx和php的HA1、keepalived安裝
安裝方法見:http://www.centos.bz/2012/02/nginx-keepalived-high-availability/
2、配置
節點一node1配置如下:

[*]global_defs {
[*]   notification_email {
[*]     admin@centos.bz
[*]   }
[*]   notification_email_from keepalived@domain.com
[*]   smtp_server 127.0.0.1
[*]   smtp_connect_timeout 30
[*]   router_id LVS_DEVEL
[*]}
[*]vrrp_instance VI_1 {
[*]    state MASTER        ############ 輔機為 BACKUP
[*]    interface eth0
[*]    virtual_router_id 100
[*]    mcast_src_ip 192.168.1.10  ########### 本機IP
[*]    priority 102                  ########### 權值要比 back 高
[*]    advert_int 1
[*]    authentication {
[*]        auth_type PASS
[*]        auth_pass 1111
[*]    }
[*]    virtual_ipaddress {
[*]       12.12.12.100
[*]    }
[*]}
[*]
[*]vrrp_instance VI_1 {
[*]    state BACKUP
[*]    interface eth0
[*]    virtual_router_id 200
[*]    mcast_src_ip 192.168.1.101 ########### 本機IP
[*]    priority 101              ##########權值 要比 master 低。。
[*]    advert_int 1
[*]    authentication {
[*]        auth_type PASS
[*]        auth_pass 1111
[*]    }
[*]    virtual_ipaddress {
[*]       12.12.12.200
[*]    }
[*]}

節點二配置:

[*]global_defs {
[*]   notification_email {
[*]     admin@centos.bz
[*]   }
[*]   notification_email_from keepalived@domain.com
[*]   smtp_server 127.0.0.1
[*]   smtp_connect_timeout 30
[*]   router_id LVS_DEVEL
[*]}
[*]vrrp_instance VI_1 {
[*]    state BACKUP
[*]    interface eth0
[*]    virtual_router_id 100
[*]    mcast_src_ip 192.168.1.20 ########### 本機IP
[*]    priority 101              ##########權值 要比 master 低。。
[*]    advert_int 1
[*]    authentication {
[*]        auth_type PASS
[*]        auth_pass 1111
[*]    }
[*]    virtual_ipaddress {
[*]       12.12.12.100
[*]    }
[*]}
[*]
[*]vrrp_instance VI_1 {
[*]    state MASTER        ############ 輔機為 BACKUP
[*]    interface eth0
[*]    virtual_router_id 200
[*]    mcast_src_ip 192.168.1.103  ########### 本機IP
[*]    priority 102                  ########### 權值要比 back 高
[*]    advert_int 1
[*]    authentication {
[*]        auth_type PASS
[*]        auth_pass 1111
[*]    }
[*]    virtual_ipaddress {
[*]       12.12.12.200
[*]    }
[*]}

3、創建監控腳本
node1監控腳本:

[*]vi /opt/check.sh


[*]#!/bin/bash
[*]while  :
[*]do
[*]mysqlcheck=`/usr/bin/mysqladmin -uroot ping 2>&1`
[*]mysqlcode=`echo $?`
[*]heartbeat=`ps -C heartbeat --no-header | wc -l`
[*]if [ $mysqlcode -ne 0 ] ;then
[*] if [ $heartbeat-ne 0 ];then
[*]service heartbeat stop
[*]fi
[*]fi
[*]phpcheck=`ps -C php-fpm --no-header | wc -l`
[*]nginxcheck=`ps -C nginx --no-header | wc -l`
[*]keepalivedcheck=`ps -C keepalived --no-header | wc -l`
[*]if [ $nginxcheck -eq 0 ]|| [ $phpcheck -eq 0 ];then
[*]                if [ $keepalivedcheck -ne 0 ];then
[*]                   killall -TERM keepalived
[*]                else
[*]                   echo "keepalived is stoped"
[*]                fi
[*]        else
[*]                if [ $keepalivedcheck -eq 0 ];then
[*]                   /etc/init.d/keepalived start
[*]                else
[*]                   echo "keepalived is running"
[*]                fi
[*]fi
[*]sleep 5
[*]done

node2監控腳本:

[*]#!/bin/bash
[*]while  :
[*]do
[*]phpcheck=`ps -C php-cgi --no-header | wc -l`
[*]nginxcheck=`ps -C nginx --no-header | wc -l`
[*]keepalivedcheck=`ps -C keepalived --no-header | wc -l`
[*]if [ $nginxcheck -eq 0 ]|| [ $phpcheck -eq 0 ];then
[*]                if [ $keepalivedcheck -ne 0 ];then
[*]                   killall -TERM keepalived
[*]                else
[*]                   echo "keepalived is stoped"
[*]                fi
[*]        else
[*]                if [ $keepalivedcheck -eq 0 ];then
[*]                   /etc/init.d/keepalived start
[*]                else
[*]                   echo "keepalived is running"
[*]                fi
[*]fi
[*]sleep 5
[*]done

這個監控代碼實現了mysql,nginx,php-fpm的HA。
加上許可權,並執行

[*]chmod +x /opt/check.sh
[*]nohup sh /opt/check.sh &

設置開機啟動:
echo 「nohup sh /opt/check.sh &」 >> /etc/rc.loal
4、測試keepalived
分別啟動keepalived

[*]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
《解決方案》

:lol謝謝分享,收益
《解決方案》

好帖一定要頂!!!!!
《解決方案》

謝謝分享
《解決方案》

必須得頂啊,謝謝分享:mrgreen:
《解決方案》

非常感謝,詳細,見識了
《解決方案》

raresk 發表於 2012-04-16 11:06 static/image/common/back.gif
非常感謝,詳細,見識了
大家多交流,這個也是我在學習的過程中發現的,順便共享給大家
《解決方案》

學習了,馬上在虛擬機上實驗lz的方案
《解決方案》

頂一個!!!




[火星人 via ] 雙機熱備+負載均衡線上方案(Heartbeat+DRBD+NFS+Keepalived+Lnmp)已經有856次圍觀

http://www.coctec.com/docs/service/show-post-4154.html