Haproxy+Keepalived+Varnish+LAMP+Memcacked+NFS 實現web站點的動靜分離

Haproxy+Keepalived+Varnish+LAMP+Memcacked+NFS 實現web站點的動靜分離

(一)架構拓撲圖展示


這裏寫圖片描述

(二)架構的簡要說明


  • 本次動靜分離的源碼使用WordPress的開源程序,WordPress程序自身可以做到前臺與後臺的完全分離。爲了演示效果,使用NFS共享存儲(文件系統級共享)對外提供靜態資源和動態資源,並且將靜態資源掛載至靜態主機,動態資源掛載至動態主機。從外觀上感覺實現了動靜分離

(三)架構的實現的方式說明


  • 1:WordPress源碼放在動態服務器上,將靜態資源複製一份給NFS共享存儲目錄,將共享存儲目錄掛載至靜態服務器的站點。再將共享存儲目錄掛載至動態服務器對應的目錄,這樣使得程序的前臺和後臺能夠正常的訪問
  • 2:當用戶的請求到達Load balance的時候,將動態請求反向代理至APP Servers,將靜態請求反向代理至Varnish Servers
  • 3:當APP Servers接到動態請求,PHP引擎會根據是否需要查詢數據庫做出判斷,將解析的結果返回給haproxy反代服務器,再返回給用戶
  • 4:當Varnish Servers接到靜態請求的時候,會先查詢緩存機制中的子歷程,根據子歷程來判斷是否能夠查詢緩存,如何不能重新緩存的靜態請求通過調度算法,直接發往Static Servers服務器
  • 5:APP Servers服務器使用Memcached會話保持服務器,實現會話保持
  • 6:NFS共享存儲用來提供靜態資源的共享

(四)架構過程演示


一:配置keepalived雙主模型,實現Haproxy的高可用

  • 1:在haproxy1和haproxy2上安裝keepalived和haproxy
yum install -y keepalived haproxy
  • 2:配置haproxy1節點的keepalived主配置文件 /etc/keepalived/keepalived.conf
# 全局配置段

! Configuration File for keepalived
# 實現郵件報警功能,但是這裏必須首先在/etc/mail.rc中配置好第三方的郵件代理服務器

global_defs {
   notification_email {
    307443272@qq.com
   }
   notification_email_from yinhuanyi_cn@163.com
   smtp_server smtp.163.com
   smtp_connect_timeout 30
   # 給節點取一個id名
   router_id haproxy1
   # 指定傳遞心跳信息的多播地址
   vrrp_mcast_group4 224.0.100.18
}

# 定義一個監控haproxy是否正常工作的腳本,監控腳本需要寫在公共區,如果haproxy服務掛了,那麼就將其優先級減去20
# 這樣這個節點就是備節點,IP就會漂移
vrrp_script check_haproxy_available { 
    script "killall -0 haproxy" 
    interval 2 
    weight -20 
}

# 配置虛擬路由第一個實例
vrrp_instance VI_1 {
    # haproxy1爲主
    state MASTER
    interface enp0s3
    virtual_router_id 51
    priority 100
    advert_int 1
    authentication {
        auth_type PASS
        auth_pass 1111 
    }
    virtual_ipaddress {
        # 這裏最好給VIP取一個別名,這樣就能夠使用ifconfig命令查看VIP了
        192.168.23.100/24 dev enp0s3 label enp0s3:0
    }
    # 下面三行的意義是當VIP發生漂移的時候調用,例如notify_master表示:當VIP漂移到master節點,調用後面的腳本
    notify_master "/root/notify.sh master"
    notify_backup "/root/notify.sh backup"
    notify_fault "/root/notify.sh fault"
    # 這裏就是調用在公共區定義的監控haproxy健康狀態的腳本
    track_script { 
    check_haproxy_available  
    }
}
# 配置虛擬路由第二個實例
vrrp_instance VI_2 {
    # 第二個實例中,是從節點
    state BACKUP
    interface enp0s3
    virtual_router_id 52
    priority 95
    advert_int 1
    authentication {
        auth_type PASS
        auth_pass 2222
    }
    virtual_ipaddress {
        192.168.23.101/24 dev enp0s3 label enp0s3:1
    }
    # 下面三行的意義是當VIP發生漂移的時候調用,例如notify_master表示:當VIP漂移到master節點,調用後面的腳本
    notify_master "/root/notify.sh master"
    notify_backup "/root/notify.sh backup"
    notify_fault "/root/notify.sh fault"
    track_script {
        check_haproxy_available
    }
}
  • 3:配置haproxy2節點的keepalived主配置文件 /etc/keepalived/keepalived.conf (與haproxy1節點不一樣的地方已經做出了修改提示)
