1、請描述本地文件系統和分布式文件系統的特點
本地文件系統
本地文件系統主要是指Ext2,Ext3,Btrfs,XFS這類,它們通常提供以下功能:
- 擴展性:隨著系統容量的增加保持性能,不隨容量變化而導致性能震蕩。比如一個目錄下的海量文件,在EXT2/3中由于目錄設計問題會導致較大的性能問題。再比如EXT2/3中的Metadata的占用和inode的劃分可能會導致空間的浪費。
-
數據一致性
- Checksum: Checksum與對應的數據塊分開放置,避免silent corruption
- COW事務: COW事務參考文件系統特性 – COW事務
- Log: Log被一些文件系統用作WAL模式來加快寫操作,并且保證寫操作的原子性
-
多設備管理:傳統上Linux往往使用LVM進行多設備的管理,現代文件系統往往增加對多設備的支持。如ZFS和Btrfs會有存儲池模型對應LVM的邏輯卷組,文件系統會對底層的多設備進行并行的訪問。
- 快照和克隆:采用COW事務模型的文件系統通常具有這個特性
- 軟件RAID支持:現代文件系統通過對多設備的管理可以很好的支持軟件RAID,如Btrfs對Metadata進行RAID1的默認保護
- 針對SSD的優化: 除了SSD對于隨機讀這一特性的優化外,還有對SSD擦除操作的優化。另外,SSD在使用容量接近100%時會導致極差的寫入性能,文件系統也可以對SSD的分配策略和重平衡進行一定的優化。
- 壓縮和加密: 現在的IO速度遠遠跟不上CPU的發展,因此對磁盤文件進行壓縮讀寫是個很好的選擇,現代文件系統往往支持多種壓縮格式,而且可以支持整個文件系統的加密或者某個文件和目錄的加密
- 去重: 文件系統系統去重是個大話題,主要是計算塊的checksum方法或者客戶端計算文件的hash來決定是否是一個新文件。
分布式文件系統
分布式文件系統的架構和實現有非常大的差異,如NFS這種傳統的基于存儲服務器的網絡文件系統,基于SAN的GPFS,然后現在的集群式架構,比如HDFS這種有中心的分布式,如GlusterFS這種無中心分布式,再如Ceph這種部分在內核態部分在用戶態等等。
NFS
GPFS
HDFS
GlusterFS
由于架構上的差異和本身文件系統的設計目標,通常分布式文件系統可以根據接口類型分成塊存儲、對象存儲和文件存儲。如Ceph具備塊存儲(Experiment)、文件存儲和對象存儲的能力,GlusterFS支持對象存儲和文件存儲的能力。而MogileFS只能作為對象存儲并且通過key來訪問。
- 擴展能力: 毫無疑問,擴展能力是一個分布式文件系統最重要的特點。分布式文件系統中元數據管理一般是擴展的重要問題,GFS采用元數據中心化管理,然后通過Client暫存數據分布來減小元數據的訪問壓力。GlusterFS采用無中心化管理,在客戶端采用一定的算法來對數據進行定位和獲取。
- 高可用性: 在分布式文件系統中,高可用性包含兩層,一是整個文件系統的可用性,二是數據的完整和一致性。整個文件系統的可用性是分布式系統的設計問題,類似于NOSQL集群的設計,比如有中心分布式系統的Master服務器,網絡分區等等。數據完整性則通過文件的鏡像和文件自動修復等手段來解決,另外,部分文件系統如GlusterFS可以依賴底層的本地文件系統提供一定支持。
- 協議和接口: 分布式文件系統提供給應用的接口多種多樣,Http RestFul接口、NFS接口、Ftp等等POSIX標準協議,另外通常會有自己的專用接口。
- 彈性存儲: 可以根據業務需要靈活地增加或縮減數據存儲以及增刪存儲池中的資源,而不需要中斷系統運行。彈性存儲的最大挑戰是減小或增加資源時的數據震蕩問題。
- 壓縮、加密、去重、緩存和存儲配額: 這些功能的提供往往考驗一個分布式文件系統是否具有可擴展性,一個分布式文件系統如果能方便的進行功能的添加而不影響總體的性能,那么這個文件系統就是良好的設計。這點GlusterFS就做的非常好,它利用類似GNU/Hurd的堆棧式設計,可以讓額外的此類功能模塊非常方便的增加。
2、總結常用的分布式文件系統的應用場景及常規的維護方式;
常見的分布式文件系統有,GFS、HDFS、Lustre 、Ceph 、GridFS 、mogileFS、TFS、FastDFS等。各自適用于不同的領域。它們都不是系統級的分布式文件系統,而是應用級的分布式文件存儲服務。
GFS(Google File System)
Google公司為了滿足本公司需求而開發的基于Linux的專有分布式文件系統。。盡管Google公布了該系統的一些技術細節,但Google并沒有將該系統的軟件部分作為開源軟件發布。
下面分布式文件系統都是類 GFS的產品。
HDFS
Hadoop 實現了一個分布式文件系統(hadoop Distributed File System),簡稱HDFS。 Hadoop是Apache Lucene創始人Doug Cutting開發的使用廣泛的文本搜索庫。它起源于Apache Nutch,后者是一個開源的網絡搜索引擎,本身也是Luene項目的一部分。Aapche Hadoop架構是MapReduce算法的一種開源應用,是Google開創其帝國的重要基石。
Ceph
是加州大學圣克魯茲分校的Sage weil攻讀博士時開發的分布式文件系統。并使用Ceph完成了他的論文。
說 ceph 性能最高,C++編寫的代碼,支持Fuse,并且沒有單點故障依賴, 于是下載安裝, 由于 ceph 使用 btrfs 文件系統, 而btrfs 文件系統需要 linux 2.6.34 以上的內核才支持。可是ceph太不成熟了,它基于的btrfs本身就不成熟,它的官方網站上也明確指出不要把ceph用在生產環境中。
Lustre
Lustre是一個大規模的、安全可靠的,具備高可用性的集群文件系統,它是由SUN公司開發和維護的。
該項目主要的目的就是開發下一代的集群文件系統,可以支持超過10000個節點,數以PB的數據量存儲系統。
目前Lustre已經運用在一些領域,例如HP SFS產品等。
MogileFS
由memcahed的開發公司danga一款perl開發的產品,目前國內使用mogielFS的有圖片托管網站yupoo等。
MogileFS是一套高效的文件自動備份組件,由Six Apart開發,廣泛應用在包括LiveJournal等web2.0站點上。
MogileFS由3個部分組成:
第1個部分是server端,包括mogilefsd和mogstored兩個程序。前者即是 mogilefsd的tracker,它將一些全局信息保存在數據庫里,例如站點domain,class,host等。后者即是存儲節點(store node),它其實是個HTTP Daemon,默認偵聽在7500端口,接受客戶端的文件備份請求。在安裝完后,要運行mogadm工具將所有的store node注冊到mogilefsd的數據庫里,mogilefsd會對這些節點進行管理和監控。
第2個部分是utils(工具集),主要是MogileFS的一些管理工具,例如mogadm等。
第3個部分是客戶端API,目前只有Perl API(MogileFS.pm)、PHP,用這個模塊可以編寫客戶端程序,實現文件的備份管理功能。
mooseFS
持FUSE,相對比較輕量級,對master服務器有單點依賴,用perl編寫,性能相對較差,國內用的人比較多
MooseFS與MogileFS的性能測試對比
FastDFS
是一款類似Google FS的開源分布式文件系統,是純C語言開發的。
FastDFS是一個開源的輕量級分布式文件系統,它對文件進行管理,功能包括:文件存儲、文件同步、文件訪問(文件上傳、文件下載)等,解決了大容量存儲和負載均衡的問題。特別適合以文件為載體的在線服務,如相冊網站、視頻網站等等。
TFS(Taobao !FileSystem)
是一個高可擴展、高可用、高性能、面向互聯網服務的分布式文件系統,主要針對海量的非結構化數據,它構筑在普通的Linux機器 集群上,可為外部提供高可靠和高并發的存儲訪問。TFS為淘寶提供海量小文件存儲,通常文件大小不超過1M,滿足了淘寶對小文件存儲的需求,被廣泛地應用 在淘寶各項應用中。它采用了HA架構和平滑擴容,保證了整個文件系統的可用性和擴展性。同時扁平化的數據組織結構,可將文件名映射到文件的物理地址,簡化 了文件的訪問流程,一定程度上為TFS提供了良好的讀寫性能。
官網 : http://code.taobao.org/p/tfs/wiki/index/
GridFS文件系統
MongoDB是一種知名的NoSql數據庫,GridFS是mongodb的一個內置功能,它提供一組文件操作的API以利用MongoDB存儲文件,GridFS的基本原理是將文件保存在兩個Collection中,一個保存文件索引,一個保存文件內容,文件內容按一定大小分成若干塊,每一塊存在一個Document中,這種方法不僅提供了文件存儲,還提供了對文件相關的一些附加屬性(比如MD5值,文件名等等)的存儲。文件在GridFS中會按4MB為單位進行分塊存儲。
MongoDB GridFS 數據讀取效率 benchmark
3、從理論原理到實戰案例來闡述MogileFS體系
簡介
MogileFS是一個開源的分布式文件存儲系統,由LiveJournal旗下的DangaInteractive公司開發。Danga團隊開發了包括 Memcached、MogileFS、Perlbal 等多個知名的開源項目。目前使用MogileFS 的公司非常多,如日本排名先前的幾個互聯公司及國內的yupoo(又拍)、digg、豆瓣、1號店、大眾點評、搜狗和安居客等,分別為所在的組織或公司管理著海量的圖片。
MogileFS組成部分
MogileFS由3個部分組成:
1、server:主要包括mogilefs和mogstored兩個應用程序。mogilefs實現的是tracker,它通過數據庫來保存元數據信息,包括站點domain、class、hots等;mogstored是存儲節點(storgenode’),它其實是個WsbDAV服務,默認監聽在7500 端口,接受客戶端的文件存儲請求。在Mogilefs安裝完后,要運行mogadm工具將所有storge node注冊到mogilefs的數據庫里,mogilefs會對這些節點進行管理和監控。
2、utils(工具集):主要是Mogilefs的一些管理工具,例如mogadm等
3、客戶端API:mogilefs的客戶端API很多,例如Perl、PHP、java、python等,用這個模塊可以編寫客戶端程序,實現文件的備份管理功能等;
MogileFS特性
1、 工作與應用層
2、 無單點:三大組件(tracker、mogstore,database)皆可實現高可用;
3、 自動完成文件復制:復制的最小單位不是文件,而是class,文件可以被自動復制到多個有足夠存儲空間的存儲節點上;
4、 傳輸無需特殊協議:可以通過NFS或HTTP協議進行通信;
5、 名稱空間:文件通過一個給定的key來確定,是一個全局的命名空間,沒有目錄基于域實現文件隔離;
6、 不共享任何數據:無需通過昂貴的SAN來共享磁盤,每個存儲節點只需維護自己所屬的存儲設備(device);
MogileFS原理
術語解釋
tracker:借助數據庫保存各個節點的元數據信息,便于檢索定位數據位置并監控各個節點,告知客戶端存儲區的位置并指揮storage節點復制數據副本,進程為mogilefsd
database:為tracker節點存儲節點文件的元數據信息;
storage:將指定域中的鍵轉換我I特有的文件名存儲與在特定的設備文件中,轉換后文件名為值,storage自動維護鍵值之間的對應關系,storage節點使用http進行數據傳輸,依賴于perbl,進程為mogstored,perbal;
Domain:一個域中的鍵值為唯一的,一個Mogilefs可以有多個域來存儲不同類型的文件;
Class:復制的最小單位,管理文件屬性,定義文件存儲在不同設備上的分數;
device:一個存儲節點,可以有多個device,就是用來存放文件的目錄,每個設備都有一個設備ID,需要在mogstored配置文件中docroot配置,設備不能刪除,只能將設備的狀態置為dead,置為dead之后數據就無法恢復了,并且設備ID也無法使用。(建議每個節點只有一個device,文件存儲多份時,有多余數據備份在當前節點其他設備,等于沒有備份,若只備份2份,節點發生故障,數據就會丟失);
Mogilefs架構圖

