利用 glusterfs 達成目錄即時自動同步與高可用性

http://cyrilwang.blogspot.tw/2013/09/glusterfs.html

去年我介紹過利用 lsyncd 這個套件來達成目錄的同步備援,今天則要利用 glusterfs 來達成類似的效果。雖說類似,但是 lsyncd 與 glusterfs 相比有下列差別:

  • lsyncd 監測目錄的變動,並定期 (或達到一定的異動次數) 將異動同步到另外一個目錄。因為 lsyncd 採用 inotify 監測技術,所以如果目錄內的檔案或子目錄一多,就可能會產生無法監測的問題。
  • lsyncd 本身並沒有支援高可用性,必須利用其它機制 (如 heartbeat) 來達成高可用性。
  • 被同步的目錄通常僅能當做備援,無法作為負載平衡之用。不但在資源使用上較為浪費,擴充性也比較差。

嚴格來說,拿 lsyncd 與 glusterfs 相比並不是一件公平且合理的事情,因為 glusterfs 本身是一個完整的分散式檔案系統,所以在功能上本就遠比 lsyncd 這類工具來的強大許多。用最簡單的說法,glusterfs 可以將許多不同的儲存空間整合在一起,變成一個分散式的虛擬儲存空間。glusterfs 所管理的虛擬儲存空間除了可以具備分散的特性 (distributed, 也就是將不同的檔案存放在不同的儲存空間) 之外,glusterfs 還提供了複製 (replicated, 也就是同一個檔案存放在兩個以上的儲存空間) 以及分條 (stripped, 也就是將一個檔案打散在多個不同的儲存空間) 的選項。這些選項可以單獨使用,也可以一起套用。今天我要跟大家分享的就是透過複製特性來達成目錄的自動同步與高可用性。
範例需要三台 Linux 系統,其中兩台作為 glusterfs 的服務端,另外一台則作為 glusterfs 的用戶端,所使用的環境皆為 CentOS 6.4。相關架構如下:

為了方便起見,我們讓這三台 Linux 之間可以透過主機名稱進行連結,所以我們在 /etc/hosts 設定如下:

192.168.199.100 server1.cyril.idv server1
192.168.199.101 server2.cyril.idv server2
192.168.199.102 client.cyril.idv client

接下來就讓我們一起一步步完成今天的範例吧。

第一階段:glusterfs 服務端的基本安裝
此階段的步驟必須在 server1 與 server2 上皆予以執行。

  1. 安裝 glusterfs 的 repo 
    指令為

    wget http://download.gluster.org/pub/gluster/glusterfs/3.3/LATEST/EPEL.repo/glusterfs-epel.repo -O /etc/yum.repos.d/glusterfs-epel.repo

    註1:雖然目前 glusterfs 的最新版本為 3.4,但是 GA 版本仍為 3.3,所以在這個範例中我選擇使用 3.3 的 repo。 
    如果系統已經安裝 EPEL 的 repo,裡面就包含了 glusterfs 3.2 的相關 RPM 套件。但仍建議停用 EPEL 內的 glusterfs 套件,而改採用上述的套件。

  2. 安裝 glusterfs 的服務器套件 
    指令為

    yum install glusterfs-server -y
  3. 設定 glusterfs 服務開機後自動啟動 
    指令為

    chkconfig glusterd on
  4. 啟動 glusterfs 服務 
    指令為

    service glusterd start
  5. 修改防火牆設定 
    在 glusterfs 官方文件中提到應該開啟 TCP 111, 24007, 24008, 24009 以及之後的數個埠號,至於要開到幾個埠號,則跟 brick 數量有關。以這個例子而言,應該開啟 TCP 111, 24007, 24008, 24009, 24010, 24011 等埠號。 
    修改完後記得確認防火牆規則是否已經生效。指令為

    iptables –L -n

    執行後應可以看到類似下列資訊

    Chain INPUT (policy ACCEPT)
    target     prot opt source               destination
    ACCEPT     all  --  0.0.0.0/0            0.0.0.0/0           state RELATED,ESTABLISHED
    ACCEPT     icmp --  0.0.0.0/0            0.0.0.0/0      
    ACCEPT     all  --  0.0.0.0/0            0.0.0.0/0
    ACCEPT     tcp  --  0.0.0.0/0            0.0.0.0/0           state NEW tcp dpt:22
    ACCEPT     tcp  --  0.0.0.0/0            0.0.0.0/0           state NEW tcp dpt:111
    ACCEPT     tcp  --  0.0.0.0/0            0.0.0.0/0           state NEW tcp dpt:24007
    ACCEPT     tcp  --  0.0.0.0/0            0.0.0.0/0           state NEW tcp dpt:24008
    ACCEPT     tcp  --  0.0.0.0/0            0.0.0.0/0           state NEW tcp dpt:24009
    ACCEPT     tcp  --  0.0.0.0/0            0.0.0.0/0           state NEW tcp dpt:24010
    ACCEPT     tcp  --  0.0.0.0/0            0.0.0.0/0           state NEW tcp dpt:24011
    REJECT     all  --  0.0.0.0/0            0.0.0.0/0           reject-with icmp-host-prohibited
    Chain FORWARD (policy ACCEPT)
    target     prot opt ource               destination
    REJECT     all  --  0.0.0.0/0            0.0.0.0/0           reject-with icmp-host-prohibited
    Chain OUTPUT (policy ACCEPT)     
    target     prot opt source               destination