! Configuration File for keepalived

global_defs {
   notification_email {
    307443272@qq.com
   }
   notification_email_from yinhuanyi_cn@163.com
   smtp_server smtp.163.com
   smtp_connect_timeout 30
   router_id haproxy2 # 需要修改
   vrrp_mcast_group4 224.0.100.18
}

vrrp_script check_haproxy_available {
    script "killall -0 haproxy"
    interval 2
    weight -20
}

vrrp_instance VI_1 {
    state BACKUP  # 需要修改
    interface enp0s3
    virtual_router_id 51 
    priority 95 # 需要修改
    advert_int 1
    authentication {
        auth_type PASS
        auth_pass 1111 
    }
    virtual_ipaddress {
        192.168.23.100/24 dev enp0s3 label enp0s3:0
    }
    notify_master "/root/notify.sh master"
    notify_backup "/root/notify.sh backup"
    notify_fault "/root/notify.sh fault"
    track_script {
        check_haproxy_available
    }
}
vrrp_instance VI_2 {
    state MASTER  # 需要修改
    interface enp0s3
    virtual_router_id 52
    priority 100 # 需要修改
    advert_int 1
    authentication {  
        auth_type PASS
        auth_pass 2222
    }
    virtual_ipaddress { 
        192.168.23.101/24 dev enp0s3 label enp0s3:1
    }
    notify_master "/root/notify.sh master"
    notify_backup "/root/notify.sh backup"
    notify_fault "/root/notify.sh fault"
    track_script {
        check_haproxy_available
    }
}
  • 4:當VIP在haproxy1和haproxy2節點漂移的時候,調用的腳本如下
#!/bin/bash 
# 
contact='[email protected]' 
notify() { 
mailsubject="$(hostname) to be $1 and vip is floating " 
mailbody="$(date +'%F %T'),$(hostname) change to be $1" 
echo "$mailbody" | mail -s "$mailsubject" $contact 
} 
case $1 in 
master) 
# 發送報警郵件
notify master
# 如果成爲主節點,需要啓動haproxy
systemctl start haproxy.service
echo "send mail to $contact " 
;; 
backup) 
# 發送報警郵件
notify backup 
# 如果成爲備節點,先強制重啓一下haproxy
systemctl restart haproxy.service
echo "send mail to $contact"
;; 
fault) 
notify fault 
;; 
*) 
echo "usage: $(basename $0) {master|backup|fault}" 
;; 
esac
  • 5:既然是郵件報警提示,那麼需要配置/etc/mail.rc文件
# 注意smtp-auth-password的值不是登入郵件服務器的密碼,而是代理使用第三方郵件客戶端發送郵件的授權碼哦
set from=yinhuanyi_cn@163.com smtp=smtp.163.com
set smtp-auth-user=yinhuanyi_cn@163.com smtp-auth-password=xxxxxxxx
set smtp-auth=login
  • 6:現在就可以啓動haproxy1和haproxy2的keepalived服務了
systemctl start keepalived.service

二:配置Haproxy反代服務,實現動靜分離

  • 1:配置haproxy1的主配置文件/etc/haproxy/haproxy.cfg ,haproxy2的配置文件與haproxy1的一樣