上圖為Mogilefs架構圖,下面也描述了圖中體現出一次數據請求過程。
1、 客戶端在發起一次數據請求,假設請求banner.jpg,請求首先到達前端代理perbal(當然此處可利用Nginx實現)
2、 perbal或nginx會將請求代理至Mogilefs client(這里解釋下,MogileFS本身就是一個Web服務可以提高返回數據信息,不過普通的瀏覽器或web客戶端是不具備利用獲取的Mogilefs返回的數據位置信息再次請求storage節點獲取數據的,所以此處需要一個特定的客戶端來訪問Mogilefs,而此客戶端在Nginx代理時,是nginx的特定的模塊。)
3、 mogilefs client模塊將請求發往trackers節點,trackers向DB server發起查詢
4、 tracker將以banner.jpg為key查詢到的vlaue值發給nginx。
5、 Nginx通過Mogilefs API向storage 節點請求數據。
這就是一次完整的數據獲取過程。
MogileFS的實現
各角色和服務之間都是基于套接字來進行通信的,就服務本身就沒有耦合性,所以可以在服務器設備有限的場景下運行多種服務或角色.
2)Nginx根據反向代理+負載均衡機制隨機代理到后端Tracker(node1)(任意一臺)。
3)Tracker(node1)向mysql服務器發起查詢請求。
4)mysql服務器返回查詢結果給Tracker(node1)。
5)Tracker(node1)將查詢結果返回給Nginx。
6)Nginx將查詢結果根據模塊轉換為合理的url發送給后端的Storage存儲服務器(node3)。
7)Storage存儲服務器(node3)將文件內容通過http協議返回給Nginx。
8)Nginx將結果返回給應用層的請求。
說明:大家一眼就可以看出來這個拓撲規劃的缺陷,首先是前端nginx代理服務器單點故障所在處、如果高并發的情況下一臺根本就支撐不了,此時前端可以考慮Nginx+keepalived或者是Haproxy+keepalived,其次是后端的mysql,就算前端一臺nginx支撐得了,但是讀寫操作都壓在了一臺mysql上面,很明顯mysql就需要擴展了,構建主從的架構適宜,最后的Tracker和Storage完全可以在一臺主機上運行,他們之間沒有任何影響;但是本文的重點在于如何去部署一個MogileFS的應用場景,其他并未考慮,請各位朋友不要誤解!
2.實驗步驟:
(1).安裝、配置mysql 172.16.41.5
1 yum -y install mariadb-server mariadb
2
3
4
5
6
7
8
9
10
|
MariaDB [(none)]> use mysql
#刪除有安全隱患的賬戶
MariaDB [mysql]> DELETE FROM user WHERE host = ‘::1’;
MariaDB [mysql]> DELETE FROM user WHERE user = ”;
#授權root用戶能遠程登錄
MariaDB [mysql]> GRANT ALL ON *.* TO ‘root’@’172.16.%.%’ IDENTIFIED BY ‘123.com’;
#授權moguser用戶
MariaDB [mysql]> GRANT ALL ON mogdb.* TO ‘moguser’@’172.16.%.%’ IDENTIFIED BY ‘123.com’;
#刷新授權表
MariaDB [mysql]> FLUSH PRIVILEGES;
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
|
yum -y install perl-IO-AIO perl-Net-Netmask perl-core #解決perl依賴關系
#→下面這些包是Tracker和Storage端必裝的程序包.
yum -y install *.rpm
MogileFS-Server-2.46-2.el6.noarch.rpm
MogileFS-Server-mogilefsd-2.46-2.el6.noarch.rpm
MogileFS-Server-mogstored-2.46-2.el6.noarch.rpm
MogileFS-Utils-2.19-1.el6.noarch.rpm
perl-5.10.1-144.el6.i686.rpm
Perlbal-1.78-1.el6.noarch.rpm
Perlbal-doc-1.78-1.el6.noarch.rpm
perl-Danga-Socket-1.61-1.el6.rf.noarch.rpm
perl-MogileFS-Client-1.14-1.el6.noarch.rpm
perl-Net-Netmask-1.9015-8.el6.noarch.rpm
perl-Perlbal-1.78-1.el6.noarch.rpm
注意:
mogilefs 0.25模塊會導致MogileFS復制不正常 , 發現文件少于指定的份數
解決方法
如果發現是顯示上面的 0.25 就一定會出問題.建議退回到 0.23 就不會在出問題了.
所以建議大家在安裝完 MogileFS 后,先退回這個模塊到 0.23.
perl -MSys::Syscall -e ‘print $Sys::Syscall::VERSION’ #查看版本
wget http://search.cpan.org/CPAN/authors/id/B/BR/BRADFITZ/Sys-Syscall-0.23.tar.gz
perl Makefile.PL
make
make install
|
1
2
|
#→安裝好tracker后會在/var/run/下面生成該目錄,改變目錄屬主.屬組
[root@node1 ~]# chown -R mogilefs.mogilefs /var/run/mogilefsd
|
1
|
[root@node1 ~]# mogdbsetup –dbrootuser=root –dbname=mogdb –dbhost=172.16.41.5
–dbport=3306 –dbrootpass=123.com –dbuser=moguser –dbpass=123.com –yes
|
<3>驗證初始化數據庫結果:
<4>修改tracker配置文件,如下內容:
1
2
3
4
5
6
|
[root@node1 ~]# vim /etc/mogilefs/mogilefsd.conf
#→修改下面4項即可其它參數根據工作環境自定
db_dsn = DBI:mysql:mogdb:host=172.16.41.5
db_user = moguser
db_pass = 123.com
listen = 0.0.0.0:7001
|
<5>修改storage配置文件,如下內容:
1
2
3
4
5
6
7
8
|
[root@node1 ~]# vim /etc/mogilefs/mogstored.conf
maxconns = 10000 #→存儲系統的最大連接數.
httplisten = 0.0.0.0:7500 #→這個就是webDAV服務使用的端口,但是這里我們不知使用它.
mgmtlisten = 0.0.0.0:7501 #→mogilefs的管理端口.
docroot = /data/mogdata #→該項決定了數據的在storage上存儲的實際位置,建議使用的是一個單獨掛載使用的磁盤.這里我就不用演示了.
pidfile = /var/run/mogilefsd/mogstored.pid
[root@node1 ~]# mkdir -p /data/mogdata/dev1
#→這里一定要改變數據存放目錄的屬主屬組,應為mogilefs服務程序必須是以普通用戶來運行的,否則服務啟動將失敗!
[root@node1 ~]# chown -R mogilefs.mogilefs /data/mogdata/dev1
|
<6>啟動tracker和storage服務:
1
2
3
4
5
|
[root@node2 ~]# service mogilefsd start
Starting mogilefsd [ OK ]
[root@node2 ~]# service mogstored start
Starting mogstored [ OK ]
[root@node2 ~]#
|
<7>在node1上面將自己添加mogstore存儲主機
1
|
[root@node1 ~]# mogadm –trackers=172.16.41.1:7001 host add 172.16.41.1
–ip=172.16.41.1 –status=alive
|
下面繼續配置:
<8>現將兩個配置文件拷貝至兩個節點中–要保證各個程序包都已經安裝了,否則在拷貝后安裝會覆蓋兩個配置文件.
1
2
3
4
5
6
7
|
[root@node1 ~]# scp /etc/mogilefs/* 172.16.41.2:/etc/mogilefs/
mogilefsd.conf 100% 1462 1.4KB/s 00:00
mogstored.conf 100% 93 0.1KB/s 00:00
[root@node1 ~]# scp /etc/mogilefs/* 172.16.41.3:/etc/mogilefs/
mogilefsd.conf 100% 1462 1.4KB/s 00:00
mogstored.conf 100% 93 0.1KB/s 00:00
[root@node1 ~]#
|
(4)配置node2.example.com
<1>程序包已經安裝
<2>設定數據庫已經完畢,該節點與node3節點無需重復此操作
<3>配置tracker.
1
2
|
#→安裝好tracker后會在/var/run/下面生成該目錄,改變目錄屬主.屬組
[root@node2 ~]# chown -R mogilefs.mogilefs /var/run/mogilefsd
|
<4>修改tracker配置文件,如下內容:
1
2
3
4
5
6
|
[root@node2 ~]# vim /etc/mogilefs/mogilefsd.conf
#→修改下面4項即可其它參數根據工作環境自定
db_dsn = DBI:mysql:mogdb:host=172.16.41.5
db_user = moguser
db_pass = 123.com
listen = 0.0.0.0:7001
|
<5>修改storage配置文件,如下內容:
1
2
3
4
5
6
7
8
|
[root@node2 ~]# vim /etc/mogilefs/mogstored.conf
maxconns = 10000
httplisten = 0.0.0.0:7500
mgmtlisten = 0.0.0.0:7501
docroot = /data/mogdata#→該項決定了數據的在storage上存儲的實際位置,建議使用的是一個單獨掛載使用的磁盤.這里我就不用演示了.
[root@node2 ~]# mkdir -p /data/mydata/dev2
#→這里一定要改變數據存放目錄的屬主屬組,應為mogilefs服務程序必須是以普通用戶來運行的,否則服務啟動將失敗!
[root@node2 ~]# chown -R mogilefs.mogilefs /data/mogdata/dev2
|
<6>啟動tracker和storage服務:
1
2
3
4
5
|
[root@node2 ~]# service mogilefsd start
Starting mogilefsd [ OK ]
[root@node2 ~]# service mogstored start
Starting mogstored [ OK ]
[root@node2 ~]#
|
<7>在node1上面將自己添加mogstore存儲主機
1
|
[root@node2 ~]# mogadm –trackers=172.16.41.2:7001 host add 172.16.41.2
–ip=172.16.41.2 –status=alive
|
此時兩個節點都加入到了MogileFS系統中,第三個節點配置與第二個一樣,只是配置文件修改一下即可,這里不在贅述!
下面就可以在node1節點上控制其他兩個節點即可!
(5)管理配置MogileFS集群系統
1
2
3
4
5
6
7
|
#→添加的第一個設備,設備號不能重名
[root@node1 ~]# mogadm –trackers=172.16.41.1:7001 device add 172.16.41.1 1
#→添加的第二個設備
[root@node1 ~]# mogadm –trackers=172.16.41.2:7001 device add 172.16.41.2 2
#→添加的第三個設備
[root@node1 ~]# mogadm –trackers=172.16.41.3:7001 device add 172.16.41.3 3
[root@node1 ~]# mogadm –trackers=172.16.41.3:7001 device list
|
<2>添加域domain—–域用來存儲不同應用類型的數據的容器
1
2
3
4
5
|
#→創建的圖片存放域
[root@node1 ~]# mogadm –trackers=172.16.41.1:7001 domain add images
#→創建的html等文件存放域
[root@node1 ~]# mogadm –trackers=172.16.41.1:7001 domain add files
[root@node1 ~]# mogadm –trackers=172.16.41.1:7001 domain list
|
<3>添加類class
1
2
3
4
5
6
7
|
[root@node1 ~]# mogadm –trackers=172.16.41.1:7001 class add images class0 –mindevcount=2
[root@node1 ~]# mogadm –trackers=172.16.41.1:7001 class add images class1 –mindevcount=2
[root@node1 ~]# mogadm –trackers=172.16.41.1:7001 class add images class3 –mindevcount=2
[root@node1 ~]# mogadm –trackers=172.16.41.1:7001 class add files class0 –mindevcount=2
[root@node1 ~]# mogadm –trackers=172.16.41.1:7001 class add files class1 –mindevcount=2
[root@node1 ~]# mogadm –trackers=172.16.41.1:7001 class add files class2 –mindevcount=2
[root@node1 ~]# mogadm –trackers=172.16.41.1:7001 class list
|
這里再次提一下關于這兩個概念
域(domain)
在一個 MogileFS 中,可以有多個域,用來存放不同的文件,比如,不同大小的文件,不同類型的文件.在上圖中所有 alive 的”設備”是一個大的整體,形成一個統一的存儲空間,里面的數據可以根據 “域” domain 和類 class 來分類管理,屬于同一個 domain,即使是屬于不同的class,文件的key也必須是唯一的.不同域的 key 才能重復.
類(class)
在一個域中,可以有多個類,主要是用來控制復制單元的,類是用來做屬性管理的,類是比域 domain 低一個級別,可以定義一個文件存儲在不同 device 中的份數.一個文件必須通過 domain,class 和 key 才能找出來.我們可以給不同的重要程度的文件,不同熱度的文件,來分別用類來控制份數.
使用mogupload工具在這里是為了測試,實際環境中上傳是由程序員在代碼中使用mogilefs的API進行交互的。
1
2
3
|
[root@node1 ~]# mogupload –trackers=172.16.41.1:7001 –domain=images –key=’tux_1.jpg’ –file=’/root/my_test_data/1.jpg’
#→–key=’tux_1.jgp’ 是我要上傳后的鍵是什么
#→ –file 指的是我要上傳的文件
|
通過將它給出的路徑來訪問一下看能不能正常的訪問到?
模擬某個節點故障,看文件是否還在?
看到我們的文件還有一份保存在另外一節點上面的,通過那個路徑也能訪問到該文件,而且在每個storage節點上都能看到這個文件,之前說過啦,他們用的都是一個數據庫;
OK!此時我們MogileFS系統基本上部暑基本完畢;
下面介紹Nginx做為MogileFS的前端客戶端是如何實現的!
Nginx做為MogileFS的前端客戶端,我們使用Nginx來吐文件,做前端的查詢代理時,我們需要使用到mogilefs的這個模塊,可以下載這個模塊編譯進Nginx就行了,直接使用 ./configure -add-module=這個參數就可以了,最新的這個模塊的下載地址是:https://github.com/vkholodkov/nginx-mogilefs-module
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
|
#這里需要安裝個pcre-devel包
[root@node ~]# yum install -y pcre-devel
#解壓獲取到的mogilefs模塊包
[root@node4 ~]# tar -zxvf nginx_mogilefs_module-1.0.4.tar.gz
#解壓、編譯安裝nginx
[root@node4 ~]# tar -xf nginx-1.4.7.tar.gz -C /usr/src/
[root@nginx ~]# cd /usr/src/nginx-1.4.7/
[root@nginx nginx-1.4.7]#
./configure \
–prefix=/usr \
–sbin-path=/usr/sbin/nginx \
–conf-path=/etc/nginx/nginx.conf \
–error-log-path=/var/log/nginx/error.log \
–http-log-path=/var/log/nginx/access.log \
–pid-path=/var/run/nginx/nginx.pid \
–lock-path=/var/lock/nginx.lock \
–user=nginx \
–group=nginx \
–with-http_ssl_module \
–with-http_flv_module \
–with-http_stub_status_module \
–with-http_gzip_static_module \
–http-client-body-temp-path=/var/tmp/nginx/client/ \
–http-proxy-temp-path=/var/tmp/nginx/proxy/ \
–http-fastcgi-temp-path=/var/tmp/nginx/fcgi/ \
–http-uwsgi-temp-path=/var/tmp/nginx/uwsgi \
–http-scgi-temp-path=/var/tmp/nginx/scgi \
–with-pcre \
–with-debug \
–add-module=/root/nginx_mogilefs_module-1.0.4
make
make install
make時出現以下錯誤,解決辦法:# vim objs/Makefile (修改objs/Makefile文件,
“去掉其中的”-Werror” CFLAGS = -pipe -O -W -Wall -Wpointer-arith -Wno-unused-parameter -g ),
然后就能夠正常編譯了. 先./configure 后在刪除,最后make
/root/nginx-mogilefs-module-master/ngx_http_mogilefs_module.c:748:37: 錯誤:變量‘request’被設定但未被使用 [-Werror=unused-but-set-variable]
ngx_str_t request, domain;
^
/root/nginx-mogilefs-module-master/ngx_http_mogilefs_module.c: 在函數‘ngx_http_mogilefs_create_spare_location’中:
/root/nginx-mogilefs-module-master/ngx_http_mogilefs_module.c:1541:39: 錯誤:變量‘pclcf’被設定但未被使用 [-Werror=unused-but-set-variable]
ngx_http_core_loc_conf_t *clcf, *pclcf, *rclcf;
^
cc1: all warnings being treated as errors
make[1]: *** [objs/addon/nginx-mogilefs-module-master/ngx_http_mogilefs_module.o] 錯誤 1
make[1]: 離開目錄“/root/nginx-1.10.3”
make: *** [build] 錯誤 2
|
2.為nginx提供SysV init腳本:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
|
[root@nginx ~]# vim /etc/rc.d/init.d/nginx
#!/bin/sh
#
# nginx – this script starts and stops the nginx daemon
#
# chkconfig: – 85 15
# description: Nginx is an HTTP(S) server, HTTP(S) reverse \
# proxy and IMAP/POP3 proxy server
# processname: nginx
# config: /etc/nginx/nginx.conf
# config: /etc/sysconfig/nginx
# pidfile: /var/run/nginx.pid
# Source function library.
. /etc/rc.d/init.d/functions
# Source networking configuration.
. /etc/sysconfig/network
# Check that networking is up.
[ “$NETWORKING” = “no” ] && exit 0
nginx=”/usr/sbin/nginx”
prog=$(basename $nginx)
NGINX_CONF_FILE=”/etc/nginx/nginx.conf”
[ -f /etc/sysconfig/nginx ] && . /etc/sysconfig/nginx
lockfile=/var/lock/subsys/nginx
make_dirs() {
# make required directories
user=`nginx -V 2>&1 | grep “configure arguments:” | sed ‘s/[^*]*–user=\([^ ]*\).*/\1/g’ -`
options=`$nginx -V 2>&1 | grep ‘configure arguments:’`
for opt in $options; do
if [ `echo $opt | grep ‘.*-temp-path’` ]; then
value=`echo $opt | cut -d “=” -f 2`
if [ ! -d “$value” ]; then
# echo “creating” $value
mkdir -p $value && chown -R $user $value
fi
fi
done
}
start() {
[ -x $nginx ] || exit 5
[ -f $NGINX_CONF_FILE ] || exit 6
make_dirs
echo -n $”Starting $prog: ”
daemon $nginx -c $NGINX_CONF_FILE
retval=$?
echo
[ $retval -eq 0 ] && touch $lockfile
return $retval
}
stop() {
echo -n $”Stopping $prog: ”
killproc $prog -QUIT
retval=$?
echo
[ $retval -eq 0 ] && rm -f $lockfile
return $retval
}
restart() {
configtest || return $?
stop
sleep 1
start
}
reload() {
configtest || return $?
echo -n $”Reloading $prog: ”
killproc $nginx -HUP
RETVAL=$?
echo
}
force_reload() {
restart
}
configtest() {
$nginx -t -c $NGINX_CONF_FILE
}
rh_status() {
status $prog
}
rh_status_q() {
rh_status >/dev/null 2>&1
}
case “$1” in
start)
rh_status_q && exit 0
$1
;;
stop)
rh_status_q || exit 0
$1
;;
restart|configtest)
$1
;;
reload)
rh_status_q || exit 7
$1
;;
force-reload)
force_reload
;;
status)
rh_status
;;
condrestart|try-restart)
rh_status_q || exit 0
;;
*)
echo $”Usage: $0 {start|stop|status|restart|condrestart|try-restart|reload|force-reload|configtest}”
exit 2
esac
[root@nginx ~]# chmod +x /etc/rc.d/init.d/
[root@nginx ~]# chkconfig –add nginx
[root@nginx ~]# chkconfig nginx on
#啟動nginx
[root@nginx ~]# service nginx start
Starting nginx: [ OK ]
[root@nginx ~]# ss -tnl | grep :80
LISTEN 0 128 *:80 *:*
[root@nginx ~]#
|
3.修改nginx主配置文件:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
|
[root@nginx ~]# vim /etc/nginx/nginx.conf
worker_processes 2;
events {
worker_connections 1024;
}
http {
include mime.types;
default_type application/octet-stream;
sendfile on;
keepalive_timeout 65;
gzip on;
server {
listen 80;
server_name www.magelinux.com;
location / {
root html;
index index.html index.htm;
}
################About images###############
location /images/ {
mogilefs_tracker 172.16.41.1:7001;
mogilefs_domain images;
mogilefs_pass {
proxy_pass $mogilefs_path;
proxy_hide_header Content-Type;
proxy_buffering off;
}
}
################About files###############
location /files/ {
mogilefs_tracker 172.16.41.1:7001;
mogilefs_domain images;
mogilefs_pass {
proxy_pass $mogilefs_path;
proxy_hide_header Content-Type;
proxy_buffering off;
}
}
error_page 404 /404.html;
error_page 500 502 503 504 /50x.html;
location = /50x.html {
root html;
}
}
}
|
4.測試:
下面我上傳一個html文檔看能否代理成功?
此時我查看到了在兩個域類有兩個key,注意它們在上傳的時候輸入的類容,以及在去觀察在nginx反代中的書寫方法有是有一定區別的,先測試,稍后說
ok!fiels測試沒有問題,但是我們可以將nginx的配置修改一下,讓我在定義鍵的時候也改一下.
nginx中只需要修改 location /files/ 和proxy pass這段內容即可,這種方式定義images也一樣適用,先看看效果吧.
重新加載nginx、再次訪問測試:
這兩種定義方法可根據實際場景應用!
朋友們大概注意到了我在nginx的配置文件中,只是配置了將客戶端請求代理到后端的一臺tracker上面,如果要將多個tracker基于負載均衡的方式來提供服務,于是我們就需要定義upstream啦;請看以下配置:
重新加載nginx、再次訪問測試:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
|
####################################################################
#→顯示當前mogilefs的配置信息(host,domain,class)狀態,如果加上–stats=”domains”可以只顯示domian相關的信息.
[root@node1 ~]# mogstats –config=/etc/mogilefs/mogilefsd.conf
####################################################################
#→顯示一個具體文件的信息,包括所在域、副本數、文件ID、key、復制到了哪些tracker上面.
[root@node1 ~]# mogfileinfo –trackers=172.16.41.1:7001 –domain=images –key=”tux_1.jpg”
####################################################################
#→上傳一個本地文件到指定的域內,同時必須指定key.
[root@node1 ~]# mogupload –trackers=172.16.41.1:7001 –domain=images –key=’tux_1.jpg’ –file=’/root/my_test_data/1.jpg’
####################################################################
#→刪除指定域內的一個key.
[root@node1 ~]# mogdelete –trackers=172.16.41.1:7001 –domain=images –key=’test1.html
####################################################################
#→查看指定域內的文件有哪些.
[root@node1 ~]# moglistkeys –trackers=172.16.41.1:7001 –domain=files
####################################################################
#→檢查整個mogilefs系統.
[root@node1 ~]# mogadm –trackers=172.16.41.1:7001 check
####################################################################
…………………………..
…………………………..
#→以上工具使用較為方便,其他工具使用請找”man”!
|
4、自動化運維工具ansible的應用實例
1.ansible
ansible是新出現的自動化運維工具,基于Python研發。糅合了眾多老牌運維工具的優點實現了批量操作系統配置、批量程序的部署、批量運行命令等功能。僅需在管理工作站上安裝ansible程序配置被管控主機的IP信息,被管控的主機無客戶端。ansible應用程序存在于epel(第三方社區)源,依賴于很多python組件
參考站點:http://www.ansible.com.cn
2.ansible特性
模塊化設計,調用特定的模塊來完成特定任務,本身是核心組件,短小精悍;
基于Python語言實現,由Paramiko(python的一個可并發連接ssh主機功能庫), PyYAML和Jinja2(模板化)三個關鍵模塊實現;
部署簡單,agentless無客戶端工具;
主從模式工作;
支持自定義模塊功能;
支持playbook劇本,連續任務按先后設置順序完成;
期望每個命令具有冪等性:
3.ansible架構
ansible core:ansible自身核心模塊
host inventory:主機庫,定義可管控的主機列表
connection plugins:連接插件,一般默認基于ssh協議連接
modules:core modules(自帶模塊)、custom modules(自定義模塊)
playbooks:劇本,按照所設定編排的順序執行完成安排任務
4.配置文件:
(1)ansible應用程序的主配置文件:/etc/ansible/ansible.cfg
(2) Host Inventory定義管控主機:/etc/ansible/hosts
遵循INI風格;中括號中的字符是組名;一個主機可同時屬于多個組;
示例:
# Ex 1: Ungrouped hosts, specify before any groupheaders.直接在任何組的頭部前面指定,不屬于任何組的主機
green.example.com
blue.example.com
192.168.100.1
192.168.100.10
# Ex 2: A collection of hosts belonging to the’webservers’ group;一批主機屬于一個組,例如定義為‘webservers’的組
[webservers]
alpha.example.org
beta.example.org
192.168.1.100
192.168.1.110
注意:默認是以root用戶執行,但是基于ssh連接操作要多次輸入密碼,為方便可以使用基于ssh密鑰方式進行認證
二、ansible應用程序命令
1.ansible-doc命令:獲取模塊列表,及模塊使用格式;
ansible-doc -l:獲取列表
ansible-doc -s module_name:獲取指定模塊的使用信息
2.ansible命令格式
ansible <host-pattern> [-f forks] [-m module_name] [-a args]
<host-pattern> |
指明管控主機,以模式形式表示或者直接給定IP,必須事先定義在文件中;all設置所有 |
[-f forks] |
指明每批管控多少主機,默認為5個主機一批次 |
[-m module_name] |
使用何種模塊管理操作,所有的操作都需要通過模塊來指定 |
[-a args] |
指明模塊專用參數;args一般為key=value格式 注意:command模塊的參數非為kv格式,而是直接給出要執行的命令即可; |
注意:<host-pattern>默認讀取/etc/ansible/hosts,也可以指明自定義文件路徑
-iPATH, –inventory=PATH:指明使用的host inventory文件路徑;
常用模塊(module_name):
1)command:默認模塊,可省略。在遠程主機上進行操作命令
-a ‘COMMAND’
注意:comand模塊的參數非key=value格式,直接給出要執行的命令
[root@localhost ~]# ansible all -m command -a ‘ifconfig’
2)user:
-a ‘name= state={present(創建)|absent(刪除)} force=(是否強制操作刪除家目錄) system= uid= shell= home=’
[root@localhost ~]# ansible all -m user -a ‘name=ansible state=present’
3)group:
-a ‘name= state={present|absent} gid= system=(系統組)‘
[root@localhost ~]# ansible all -m group -a ‘name=mygroup state=presentsystem=true’
4)cron:
-a ‘name= state= minute= hour= day= month= weekday= job=’
[root@localhost ~]# ansible all -m cron -a ‘name=’Time’ state=presentminute=’*/5′ job=’/usr/sbin/ntpdate 172.168.0.1 &> /dev/null”
5)ping:
無參數
[root@localhost ~]# ansible all -m ping
6)file:文件管理
-a ‘path= mode= owner= group= state={file|directory|link|hard|touch|absent} src=(link,鏈接至何處)‘
[root@localhost ~]# ansible all -m file -a ‘path=/tmp/testdirstate=directory’
[root@localhost ~]# ansible all -m file -a ‘path=/tmp/test.txt state=touchmod=600 owner=user1’
7)copy:
-a ‘dest=(遠程主機上路徑) src=(本地主機路徑) content=(直接指明內容) owner= group= mode=’
[root@localhosttmp]# ansible web -m copy -a ‘src=/etc/yum.repos.d/aliyun.repodest=/etc/yum.repos.d/’
8)template
-a ‘dest= src=\’#\'” content= owner= group= mode=’
9)yum:
-a ‘name= conf_file=(指明配置文件) state={present|latest|absent} enablerepo= disablerepo=’
[root@localhost ~]# ansible all -m yum ‘name=httpd state=present’
10)service:
-a ‘name= state={started|stopped|restarted} enabled=(是否開機自動啟動) runlevel=’
[root@localhost ~]# ansible all -m service -a ‘name=httpd state=started’
11)shell:
-a ‘COMMAND’ 運行shell命令
[root@localhost ~]# ansible all -m shell -a echo “123456789” |passwd –stdin user1′
12)script:
-a ‘/PATH/TO/SCRIPT’運行腳本
[root@localhost ~]# ansible all -m script -a ‘/tmp/a.sh’
13)setup:獲取指定主機的facts變量;
三、Playbooks劇本
1.playbook組織格式:YAML語言格式
playbooks是ansible更強大的配置管理組件,實現基于文本文件編排執行的多個任務,且多次重復執行
(1)YAML簡介
YAML:YAML Ain’t Markup Language; Yet Another Markup Language;
類似于半結構化數據,聲明式配置;可讀性較高的用來表達資料序列的格式,易于與腳本語言交互
官方站點:http://www.yaml.org
(2)語法格式
1)任何書記結構都用縮進來標識,可以嵌套
2)每一行是一個鍵值數據key:value,冒號隔開。若想在一行標識需要用{ }和,分隔格式
3)列表用 – 標識
2.inventory參數:主機庫ssh參數設置
ansible基于ssh連接inventory中指定的遠程主機時,將以此處的參數指定的屬性進行;
ansible_ssh_port |
指定ssh端口 |
ansible_ssh_user |
指定ssh用戶 |
ansible_ssh_pass |
指定ssh用戶登錄是認證密碼,明文密碼不安全 |
ansible_sudo_pass |
指明sudo時候的密碼 |
實例:
[websrvs]
192.168.0.101 ansible_ssh_port=22 ansible_ssh_user=root ansible_ssh_pass=xuding
192.168.0.102
注意:在/etc/ansible/hosts中直接定義連接時候的密碼不安全,一般建議基于ssh的密鑰認證方式實現
3.playbooks
(1)核心元素
Tasks任務、Variables變量、Templates模板、Handlers處理器、Roles角色
(2)playbooks中定義任務:
– name: task description 注釋描述信息
module_name: module_args 聲明模塊:定義ansible模塊參數
(3)ansible-playbook執行命令:
ansible-playbook <filename.yml> … [options]
4.playbook— 變量
(1)變量命名:字母、數字和下劃線組成,僅能以字母開頭;
(2)變量種類:
1)facts:由遠程主機發回的主機特有的屬性信息,這些信息被保存在ansible變量中;無須聲明,可直接調用;
2)自定義變量:
通過命令行傳遞:ansible-playbook test.yml –extra-vars “host=www user=test”
通過roles傳遞
3)主機變量:定義在inventory中的主機之后的變量;直接傳遞給單個主機的變量
實例:
[root@localhost ~]# vim /etc/ansible/hosts中直接定義在主機之后
[web]
192.168.0.101 host=mail
192.168.0.102
192.168.0.103
4)組變量:定義在inventory中的組上的變量(例如在默認的文件/etc/ansible/hosts上編輯)
[group_name:vars]
var1=value
var2=value
注意:組名要事先存在,實例如下:
[websrvs]
192.168.0.101
192.168.0.102
[websrvs:vars]
host=mail
變量使用示例:
[root@localhost~]# vim useradd.yml
– hosts: websrvs
remote_user: root
vars:
username: testuser
password: xuding
tasks:
-name: add user
user: name={{ username }} state=present
-name: set password
shell: /bin/echo {{ password }} |/usr/bin/passwd –stdin {{ username }}
注釋:
1) {{ }} 調用變量
2) #ansible-playbook /PATH/TO/SOME_YAML_FILE { -eVARS|–extra-vars=VARS} 變量的重新賦值調用方法
[root@localhost ~]# ansible-playbookuseradd.yml –extra-vars “username=ubuntu”
5.playbook— tasks
(1)條件測試:
在某task后面添加when子句即可實現條件測試功能;when語句支持Jinja2語法;
實例:當時RedHat系列系統時候調用yum安裝
tasks:
-name: install web server package
yum: name=httpd state=present
when: ansible_os_family == “RedHat”
(2)迭代:item
在task中調用內置的item變量;在某task后面使用with_items語句來定義元素列表;
tasks:
-name: add four users
user: name={{ item }} state=present
with_items:
-testuser1
-testuser2
-testuser3
-testuser4
注意:迭代中,列表中的每個元素可以為字典格式;
實例:
-name: add two users
user: name={{ item.name }} state=present groups={{ item.groups }}
with_items:
– { name: ‘testuser5’, groups: ‘wheel’ }
– { name: ‘testuser6’, groups: ‘root’ }
6.playbook— handlers:處理器;觸發器
只有其關注的條件滿足時,才會被觸發執行的任務;
實例:配置文件發生改變觸發重啟服務
-hosts: websrvs
remote_user: root
tasks:
-name: install httpd
yum:name=httpd state=present
-name: install config file
copy: src=/root/httpd.confdest=/etc/httpd/conf/httpd.conf
notify: restart httpd
-name: start httpd service
service: name=httpd state=started
handlers:
-name: restart httpd
service: name=httpd state=restarted
7.playbook模板
templates:
用于生成文本文件(配置文件);模板文件中可使用jinja2表達式,表達式要定義在{{}},也可以簡單地僅執行變量替換;
roles:
roles用于實現“代碼復用”;
roles以特定的層次型格式組織起來的playbook元素(variables,tasks, templates, handlers);
可被playbook以role的名字直接進行調用;
用法:在roles/下建立[group_name]子目錄,并非全部都要創建;例如:
/etc/ansible/roles/(在/etc/ansible/ansible.cfg定義roles目錄)
webserver/
files/:此角色中用到的所有文件均放置于此目錄中;
templates/:Jinja2模板文件存放位置;
tasks/:任務列表文件;可以有多個,但至少有一個叫做main.yml的文件;
handlers/:處理器列表文件;可以有多個,但至少有一個叫做main.yml的文件;
vars/:變量字典文件;可以有多個,但至少有一個叫做main.yml的文件;
meta/:此角色的特殊設定及依賴關系;
原創文章,作者:N27_Vicent,如若轉載,請注明出處:http://www.www58058.com/84059
文章的廣度和深度讓人印象深刻,再接再勵。