第二階段:glusterfs 服務端的服務設定
此階段的指令僅需在 server1 予以執行即可。

  1. 將 server2 加入可信任的儲存池 (Trusted Stroage Pool) 
    指令為

    [root@server1 ~]gluster peer probe server2.cyril.idv

    執行後應可看到下列訊息

    Probe successful
  2. 確認信任關係 
    指令為

    [root@server1 ~]gluster peer status

    執行後應可看到類似下面的訊息

    Number of Peers: 1
    
    Hostname: server2.cyril.idv
    Uuid: f44e01c6-e889-432a-8056-cf7174421324
    State: Peer in Cluster (Connected)
  3. 建立 Volume 
    在 glusterfs 的架構中,每一個 volume 就代表了單獨的虛擬檔案系統。建立 volume 的指令為

    [root@server1 ~]gluster volume create datavol replica 2 transport tcp server1.cyril.idv:/data server2.cyril.idv:/data

    執行後應可看到下列訊息

    Creation of volume datavol has been successful. Please start the volume to access data.

    註2:glusterfs 會自動建立不存在的 /data 目錄。此外,在建立 volume 時,我們不需要特別指定虛擬檔案系統的屬性 (像是分散與否),glusterfs 會自動根據相關參數 (如 brick 數) 決定此一虛擬檔案系統的屬性。

  4. 啟動 Volume 
    指令為

    [root@server1 ~]gluster volume start datavol

    執行後應可看到下列訊息

    Starting volume datavol has been successful
  5. 確認服務之間的連線已經正常連結 
    指令為

    [root@server1 ~]netstat –tap | grep glusterfsd

    執行後應可看到類似下列的訊息

    tcp        0      0 *:24009                     *:*                         LISTEN      2343/glusterfsd
    tcp        0      0 server1.cyril.idv:24009     server2.cyril.idv:exp2      ESTABLISHED 2343/glusterfsd
    tcp        0      0 server1.cyril.idv:24009     server1.cyril.idv:1020      ESTABLISHED 2343/glusterfsd
    tcp        0      0 server1.cyril.idv:24009     server2.cyril.idv:1020      ESTABLISHED 2343/glusterfsd
    tcp        0      0 server1.cyril.idv:24009     server1.cyril.idv:1023      ESTABLISHED 2343/glusterfsd
    tcp        0      0 localhost:1020              localhost:24007             ESTABLISHED 2343/glusterfsd
  6. 查詢 volume 的狀態 
    指令為

    [root@server1 ~]gluster volume info datavol

    執行後應可看到類似下列訊息

    
    Volume Name: datavol
    Type: Replicate
    Volume ID: 185ef7c6-7c7f-461d-8690-eec24a1a4c38
    Status: Started
    Number of Bricks: 1 x 2 = 2
    Transport-type: tcp
    Bricks:
    Brick1: server1.cyril.idv:/data
    Brick2: server2.cyril.idv:/data

    其中 Type 資訊表示這是一個複製的 (Replicate) 虛擬檔案系統。

  7. 為了增加安全性,我們可以限制只有 client 電腦的 IP 才能連上此一虛擬檔案系統 
    指令為

    [root@server1 ~]gluster volume set datavol auth.allow 192.168.199.102

    執行後應可看到下列訊息

    Set volume successful
  8. 再次確認 volume 的狀態 
    指令同樣為

    [root@server1 ~]gluster volume info datavol

    執行後應可看到類似下列訊息

    
    Volume Name: datavol
    Type: Replicate
    Volume ID: 185ef7c6-7c7f-461d-8690-eec24a1a4c38
    Status: Started
    Number of Bricks: 1 x 2 = 2
    Transport-type: tcp
    Bricks:
    Brick1: server1.cyril.idv:/data
    Brick2: server2.cyril.idv:/data
    Options Reconfigured:
    auth.allow: 192.168.199.102