# 全局配置段
global
    # 指定日誌記錄路徑,這個local2和local3是需要在/etc/rsyslog.conf文件中指定的,指定了日誌存儲路徑之後,需要重啓rsyslog服務哦
    log         127.0.0.1 local2
    log         127.0.0.1 local3
    chroot      /var/lib/haproxy
    pidfile     /var/run/haproxy.pid
    maxconn     4000
    user        haproxy
    group       haproxy
    daemon
    # 設置後臺運行4個haproxy進程會報出警告,所以註釋
    # nbproc 4

    # turn on stats unix socket
    stats socket /var/lib/haproxy/stats

# 這裏是默認的選項,如何在listen段,backend段,frontend段中將這些選項按需求重新制定
defaults
    # 指定默認的模式mode,
    mode                    http
    # 調用全局的日誌區
    log                     global
    option                  httplog
    option                  dontlognull
    option http-server-close
    # 在後端的web服務中可以記錄客戶端的源IP地址
    option forwardfor       except 127.0.0.0/8
    # 雖然使用cookie機制,但是當調度到後端的服務器不用時,強行調離至其他的後端服務器
    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
    # 指定接受3000個併發
    maxconn                 30000

# haproxy的統計頁面配置段
listen stats 
    bind *:9001 
    mode http
    stats enable  
    # 如果不設置URI,默認是/haproxy?stats
    stats uri /stats  
    # 指定認證提示符
    stats realm HAProxy\ statistics
    # 指定用戶名和密碼
    stats auth yhy:xxxxxxxx  
    stats refresh 20
    stats admin if TRUE 
    #隱藏統計頁面上HAProxy的版本信息
    stats hide-version

# 指定後端php動態資源主機組,後端的動態資源不做緩存,直接將請求反代值後端的app servers中
backend phpservers_backend  

    # 這裏使用了cookie粘性機制,當客戶端沒有被設置cookie值的時候,通過輪詢調度到app servers主機上
    balance roundrobin

    # 指定我們需要插入的cookie的key爲PHP,使用的是insert方法,indirect表示如何會話已經有cookie值了,將不會再次發送cookie到客戶端,nocache表示如果客戶端和haproxy之間有代理,那麼指定nocache將不會將所有的請求都發往一臺服務器,會清除緩存
    cookie PHP insert indirect nocache

    # server後面的cookie參數是給當前server指定cookie值,使得同一個用戶的請求始終發往同一臺服務器
    server phpserver1 192.168.23.23:8000 check weight 1 cookie phpserver1 maxconn 300
    server phpserver2 192.168.23.24:8000 check weight 2 cookie phpserver2 maxconn 600

# 指定後端varnish靜態資源緩存主機組
backend varnish_backend

    # 對用戶請求的URL做哈希計算,使得同一URL的請求始終發往同一臺服務器,基於URL做哈希計算,使得varnish緩存的命中率提高,uri算法適用於後端爲緩存服務器的場景
    balance uri

    # 使用的的hash類型是動態hash,即一致性哈希算法
    hash-type consistent

    # 使用http協議做健康狀態檢查,默認是tcp協議
    option httpchk  
    server varnish_server1 192.168.23.17:7000 check maxconn 10000
    server varnish_server2 192.168.23.18:7000 check maxconn 10000

# 指定當請求到達的時候,如果是.php結尾的請求,直接發給後端的php主機組,默認是發送給後端web靜態資源主機組
frontend myservers_frontend   
    bind *:80
    # 設置一個訪問控制規則,只要請求路徑爲靜態資源的都會被匹配到,並且發往varnish主機組
    acl varnish_page       path_beg       -i /static /images /javascript /stylesheets
    acl varnish_page       path_end       -i .jpg .gif .png .jpeg .css .js .html .txt .htm .ico
    use_backend varnish_backend if varnish_page
    # 沒有被匹配到的請求全部發往phpservers_backend服務器
    default_backend phpservers_backend
  • 2:檢查haproxy配置文件的語法
[root@haproxy2 ~] haproxy -c -f /etc/haproxy/haproxy.cfg
Configuration file is valid
  • 3:通過haproxy的數據統計頁面來監控後端節點的狀態信息
http://192.168.23.100:9001/stats

三:配置Varnish,爲反覆請求的靜態資源提供內存緩存(yum 安裝varnish)

  • 1:配置varnish1的對於varnish進程參數的配置文件/etc/varnish/varnish.params

# 指定重新reload varnish的時候,重新reload一下VCL配置文件
RELOAD_VCL=1

# 指定VCL的配置文件
VARNISH_VCL_CONF=/etc/varnish/default.vcl

# 指定varnish作爲反代時候監聽的地址和端口
# 在企業級情況下,varnish通常是面向的Nginx或haproxy這樣的反代負載均衡器,可以實現端口映射的功能,不一定是80端口
VARNISH_LISTEN_PORT=7000

# 指定varnishadm的shell登入接口
VARNISH_ADMIN_LISTEN_ADDRESS=127.0.0.1
VARNISH_ADMIN_LISTEN_PORT=6082

# 指定shell接口使用的密鑰文件
VARNISH_SECRET_FILE=/etc/varnish/secret


# 指定varnish存儲的類型,以及大小,這裏使用默認的內存緩存,大小爲256M即可
VARNISH_STORAGE="malloc,256M"

# 指定varnish進程的屬主和屬組
VARNISH_USER=varnish
VARNISH_GROUP=varnish

# 指定運行時的參數,使用-p選項來指定
DAEMON_OPTS="-p thread_pools=6 -p thread_pool_min=5 -p thread_pool_max=500 -p thread_pool_timeout=300"
  • 2:配置varnish1的vcl規則:/etc/varnish/default.vcl
vcl 4.0;

# 導入調度器模塊
import directors;

# 指定調度到後端的主機
backend web1 {
    .host = "192.168.23.21";
    .port = "8000";
    .probe = {
        # 指定做健康狀態檢查的URL,既然給了這個URL,一定需要讓後端主機的站點目錄裏面有這個URL,如果沒有varnish將不會將請求調度到這臺主機上
    .url = "/health.html";
        # 指定檢查的超時時長
    .timeout = 2s;
    # 檢查每次檢查的時間間隔
    .interval = 4s;
        # 指定一個檢測多少次
    .window = 5;
    # 指定最少成功多少次認爲後端主機有效
    .threshold = 3;
    } 
}

backend web2 {
    .host = "192.168.23.22";
    .port = "8000";
    .probe = {
        # 指定做健康狀態檢查的URL
    .url = "/health.html";
        # 指定檢查的超時時長
    .timeout = 2s;
    # 檢查每次檢查的時間間隔
    .interval = 4s;
        # 指定一個檢測多少次
    .window = 5;
    # 指定最少成功多少次認爲後端主機有效
    .threshold = 3;
    } 
}


# 定義負載均衡調度器
sub vcl_init {
    # 創建一個調度器對象,directors.round_robin()指定了輪詢調度算法
    new static = directors.round_robin();
    static.add_backend(web1);
    static.add_backend(web2);
}

# 第一個子歷程,當收到請求處理的子歷程
sub vcl_recv {

    # 指定varnish接受到的請求全部發往後端的static主機組
    set req.backend_hint = static.backend();


    # 如何請求方法是pri,直接返回synth子歷程
    if (req.method == "PRI") {
        /* We do not support SPDY or HTTP/2.0 */
        return (synth(405));
    }


    # 如果不是一下七中方法的任意一個,直接返回pipe子歷程
    if (req.method != "GET" &&
      req.method != "HEAD" &&
      req.method != "PUT" &&
      req.method != "POST" &&
      req.method != "TRACE" &&
      req.method != "OPTIONS" &&
      req.method != "DELETE") {
        /* Non-RFC2616 or CONNECT which is weird. */
        return (pipe);
    }


    # 如果不是get或者head方法,我們就不用去查緩存,直接交由後端主機處理就是
    if (req.method != "GET" && req.method != "HEAD") {
        /* We only deal with GET and HEAD by default */
        return (pass);
    }


    # 如果客戶端的請求報文中的http首部包含認證信息或cookie信息,也直接交由後端主機處理,這是保密的靜態內容
    # 由於在haproxy對於動態請求都會在用戶的瀏覽器中設置cookie信息,因此,下面這項先將其註釋掉,以免請求都不能查詢緩存
    #if (req.http.Authorization || req.http.Cookie) {
    #    /* Not cacheable by default */
    #   return (pass);
    #}


    # 如何請求的方法是PURGE,那麼直接發往purge子歷程處理,但是我這裏使用curl命令請求返回501錯誤,不知道爲什麼
    if (req.method == "PURGE") {
        #if (!client.ip ~ purgers) {
        #    return(synth(405));
        #}
        return (purge);
    }



    # 否則其他的請求都通過hash子歷程處理
    return (hash);
}