第三階段:glusterfs 用戶端的安裝

  1. 安裝 glusterfs 的 repo 
    指令為

    [root@client ~]wget http://download.gluster.org/pub/gluster/glusterfs/3.3/LATEST/EPEL.repo/glusterfs-epel.repo -O /etc/yum.repos.d/glusterfs-epel.repo
  2. 安裝 glusterfs 用戶端的套件 
    指令為

    [root@client ~]yum install glusterfs-client -y
  3. 建立掛載點 
    指令為

    [root@client ~]mkdir /mnt/glusterfs/data –p
  4. 掛載虛擬檔案系統 
    指令為

    [root@client ~]mount.glusterfs server1.cyril.idv:/datavol /mnt/glusterfs/data
  5. 確認掛載的結果 
    指令為

    [root@client ~]mount –t fuse.glusterfs

    執行後應可看到類似下列訊息

    server1.cyril.idv:/datavol on /mnt/glusterfs/data type fuse.glusterfs (rw,default_permissions,allow_other,max_read=131072)
  6. 設定開機自動掛載 
    修改 /etc/fstab,加上下列設定

    server1.cyril.idv:/datavol /mnt/glusterfs/data glusterfs defaults 0 0
  7. 重新開機 
    指令為

    [root@client ~]sync; shutdown –r now
  8. 確認開機自動掛載是否成功
    指令同樣為

    [root@client ~]mount –t fuse.gluserfs

    執行後應可看到類似下列訊息

    server1.cyril.idv:/datavol on /mnt/glusterfs/data type fuse.glusterfs (rw,default_permissions,allow_other,max_read=131072)
  9. 測試檔案的操作 
    指令為

    [root@client ~]echo "Hello GlusterFS" >> /mnt/glusterfs/data/test0
  10. 確認檔案的同步複製 
    我們可以同時在 server1 與  server2 的 /data 下看到 test0 這個檔案,而且內容皆為 "Hello GlusterFS"。

至此,我們已經完成利用 glusterfs 建立目錄即時同步的架構。接下來我們將透過更多的例子,看看此一架構可以提供何種程度的高可用性。 
註3:如果我們直接在 server1 或 server2 上針對檔案系統 (也就是 /data) 進行異動的操作 (如新增檔案),將無法對達到同步的效果,甚至連用戶端也無法接受到這些異動。

第四階段:高可用性測試

  1. 關閉 server1 
    指令為

    [root@server1 ~]sync;shutdown –h now
  2. 修改檔案內容 
    指令為

    [root@client ~]echo "Hello GlusterFS Replication" >> /mnt/glusterfs/data/test0

    雖然 server1 已經關機,但是我們依舊可以對原本掛載的目錄進行讀寫,其讀寫的目的地會自動變成 server2。

  3. 確認 server2 上檔案 test0 的內容 
    指令為

    [root@server2 ~]# cat /data/test0

    執行後應可看到下列訊息

    Hello GlusterFS
    Hello GlusterFS Replication
  4. 開啟 server1
  5. 確認 server1 上檔案 test0 的內容 
    指令為

    [root@server1 ~]# cat /data/test0

    執行後應可看到下列訊息

    Hello GlusterFS
    Hello GlusterFS Replication

    註4:glusterfs 具備自動修復 (heal) 的功能,如果目錄下的資料較多,自動修復所需的時間也會跟著增長。在自動修復期間雖然服務端的檔案可能會有不一致的現象發生,但是 glusterfs 會確保用戶端只會看到最新的檔案。

  6. 再次關閉 server1 
    指令同樣為

    [root@server1 ~]sync;shutdown –h now
  7. 卸載用戶端上的目錄掛載 
    指令為

    [root@client ~]umount /mnt/glusterfs/data
  8. 再次掛載目錄 
    指令為

    [root@client ~]mount -a

    執行後應可看到下列訊息

    Mount failed. Please check the log file for more details.      

    註5:掛載失敗的原因在於 server1 已經關機,所以用戶端自然無法進行連結。雖然 glusterfs 在掛載後的讀寫具備自動切換的能力,但是掛載時的動作卻無法自動切換。

  9. 修改掛載的參數,使其支援備用掛載主機 
    修改 /etc/fstab,將原本

    server1.cyril.idv:/datavol /mnt/glusterfs/data glusterfs defaults 0 0

    修改為

    server1.cyril.idv:/datavol /mnt/glusterfs/data glusterfs defaults,backupvolfile-server=server2.cyril.idv 0 0
  10. 再次掛載目錄 
    指令為

    [root@client ~]mount –a
  11. 確認掛載結果 
    指令為

    [root@client ~]mount –t fuse.glusterfs      

    執行後應可看到下列訊息

    server2.cyril.idv:/datavol on /mnt/glusterfs/data type fuse.glusterfs (rw,default_permissions,allow_other,max_read=131072)

    註6:在此我們可以看到掛載主機已經從 server1 改為 server2了。透過此一參數,可以避免 glusterfs 在掛載目錄時因為單一主機失效而掛載失敗。

透過 glusterfs,我們可以輕鬆建立一個可自動同步且具備高可用性的目錄。更棒的是,如果未來我們發現這個目錄有空間不足或效能低落的情況發生,只要加上更多的 brick,就可以直接在線上進行擴充的工作,不用再擔心因為資料轉移所造成的過多時間花費與停機時間了。