# 指定purge的子歷程,視乎不起作用,錯誤提示無法處理,因此註釋
#sub vcl_purge {

#    return (synth(200,"Purged"));
#}

# 指定後端主機響應的響應報文子歷程
sub vcl_backend_response {

    # 如何發往後端主機的請求報文的http首部中沒有s-maxage參數,那麼做兩個if判斷
    # 1:如果請求的是css樣式代碼,設置其ttl值爲7200s,並且刪除Set-Cookie參數
    # 2:如果請求的是jpg圖片,設置其ttl值爲7200s,並且刪除Set-Cookie參數
    # 其他的請求都交由deliver子歷程處理
    if (beresp.http.cache-control !~ "s-maxage"){ 
        if (bereq.url ~ "(?i)\.css$") {

            set beresp.ttl = 7200s;
            unset beresp.http.Set-Cookie;
        }
        if (bereq.url ~ "(?i)\.jpg$") {
                set beresp.ttl = 7200s;
                unset beresp.http.Set-Cookie;
        }
    }
    return (deliver);
}

# 這一條子歷程是最後一個子歷程,通過此子歷程的請求報文執行協議給用戶
# 在deliver子歷程中可以修改響應報文http的首部
sub vcl_deliver {

    # 如果客戶端的請求被緩存命中,那麼加一個http的首部參數,明確告訴用戶請求的資源是從緩存加載的
    if (obj.hits>0)
    {

    set resp.http.X-Cache = "HIT via " + server.hostname;

    }else{

    set resp.http.X-Cache = "MISS via " + server.hostname;

    }

}
  • 3:varnish1節點和varnish2節點的配置文件都一樣,因此,直接scp一份到varnish2即可
  • 4:啓動varnish
systemctl start varnish.service

四:配置NFS服務器提供共享存儲(yum 安裝 nfs-utils)

  • 1:在NFS節點上爲靜態服務器和動態服務器提供共享存儲目錄
[root@nfs1 ~]# mkdir -pv /data/{static,dynamic}

# 在靜態共享目錄中提供WordPress源碼的靜態資源代碼,直接刪除.php結尾的文件剩下的都是靜態文件了
[root@nfs1 ~]# cd /data/static/
[root@nfs1 static]# find ./ -type f -name "*.php" | xargs rm -f 

# 在靜態共享目錄中提供WordPress源碼的靜態資源代碼,直接刪除.css .jpg .html等結尾的文件剩下的都是動態文件
[root@nfs1 static]# cd /data/dynamic/
[root@nfs1 dynamic]# find ./ -type f -name "*.css" | xargs rm -f 
  • 2:配置/etc/exports文件,將剛剛創建的共享目錄共享出去,同時拷貝一份到NFS2節點
/data                   192.168.23.0/24(rw,no_root_squash)
  • 3:在NFS2節點查看共享目錄
[root@nfs2 ~]# showmount -e 192.168.23.25
Export list for 192.168.23.25:
/data 192.168.23.0/24
  • 4:由於在static servers ,nfs , app servers 節點上都存在apache用戶和apache組,並且UID和GID都一樣,因此,直接設置apache用戶對共享目錄的訪問權限即可。但是如果NFS服務器沒有apache用戶,或uid和gid和其他節點不一樣,需要添加apache用戶。另外,如果是LNMP架構,最好是將Nginx ,php-fpm,NFS統一創建一個用戶,例如 www用戶,這樣也可以實現批量管理操作
[root@nfs1 data]# setfacl -m u:apache:rwx /data/dynamic
[root@nfs1 data]# setfacl -m u:apache:rwx /data/static
  • 5:在static servers,app servers將共享目錄掛載
[root@web1 ~]# mount -t nfs 192.168.23.25:/data/static /var/www/html/
[root@web2 ~]#  mount -t nfs 192.168.23.25:/data/static /var/www/html/ 
[root@php1 ~]# mount -t nfs 192.168.23.25:/data/dynamic /var/www/html/
[root@php2 ~]# mount -t nfs 192.168.23.25:/data/dynamic /var/www/html/

五:配置Mariadb服務器

  • 登入mariadb,創建一個wp數據庫,然後再給這個數據庫創建授權一個wp_user的用戶即可。並且修改源碼中wp-config.php文件,填寫好數據庫的相關參數。
  • 到這裏整套架構基本上就完成了90%,現在可以訪問http://192.168.23.100創建博客站點了

六:配置Memcached服務器,實現會話保持

  • 1:動態服務器的cookie信息是保持在本地的文件系統上的,雖然haproxy在調度時候,已經做了基於cookie的粘性綁定,但是如果動態服務器掛一臺,那麼基於這臺動態服務器的會話保持都將失效,因此有必要在動態服務器組後端配置一臺會話保持的服務器,實現session server
  • 2:安裝memcached服務和php與memcached連接的驅動
yum install -y memcached
yum install -y php-pecl-memcache
  • 3:在動態服務器上編輯php.ini文件
編輯php.ini文件,確保如下兩個參數的值分別如下所示:
session.save_handler = memcache
session.save_path = "tcp://192.168.23.28:11211?persistent=1&weight=1&timeout=1&retry_interval=15"
  • 4:只要php程序調用php連接memcached的接口,就能實現session server。這裏介紹的較爲簡單,之後我們將使用redis取代memcached,實現會話保持功能

七:配置 Keepalived + Rsync + Inotify 服務解決NFS單點故障的問題 (yum 安裝 keepalived 、inotify-tools)

  • 1:從架構圖中我們可以知道,NFS2作爲NFS1容災備用需要做到NFS1和NFS2的共享目錄數據同步。並且,當一臺NFS掛了,另一臺會馬上搶奪VIP,替代掛掉的主機,那麼又要使用keepalived來實現了
  • 2:首先將靜態資源和動態資源的共享目錄卸載掉,因爲,接下來我們將NFS1,NFS2通過keepalived實現高可用,如同架構圖所示,通過VIP對外提供服務
  • 3:在NFS1的共享目錄/data的所有文件拷貝一份到NFS2,並且爲了保證目錄權限有效,重新設置下/data/目錄的訪問權限
[root@nfs2 ~]# mkdir -pv /data
[root@nfs1 data]# scp -rpv ./* 192.168.23.26:/data
[root@nfs2 data]# setfacl -m u:apache:rwx /data/dynamic
[root@nfs2 data]# setfacl -m u:apache:rwx /data/static
  • 4:在NFS1和NFS2 yum安裝keepalived,NFS1爲主節點,NFS2爲備節點, 主備節點配置文件分別如下,這裏需要說明的是,在配置文件中沒有添加腳本報警功能
! Configuration File for keepalived

global_defs {
   notification_email {
    307443272@qq.com
   }
   notification_email_from yinhuanyi_cn@163.com
   smtp_server smtp.163.com
   smtp_connect_timeout 30
   router_id NFS1
   vrrp_mcast_group4 224.0.101.18
}

# 定義對NFS服務做健康狀態檢查的腳本
vrrp_script check_nfs_available {
    script "killall -0 rpcbind && killall -0 rpc.statd && killall -0 rpc.mountd"
    interval 2
    weight -20
}


vrrp_instance VI_1 {
    state MASTER
    interface enp0s3
    virtual_router_id 51
    priority 100
    advert_int 1
    authentication {
        auth_type PASS
        auth_pass 3333
    }
    virtual_ipaddress {
    192.168.23.51/24 dev enp0s3 label enp0s3:0
    }
    track_script {
        check_nfs_available
    }
}
! Configuration File for keepalived

global_defs {
   notification_email {
    307443272@qq.com
   }
   notification_email_from yinhuanyi_cn@163.com
   smtp_server smtp.163.com
   smtp_connect_timeout 30
   router_id NFS2
   vrrp_mcast_group4 224.0.101.18
}

# 定義對NFS服務做健康狀態檢查的腳本
vrrp_script check_nfs_available {
    script "killall -0 rpcbind && killall -0 rpc.statd && killall -0 rpc.mountd"
    interval 2
    weight -20
}


vrrp_instance VI_1 {
    state BACKUP
    interface enp0s3
    virtual_router_id 51
    priority 95
    advert_int 1
    authentication {
        auth_type PASS
        auth_pass 3333
    }
    virtual_ipaddress {
    192.168.23.51/24 dev enp0s3 label enp0s3:0
    }
    track_script {
        check_nfs_available
    }
}
  • 5:讓內核重讀一下,nfs的配置文件 , 並且查看共享目錄
exportfs -r
[root@nfs2 keepalived]# showmount -e 192.168.23.51
Export list for 192.168.23.51:
/data 192.168.23.0/24
  • 6:重新將共享目錄掛載到靜態服務器和動態服務器
[root@web1 ~]# mount -t nfs 192.168.23.51:/data/static /var/www/html/
[root@web2 ~]# mount -t nfs 192.168.23.51:/data/static /var/www/html/
[root@php1 ~]# mount -t nfs 192.168.23.51:/data/dynamic /var/www/html/
[root@php2 ~]# mount -t nfs 192.168.23.51:/data/dynamic /var/www/html/
  • 7:在NFS2配置rsync服務,修改/etc/rsyncd.conf配置文件
# /etc/rsyncd: configuration file for rsync daemon mode

# See rsyncd.conf man page for more options.

# configuration example:
 # 指定訪問本地共享目錄的屬主和屬組,當客戶端連接到服務端,那麼進程就以這裏指定的uid和gid運行
 uid = rsync
 gid = rsync
 # 不禁錮
 use chroot = no
 # 指定服務端最大併發連接數量
 max connections = 2000
 # 指定超時時長
 timeout = 900
 # 指定程序的pid路徑
 pid file = /var/run/rsyncd.pid
 # 指定日誌路徑
 log file = /var/log/rsyncd.log
 # 指定文件系統鎖路徑
 lock file = /var/run/rsyncd.lock
 # 指定推送時出現錯誤忽略
 ignore errors
 # 指定客戶端可以向服務端推送數據,因此必須是可讀寫
 read only = false
 # 關閉遠程列表
 list = false
 # 指定允許連接rsync服務端的網絡地址
 hosts allow = 192.168.23.0/24
 hosts deny = 0.0.0.0/32
 # 啓用虛擬用戶
 auth users = nfs
 # 指定用戶名和密碼的文件,這個文件裏面的用戶名就是auth users指定的用戶名,然後給個密碼就好
 secrets file = /etc/rsync.password
 #transfer logging = yes
 #ignore nonreadable = yes
 #dont compress   = *.gz *.tgz *.zip *.z *.Z *.rpm *.deb *.bz2

 # 指定一個模塊,用來指定接受客戶端推送的目錄
 [data]
        path = /data
        comment = shared remoted NFS directory /data
  • 8:設置備份目錄的訪問權限,創建用戶,密碼
useradd rsync -s /sbin/nologin -M # 在NFS2節點創建一個rsync用戶,不能登入,不創建家目錄
chmod -R rsync /data #  修改/data目錄的屬主爲rsync,這樣rsyncd進程就能夠向目錄裏面寫數據
echo "nfs:xxxxxx" > /etc/rsync.password # 由於在/etc/rsyncd.conf主配置文件中指定了客戶端登入的用戶名以及密鑰文件路徑,那麼根據路徑創建用戶密碼即可
chmod 600 /etc/rsync.password # 修改密碼文件的權限
  • 9:配置rsync服務配置進程文件/etc/sysconfig/rsyncd
OPTIONS="--address=192.168.23.26" # 將rsync服務監聽到固定的IP地址上
  • 10:在NFS1節點安裝inotify-tools監聽工具,實現調用rsync自動遠程同步
# 1:安裝inotify-tools監控工具
yum install -y inotify-tools

# 2:創建同步時候使用的密鑰文件
echo "自己在rsync服務端設置的密碼" > /etc/rsync.password
  • 11:寫一個腳本監控/data目錄的變化,使用inotifywait監控,同時調用rsync自動遠程同步,腳本名稱就交inotify.sh,通過bash inotify.sh & ,使得腳本在後臺運行,並且加入到/etc/rc.local文件中,開機自動運行腳本文件
#!/bin/bash
inotify=/usr/bin/inotifywait
$inotify -mrq --timefmt '%d/%m/%y %H:%M' --format '%T %w%f' -e modify,delete,create,attrib,close_write /data \
| while read file; do
        /usr/bin/rsync -avz --delete /data/ nfs@192.168.23.26::backup --password-file=/etc/rsync.password
done

八:總結架構中存在的不足

  • 1:雖然給NFS共享存儲做了高可用,但是當NFS1掛掉,會出現服務無法訪問的問題,那麼就需要手動卸載,然後再次掛載(此時的NFS服務的VIP已經漂移)
# 手動停止NFS1的nfs服務,節點漂移,但是不會卸載之前的掛載點,再重新掛載,出現的錯誤如下
[root@web1 www]# ll
ls: 無法訪問html: 權限不夠
總用量 0
drwxr-xr-x 2 root root 6 1115 02:05 cgi-bin
?????????? ? ?    ?    ?            ? html

# 需要手動卸載
[root@web1 www]# umount 192.168.23.51:/data/static
[root@web1 www]# ll
總用量 0
drwxr-xr-x 2 root root  6 1115 02:05 cgi-bin
drwxr-xr-x 5 root root 74 414 05:11 html

# 再次掛載NFS
mount -t nfs 192.168.23.51:/data/static /var/www/html/
mount -t nfs 192.168.23.51:/data/dynamic /var/www/html/
  • 2:架構中沒有將MySQL數據庫的目錄通過NFS服務進行提供,是因爲考慮到MySQL是單點,並沒有配置MySQL的主從
  • 3:前端的負載均衡調度器使用的是Haproxy將用戶的請求進行動靜分離,但是Haproxy沒有緩存功能。因此,如果前端使用的是Nginx做負載均衡調度器,Nginx有透牀式緩存功能,可以對前端的用戶請求多一層緩存功能。
  • 4:對於整個架構,並沒有假設zabbix監控系統,無法對架構中的各個節點的監控狀態進行監控
  • 5:架構中沒有假設自動化運維工具ansible,運維無法實現對集羣中各個節點的服務進行有效的管理
  • 6:架構沒有實現從裸機(或無系統虛擬節點)開始完成系統的統一安裝與系統調優工作
  • 7:架構中沒有日誌分析系統

九:架構展望和升級(對於架構中存在的不足提供解決方案)

  • 1:集羣使用corosync + pacemaker解決集羣服務自動管理,這樣當NFS掛掉之後,可以實現自動卸載掛載點,自動掛載,也可以實現服務出現故障時,自動重啓的功能
  • 2:將MySQL數據庫實現主從模式,解決單點問題,並且在MySQL集羣前加入緩存,解決MySQL併發I/O慢的問題
  • 3:前端的負載均衡器改用Nginx
  • 4:在架構中添加zabbix監控系統
  • 5:加入ansible自動化運維工具,對整個架構的服務全面的掌控
  • 6:藉助Cobbler + kickstarts文件實現各個節點從系統安裝到服務正常運行的一鍵式完成
  • 7:通過添加ELK日誌分析系統,實現各個節點的日誌彙總管理與分析
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章