Hadoop學習筆記—HDFS
上一份工作主要負責大數據平台的建設,在這個過程中積累了一些Hadoop生態組件的搭建和使用筆記,由於時間關係,不打算去修改其中的錯別字和排版問題,直接釋出原始筆記。
搭建安裝
三個核心組件
一個hadoop基本集群,牽涉三個組件:
- hdfs 負責分散式的文件存儲
- yarn 負責分散式的資源管理
- mr 負責分散式計算
安裝
配置環境變數
配置etc/hadoop/hadoop-env.sh、etc/hadoop/hadoop-env.sh、etc/hadoop/yarn-env.sh 這三個腳本來配置三個組件執行的環境變數
當然,機器特定的環境變數可以放在 /etc/profile.d 中
最重要的是在上述三個shell腳本的最後,配置JAVA_HOME。
上述三個shell中,有大量環境變數KEY可以配置,他們一般見名知意。可以使用一些帶OPTS後綴的配置,去覆蓋那些特定配置。帶OPTS的後綴有
比如HADOOP_HEAPSIZE_MAX=1g 可以被HADOOP_NAMENODE_OPTS=”-Xmx5g” 所覆蓋
配置各上述三組件守護進程的相關屬性
上述環境變數配置好後,就要配置hdfs, yarn, mr三者的進程,即程式執行的行為屬性。其分別對應的配置文件為
- etc/hadoop/core-site.xml 、etc/hadoop/hdfs-site.xml 用於給hdfs配置
- etc/hadoop/yarn-site.xml 用於給yarn配置
- etc/hadoop/mapred-site.xml 用於給mr配置
具體看文檔即可,這裡對一些有意思的配置單列說明
hdfs的配置
- dfs.namenode.name.dir namenode的數據存儲路徑,多個文件,表示數據存多份,提高冗餘
yarn的配置
- yarn.log-aggregation-enable 啟動log aggregation,這會將yarn集群中執行應用的本地日誌,複製到hdfs集群中進行高可用管理
啟停
可以針hdfs,mr,yarn三個組件的各角色進行啟動。
其中Hdfs的各角色,可以使用etc/hadoop/workers
配置,通過$HADOOP_HOME/sbin/start-dfs.sh
批量啟動。
具體啟停看文檔
監控和性能
Hadoop Rack Awareness
Hadoop Rack Awareness,啟用該特性,讓Hadoop集群感知物理存儲拓撲,從而更好的提高數據分片性能,具體看文檔
yarn的NodeManagers監控
可以指定一些監控nodeManager狀態的腳本給NodeManager, NodeManager會周期性的調用,檢查自己的狀態,yarn則會收集該狀態,然後不會將程式分發到這些異常NodeManager上執行
命令
文檔地址://hadoop.apache.org/docs/stable/hadoop-project-dist/hadoop-common/FileSystemShell.html
hdfs的命令
如果hadoop操作的是hdfs,那麼下面兩種命令格式等效
bin/hadoop fs <args>
hdfs dfs <args>
hadoop fs的相關命令支援多種文件系統
- hdfs hadoop自己的分散式文件系統
- Local FS 本地文件系統,即為當前機器的文件系統
- WebHDFS
- S3 FS 亞馬遜的分散式文件系統
hadoop fs命令一般操作的文件系統路徑格式URI為scheme://authority/path
,比如hdfs舉例hdfs://namenodehost/parent/child
appendToFile
將本地單個文件或多個文件,或則本機的標準輸入中的內容,拷貝到目標文件系統
用法:hadoop fs -appendToFile <localsrc> ... <dst>
hadoop fs -appendToFile localfile /user/hadoop/hadoopfile
hadoop fs -appendToFile localfile1 localfile2 /user/hadoop/hadoopfile
hadoop fs -appendToFile localfile hdfs://nn.example.com/hadoop/hadoopfile
hadoop fs -appendToFile - hdfs://nn.example.com/hadoop/hadoopfile Reads the input from stdin.
Returns 0 on success and 1 on error.
cat
將文件系統中指定文件內容輸出到終端
用法:hadoop fs -cat [-ignoreCrc] URI [URI ...]
hadoop fs -cat hdfs://nn1.example.com/file1 hdfs://nn2.example.com/file2
hadoop fs -cat file:///file3 /user/hadoop/file4
Returns 0 on success and -1 on error
checksum
對指定文件生成checksum值
用法:hadoop fs -checksum URI
hadoop fs -checksum hdfs://nn1.example.com/file1
hadoop fs -checksum file:///etc/hosts
chgrp
改變文件的組
用法:hadoop fs -chgrp [-R] GROUP URI [URI ...]
- 其中-R是表示將該路徑下的所有文件組都修改
- GROUP是要修改成的組
- URI是文件或文件夾的路徑
- 該命令只有管理員或當前文件的擁著才能執行
chmod
改變文件的讀寫執行模式
用法: hadoop fs -chmod [-R] <MODE[,MODE]... | OCTALMODE> URI [URI ...]
- 其中-R是表示將該路徑下的所有文件組都修改
- 該命令只有管理員或當前文件的擁著才能執行
todo:具體mod詳情,需要再查閱
chown
改變文件的擁有者
用法:hadoop fs -chown [-R] [OWNER][:[GROUP]] URI [URI ]
- 其中-R是表示將該路徑下的所有文件組都修改
- 該命令只有管理員或當前文件的擁著才能執行
copyFromLocal
將當前機器本地文件,拷貝到分散式文件系統
用法: hadoop fs -copyFromLocal [args] <localsrc> URI
其中命令參數有以下幾個,都是可選
- -p複製到分散式文件系統的文件保留原文件的修改時間、許可權、所有者資訊
- -f 如果分散式文件系統已經存在該文件,則覆蓋
- -l 允許DataNode延遲持久化該文件,replication factor 是1. 也即這種方式不會要去數據馬上落地和寫副本,具有丟數據的風險,但是寫入速度可能會很快
- -d 文件複製過程中,將不會創建後綴為
._COPYING_
格式的文件
copyToLocal
將分散式文件系統中的文件拷貝到本地
count
同進指定路徑的文件、文件夾個數、當前文件佔用量大小、指定路徑允許創建的文件、文件夾個數,以及允許的最大文件、文件容量
用法:hadoop fs -count [-q] [-h] [-v] [-x] [-t [<storage type>]] [-u] [-e] <paths>
如果只用quota,而不加任何以下且與參數,則輸出的統計項有
DIR_COUNT(當前路徑的文件夾個數), FILE_COUNT(文件個數), CONTENT_SIZE(容量佔用大小), PATHNAME(當前統計的路徑)
- -h 將容量以人方便讀的方式展示,建議開啟
- -v 對統計的內容,輸出表頭,方便用戶知道統計中某列是什麼含義,建議開啟
- -q 代表quota, 能夠統計出指定路徑的name quota和space quota。 輸出的列有
QUOTA(總的name quota的大小), REMAINING_QUOTA(還剩name quota的大小), SPACE_QUOTA(space quota的大小), REMAINING_SPACE_QUOTA(還剩的space quota的大小), DIR_COUNT, FILE_COUNT, CONTENT_SIZE, PATHNAME
- -u 跟-q一樣,也是統計容量配合總計和剩餘配合,只是不再輸出-count默認的那些項。-u的輸出列為:
QUOTA, REMAINING_QUOTA, SPACE_QUOTA, REMAINING_SPACE_QUOTA, PATHNAME
- -e hadoop3.0引入的,文件擦除策略,需要再查資料解讀
demo舉例
hadoop fs -count hdfs://nn1.example.com/file1 hdfs://nn2.example.com/file2
hadoop fs -count -q hdfs://nn1.example.com/file1
hadoop fs -count -q -h hdfs://nn1.example.com/file1
hadoop fs -count -q -h -v hdfs://nn1.example.com/file1
hadoop fs -count -u hdfs://nn1.example.com/file1
hadoop fs -count -u -h hdfs://nn1.example.com/file1
hadoop fs -count -u -h -v hdfs://nn1.example.com/file1
hadoop fs -count -e hdfs://nn1.example.com/file1
對於quota(配額)的說明:
- name quota 以指定路徑做為根路徑的整顆文件樹上允許創建的文件、文件夾名稱的總體個數
- space quota 以指定路徑做為根路徑的整顆文件樹上允許創建的文件、文件夾的總體位元組數
使用hadoop fs -count -q
命令查詢配合時,如果配額沒有設置,會顯示none
或inf
可以使用hdfs dfsadmin
命令對某個指定路徑設置配額
cp
將一個文件或多個文件拷貝到另一個地方。
拷貝當個文件時,目的地可以是另一個文件,也可以是文件夾
拷貝多個文件時,目的地必須是文件夾
用法:hadoop fs -cp [-f] [-p | -p[topax]] URI [URI ...] <dest>
- -f參數加上時,目的地有該文件,則會將其覆蓋
df
查詢某個指定路徑的剩餘容量
用法:hadoop fs -df [-h] URI [URI …]
- -h是人可讀的形式
df是看的整個文件系統的使用情況和可用空間
而-count是計算指定目錄的空間佔用情況,以及管理員給分配的配合使用情況
du
查看指定路徑的文件和文件夾大小匯總
find
查找指定路徑下,名字滿足表達式的文件,並列印到終端
hadoop fs -find / -name test -print
-name 對文件名大小寫敏感
-iname 文件名大小寫不敏感
get
將hdfs中的文件拷貝到本地
getfacl
返迴文件的訪問控制列表
getfattr
將指定文件夾中的所有文件合併後,生成到目標文件中
用法:hadoop fs -getmerge [-nl] <src> <localdst>
hadoop fs -getmerge -nl /src /opt/output.txt //將src文件夾下的所有文件合併到output.txt
hadoop fs -getmerge -nl /src/file1.txt /src/file2.txt /output.txt//將file1.txt和file2.txt合併到output.txt
head
將指定文件頭一千行數據輸出到終端
hadoop fs -head pathname
tail
將指定文件尾部一千行數據輸出到終端
hadoop fs -tail [-f] URI
help
hadoop fs -help
所有fs命令的幫助手冊
usage
hadoop fs -usage command 查看單個命令的使用手冊
truncate
刪減指定文件的指定行數
touchz
創建一個文件,就像Linux的touch命令
hadoop fs -touchz pathname
touch
不存在則創建文件,存在則更新文件的更新時間
text
以文本形式輸出一個指定文件
test
測試指定路徑是否存在,是否是文件或文件夾
setrep
設置文件或文件夾的副本數。如果是文件夾,則會將該文件夾下的所有文件副本數一併設置
hadoop fs -setrep -w 3 /user/hadoop/dir1
- -w表示命令是否等待所有操作完成
setfattr
對指定文件設置附加屬性。一個文件固有的屬性有其Permission,和modifytime。用戶可以選擇添加一些附加屬性
setfacl
設置指定文件或文件夾的訪問控制列表
rmdir 刪除一個文件夾
hadoop fs -rmdir /user/hadoop/emptydir
rm
刪除一個指定文件。如果回收垃圾桶功能有的話,刪除操作會將將文件移動到垃圾桶trash
hadoop fs -rm hdfs://nn.example.com/file /user/hadoop/emptydir
put
將本地的一個或多個文件複製到分散式文件系統中的指定路徑
hadoop fs -put localfile /user/hadoop/hadoopfile
hadoop fs -put -f localfile1 localfile2 /user/hadoop/hadoopdir
hadoop fs -put -d localfile hdfs://nn.example.com/hadoop/hadoopfile
hadoop fs -put - hdfs://nn.example.com/hadoop/hadoopfile Reads the input from stdin.
moveFromLocal
將本地文件移動到文件系統,注意是移動,移動後,本地文件將被刪除
hadoop fs -moveFromLocal <localsrc> <dst>
mv
文件移動,要是移動多個文件的話,目的地必須為一個文件夾
hadoop fs -mv /user/hadoop/file1 /user/hadoop/file2
hadoop fs -mv hdfs://nn.example.com/file1 hdfs://nn.example.com/file2 hdfs://nn.example.com/file3 hdfs://nn.example.com/dir1
mkdir
創建文件夾
用法:hadoop fs -mkdir [-p] <paths>
- -p參數表示文件夾的父文件夾也會被創建
hadoop fs -mkdir /user/hadoop/dir1 /user/hadoop/dir2
hadoop fs -mkdir hdfs://nn1.example.com/user/hadoop/dir hdfs://nn2.example.com/user/hadoop/dir
ls
用法:hadoop fs -ls [-C] [-d] [-h] [-q] [-R] [-t] [-S] [-r] [-u] [-e] <args>
參數列表如下
-C: Display the paths of files and directories only.
-d: Directories are listed as plain files.
-h: Format file sizes in a human-readable fashion (eg 64.0m instead of 67108864).
-q: Print ? instead of non-printable characters.
-R: Recursively list subdirectories encountered.
-t: Sort output by modification time (most recent first).
-S: Sort output by file size.
-r: Reverse the sort order.
-u: Use access time rather than modification time for display and sorting.
-e: Display the erasure coding policy of files and directories only.
HDFS基本知識
HDFS是一個分散式文件系統。其中有兩種類型的組件
- name node, 管理整個系統的文件目錄,以及每個其下的每個文件有多少個塊block,他們存儲的機器,以及副本位置。
- data node,實際的數據存儲節點。數據的直接讀寫,都是在這上面進行的
HDFS Snapshots
HDFS Snapshots用來做數據備份,或者災難恢復。
HDFS Snapshots創建的耗時很低,幾乎是瞬間創建。
之所以快的原因是,集群沒有數據移動。
Snapshots創建後,只記錄其對應真實文件路徑下發生的變化。
當你要恢複數據時,hdfs是通過當前的數據減去Snapshots記錄的至snapshot創建以來,發生變化的數據,就等於snapshot備份初始時,對應的數據狀態。
這個思想很棒,創建備份很快的同時,備份所要求的存儲空間也很少
Snapshots的創建
一個文件夾想要使用Snapshots備份,首先該文件夾需要被設置成snapshottable(可備份)
hdfs dfsadmin -allowSnapshot <path>
然後對該文件夾創建備份
hdfs dfs -createSnapshot <path> [<snapshotName>]
- path為可備份的文件夾路徑
- snapshotName 為備份文件的名字,可以不填,默認為
's'yyyyMMdd-HHmmss.SSS
格式的命名
創建備份後,備份本身放在在備份文件夾下的.snapshot
文件夾內
Snapshots的使用
比如現在有個文件夾/foo/bar
我對foo文件夾創建一個備份s0, 那麼該備份的路徑為/foo/.snapshot/s0
我要查看所有foo的所有備份
hdfs dfs -ls /foo/.snapshot
查找備份中的文件
hdfs dfs -ls /foo/.snapshot/s0
將備份中的文件恢復到某個目錄
hdfs dfs -cp -ptopax /foo/.snapshot/s0/bar /tmp
數據複寫
hdfs中存儲的文件都很大,所以一個大文件,會被拆分成很多block. 而為了保證數據的可靠性,這些block會被以副本形式存放在多個data node.
該圖上半部分,顯示的是文件在Namenode中存儲的元數據資訊,其中包含了(以第一行為例)
- 文件名
/users/sameerp/data/part-0
- 文件塊利弊 block-ids (1,3),表示該文件有兩個塊
- 文件塊副本個數 r:2 ,表示每個塊會被存儲兩份
該圖下半部分,則是上半部分描述的兩個文件,在datanode中的實際存儲情況,可以看到第二個文件有三個快,並且每個塊有三個副本
副本的存放機制
一個大的HDFS集群,往往跨多個機架的伺服器。如果副本放一個機架,那這個機架掛了,數據就全無法訪問。如果副本分散到多個機架,那麼每次寫數據會很慢,並且會佔用大量跨機架的頻寬,且一般跨機架頻寬,沒有機架內的頻寬大。
所以副本策略需要權衡上述兩點,實現數據的可靠性存儲的同時,能保證讀寫性能。
namenode通過Hadoop Rack Awareness機制,去獲知每個datanode 對應的機架。
如果副本為3的話,且有多個機架的話,hdfs的會將兩個副本放在同一個機架上,另一個放在另外一個機架。這樣保證多數副本處於同一機架,提高讀寫速度。而單獨放置一個機架的副本,能保證前一個機架掛掉後,集群的高可用
如果副本超過4個的話,hdfs會隨機的找另外的機架來放,最終保證每個機架上的副本小於等於(replicas - 1) / racks + 2)
hdfs不會允許一個block的多個副本放在同一個datanode
副本的讀取機制
hdfs會採用就近原則,來保證讀取的高效性。就近是指看跟讀取客戶端相近
安全模式
hdfs剛啟動時,出於安全模式,在該模式下,集群不會發生數據複製的行為。namenode會接收,datanode發送來的數據block的情況(這被稱為block report,由datanode主動上報),並進行檢查。當一個在多個datanode上的同一個bock副本存活數,達到指定的最小副本數時,該block才被認為是安全可用的。當整個集群的可用block數達到一定百分比時,HDFS才認為集群可用,退出安全模式,並把安全檢查過程中發現的不安全的block,replication其副本到其它可用的datanode ,從而實現集群整體的高可用。
文件系統元數據的持久化
- fsImage namenode中,存放了文件系統命名空間和block對應datanode映射關係數據的文件叫 fsImage, 他是一個物理機文件,存放在namenode對應的宿主作業系統中
- EditLog 我們對文件系統每一次修改,如果直接在fsImage上進行,效率會很低,因為fsImage會很大。所以namenode中還有一個文件叫EditLog,專門記錄我們對文件系統的修改
- checkpoint EditLog總有要在一個時間點,將數據合併到fsImage中,這個點叫checkpoint 。 這個時間點可以是指定的時間間隔到了
dfs.namenode.checkpoint.period
,或者EditLog積累了指定的變更事務數dfs.namenode.checkpoint.txns
。當合併後,editLog將被刪除 - fsImage和Editlog的記憶體存放 我們要查找一個文件系統資訊,如果到硬碟上找fsImage和EditLog,勢必會很慢,所以當NameNode啟動時,或checkpoint發生時,namenode會將fsImage和Editlog載入到記憶體
- 查詢順序 顯然我們要查一個文件系統時,會先去editlog中找,然後去fsImage,由於editLog和fsImage本身會先落盤,我們也不用擔心對文件系統的操作丟失
通訊協議
hdfs節點間通訊協議是架設在tcp/ip上的,namenode只響應客戶端或datanode發送的請求,namenode不會主動的發起任何請求
健壯性
被動健壯性
namenode會基於datanode上報的心跳,blockreport去及時的把不可用的datanode下線,並有必要的增加將副本數不足的block副本
主動健壯性
- 往hdfs中文件的時候,存一份chcksum, 讀文件時,校驗checksum
- fsImage和editLog非常重要,即便寫磁碟,都有可能損壞,為了保證其可用性,多寫幾個副本
- namenode本身配置高可用
- 定時使用snapshot備份集群數據,使得數據可恢復
數據的組織
hdfs中將文件默認拆分為 128 MB的block
當像hdfs中寫一個需副本文件時,namenode首選選取一組datanode給到客戶端,客戶端將數據寫第一個datanode, 第一個datanode寫完後,將該數據分發給第二個datanode ,依次類推,像一個鏈式管道
數據的訪問
支援以命令、api、web瀏覽器的方式訪問hdfs文件系統
空間回收
以下兩種回收方式,都是有一定延遲的,不是操作後,就能看到多出的空間。
刪除文件
如果垃圾桶功能開啟後,刪除的文件會先到/user/<username>/.Trash
,每個用戶都有一個自己的垃圾桶。
用戶最近刪除的文件在/user/<username>/.Trash/Current
中
當到了一定時間後,垃圾桶中的文件會被徹底刪除。這個時候,hdfs會真正回收這部分空間
減少副本
將副本個數減少,也會促使集群回收對應文件的空間
editLog和fsImage的高可用
namenode存儲了整個分散式文件系統的資訊,它一旦數據丟失,那麼整個hdfs相當於文件丟失。
而namenode的文件系統實際存儲,依賴editLog和fsImage兩個文件,所以保證namenode的數據不丟失,關鍵就是要保證editLog和fsImage兩個文件的不丟失。下述三種Node,就是在做這個事情
Secondary NameNode
前面講namenode的editLog和fsImage的合併,只會在namenode啟動時進行。這樣到namenode下次啟動時,可能editlog已經非常大了,合併會很耗時。Secondary NameNode就是用來去name node上拉取editLog和fsImage,然後進行合併。然後對namenode文件系統查詢,會路由到secondary NameNode上
- checkpoint1 定時
dfs.namenode.checkpoint.period
- checkpoint2 事務數
dfs.namenode.checkpoint.txns
當然Secondary NameNode,只是做editLog和FsImage的合併,並提供查詢副本,他不並不能完全替代namenode工作。也即在Namenode掛後,集群是不可用的
Checkpoint Node
同Checkpoint Node功能類似,要去namenode上拉取,editlog和fsImage ,只是checkpoint node會將合併後的內容,上傳至Namenode。這樣Namenode 不至於去查checkpoint node
Backup Node
同Secondary NameNode和Checkpoint Node不一樣,他不會用每次都去namenode拉取editLog和fsImage。其本身就會以物理落盤的方式,存儲editLog和fsImage。由於這個特點,nameNode在啟動時,可以使用-importCheckpoint 選項,是的Namenode本身不存儲editLog和fsImage,轉而將所有將所有的存儲,代理給backup node
下下策Recovery Mode
如果editLog和fsImage實在丟失了,請用Recovery Mode
HDFS高可用HA
前面的Secondary NameNode、Checkpoint Node,Backup Node,都只是為了以某種形式備份editLog和fsImage數據。真正NameNode掛了後,集群還是需要人工干預。
這裡介紹整個NameNode的高可用方式。(再次強調Secondary NameNode並不是HA,這個命名讓人容易誤解)
正在的高可用HA需要實現兩個方面
- editLog和fsImage文件不會出現單點故障丟失
- namenode本身不會出現單點故障,掛掉後,能快速有備選的namenode起來幹活
兩種HA模式
兩種HA模式在namenode實例高可用上,都依賴zookeeper實現。只是在保證editLog和fsImage的高可用和一致性上有差異
- 使用Quorum Journal Manager,依託三個Journal Manager實例,去保證editLog和fsImage的在多個namenode之間的分散式一致性同步。
- 使用NFS,讓多個namenode讀寫editLog和fsImage的實際存儲在NFS,也即網路共享文件系統中,使得兩個namenode能夠共享editLog和fsImage數據。一般的NFS可選擇NAS。
使用上述HA中的任意一種,我們都可以不再配置Secondary NameNode、Checkpoint Node,Backup Node
以下主要介紹基於Quorum Journal Manager的高可用
通過Journal Manager實現HA
從上可以看到。為了保證fsImage和Editlog的高可用。每次namenode在發生文件系統變更時,會將其寫到Journal Manager(後續簡稱JM),JM想Zookeeper一樣,會部署奇數個節點,只有想JM半數以上的節點寫editLog和fsImage成功後,才算成功。
使用zookeeper保證主namenode掛後,standby的namenode能夠快速成為主namenode.
zookeeper本身在寫數據時,也是半數成功才算成功,為什麼不用用zookeeper一併代理JM 來存儲editLog和fsImage呢。因為editLog和fsImage的文件可能很大,zookeeper本身適合做輕量級的元數據管理,不適合做這個
配置部署
以下各種組件部署,最好使用不同的linux用戶。hadoop官方推薦的用戶跟Hadoop組件的對應關係為
配置Journal Manager
主要配置
hdfs-site.xml
如果將多個Namenode整體看做一個分散式服務的話,首先要給這個service取個名字
<property>
<name>dfs.nameservices</name>
<value>mycluster</value>
</property>
將其對應的一組namenode的聲明id
<property>
<name>dfs.ha.namenodes.mycluster</name>
<value>nn1,nn2, nn3</value>
</property>
配置namenode id對應的具體機器埠資訊
<property>
<name>dfs.namenode.rpc-address.mycluster.nn1</name>
<value>machine1.example.com:8020</value>
</property>
<property>
<name>dfs.namenode.rpc-address.mycluster.nn2</name>
<value>machine2.example.com:8020</value>
</property>
<property>
<name>dfs.namenode.rpc-address.mycluster.nn3</name>
<value>machine3.example.com:8020</value>
</property>
配置這組namenode,對應的http地址、埠資訊
<property>
<name>dfs.namenode.http-address.mycluster.nn1</name>
<value>machine1.example.com:9870</value>
</property>
<property>
<name>dfs.namenode.http-address.mycluster.nn2</name>
<value>machine2.example.com:9870</value>
</property>
<property>
<name>dfs.namenode.http-address.mycluster.nn3</name>
<value>machine3.example.com:9870</value>
</property>
配置journalnode存儲editLog和fsImage文件的路徑
<property>
<name>dfs.journalnode.edits.dir</name>
<value>/path/to/journal/node/local/data</value>
</property>
配置多台JournalNode組成的服務連接地址,他們相當於組成了一個分散式的文件目錄
<property>
<name>dfs.namenode.shared.edits.dir</name>
<value>qjournal://node1.example.com:8485;node2.example.com:8485;node3.example.com:8485/mycluster</value>
</property>
為了防止腦裂致使多個Namenode都在寫數據,可以配置一些當出現腦裂時,去殺死Namenode進程的命令,如果默認不指定命令,也需要做shell(/bin/true)。他的實現原理是,standby的namenode,準備成為active時,先通過ssh登錄到原來的active namenode 的機器上,嘗試以命令的形式殺死原來的namenode進程,保證自己啟動起來不出現腦裂。所以這一步的關鍵配置是多個namenode之前,要實現ssh免密登錄。ssh免密登錄的配置參考://www.cnblogs.com/niceshot/p/13019823.html
<property>
<name>dfs.ha.fencing.methods</name>
<value>sshfence shell(/bin/true)</value>
</property>
<property>
<name>dfs.ha.fencing.ssh.private-key-files</name>
<value>/home/vagrant/.ssh/id_rsa</value>
</property>
<property>
<name>dfs.ha.fencing.ssh.connect-timeout</name>
<value>30000</value>
</property>
還可以配置客戶端連接namenode時,出現故障的轉移策略
<property>
<name>dfs.client.failover.proxy.provider.mycluster</name>
<value>org.apache.hadoop.hdfs.server.namenode.ha.ConfiguredFailoverProxyProvider</value>
</property>
配置自動故障轉移
上述所有配置,能保證editLog和fsImage文件不丟。但nameNode掛後,還是需要通過haadmin
命令手動干預去啟動新備選nameNode。
下面的一系列配置用來使用zookeeper實現namenode的自動故障轉移
首先啟動自動轉移開關
在hdfs-site.xml 中配置
<property>
<name>dfs.ha.automatic-failover.enabled</name>
<value>true</value>
</property>
在core-site.xml 配置zk的鏈接資訊
<property>
<name>ha.zookeeper.quorum</name>
<value>zk1.example.com:2181,zk2.example.com:2181,zk3.example.com:2181</value>
</property>
<property>
<name>fs.defaultFS</name>
<value>hdfs://mycluster</value>
</property>
完成啟動部署
先啟動所有的JournalNodes
./hdfs --daemon start journalnode
初始化主namenode
//如果集群是新集群
hdfs namenode -format
//如果是對已經存在很久的集群,進行高可用改造,下面的命令,是把已經存在的editLog和fsImage數據同步到journalnode
hdfs namenode -initializeSharedEdits
啟動主namenode
./hdfs --daemon start namenode
初始化從namenode
hdfs namenode -bootstrapStandby
啟動從namenode
sbin/hadoop-daemon.sh start namenode
在namenode所在機器,執行下述命令,初始化其在zk的節點資訊
$HADOOP_HOME/bin/hdfs zkfc -formatZK
在所有namenode所在機器上啟動zkfc進程
$HADOOP_HOME/bin/hdfs --daemon start zkfc
上述所有的這些命令中的初始化動作,只在第一次配置HA時需要。後續通過 start-dfs.sh 就可以直接啟動所有相關實例
hadoop集群的升級回滾
對DataNode添加、更換磁碟
//hadoop.apache.org/docs/stable/hadoop-project-dist/hadoop-hdfs/HdfsUserGuide.html
Hadoop Rack Awareness
是一些列配置,是的hadoop集群能夠感知到當前集群的機架情況,從而應用到副本分布策略中,以提高數據的高可用。
需要在hadoop的xml中配置基於域名或ip查找機架id的實現類。實現類必須繼承org.apache.hadoop.net.DNSToSwitchMapping
介面。
實現類通過net.topology.node.switch.mapping.impl
進行配置,默認的實現為org.apache.hadoop.net.ScriptBasedMapping
ScriptBasedMapping會去調用腳本,來獲取所在集群的機架資訊,具體的所調的腳本通過net.topology.script.file.name
來配置,該配置沒有默認值。
hadoop文檔中有實現樣例,可參考
hdfs整個集群相關命令
//hadoop.apache.org/docs/stable/hadoop-project-dist/hadoop-hdfs/HDFSCommands.html
參考資料
//hadoop.apache.org/docs/stable/hadoop-project-dist/hadoop-common/RackAwareness.html
集群監控要點
- ZKFC 監控ZKFC是否ok
- 監控zookeeper狀態
安裝部署要點
zookeeper的安裝
建議的安裝方式,zookeeper三個節點分別放Namenode、standyNamenode、ResourceManager這三台機器上。
zookeeper自己的文件目錄所在磁碟,同hdfs namenode所在磁碟分開
高效能集群啟停
hdfs本身由多個組件組成,且有些組件還有多個節點,比如journalnode, datanode,一次啟動去到多個機器上執行是件很繁瑣的事情。hadoop髮型包,提供了sbin/start-dfs.sh
和 sbin/stop-dfs.sh
兩個腳本去啟停hdfs相關的所有組件:比如namenode、datanode、journalnode, zkfc 。
他實現的原理是,基於hadoop安裝包中的/opt/hadoop-3.2.1/etc/hadoop/workers文件,去登錄到相應的機器,完成組件的執行。workers中定義了所有datanode的機器host。 登錄方式是基於SSH的免密登錄方式,具體配置參見://www.cnblogs.com/niceshot/p/13019823.html
如果發起腳本執行的機器,本身也需要部署一個datanode。那麼他需要配置自己對自己的SSH免密登錄
通過core-site.xml和hdfs-site.xml , 腳本已經可以知道namenode, Journalnode,Zkfc的組件機器。所以workers文件中,只需要設置所有的datanode的機器host。
hdfs許可權控制
同linux許可權的比較
hdfs的許可權模型,同linux類似,只是去掉了setuid和setgid兩位。也支援acl,stickybit位。但同linux不同的是,hdfs本身只管理文件的許可權控制。並沒有帳號體系,比如像linux一樣有/etc/passwd存儲所有的用戶列表。也即hdfs只提供文件許可權控制。並不提供用戶管理和認證管理,這兩者都交由外部系統來實現。linux許可權模型參考資料
//www.cnblogs.com/niceshot/p/12901539.html
誰是管理員
誰啟動的namenode ,那啟動namenode進程的用戶,就是namenode 的管理員。所以namenode的管理員是會變化的,下次換個linux用戶啟動,就會導致變化
怎麼找當前操作的用戶
通過hadoop.security.authentication
配置,操作用戶識別機制,有以下兩種
simple
使用發起操作的宿主機中,當前發起操作的用戶,作為本次請求hdfs的用戶。比如當前發起hdfs dfs -ls
命令的是linux的ops用戶,那麼hdfs後續的許可權控制都會基於ops用戶去判斷。判斷其是否有指定路徑的讀許可權
kerberos
在kerberos的配置文件中配置,auth_to_local是一個principal訪問某個service時,這個service雖然知道這個Principal是KDC認證過的合法用戶
但授權怎麼做,該Principal具有什麼樣的許可權?這個需要service自己來做。
一般linux自己的授權控制是通過posix模式,加ACL的方式進行的。本質來講,都是針對當前linux本身的用戶進行授權。
比如owner,group,others,分別定義他們能做什麼和不能做什麼。
所以部署在Linux上的service,往往需要將請求過來的principal映射成本地的用戶,然後對本地的用戶進行授權檢測。這麼一看,auth_to_local這個命名還是比較直白的
auth_to_local = {
RULE:[2:\(1](johndoe)s/^.*\)/guest/
RULE:[2:$1;\(2](^.*;admin\))s/;admin$//
RULE:[2:\(2](^.*;root)s/^.*\)/root/
DEFAULT
}
}
上述這個demo配置,其實就是將johndoe/* 形式的principal會被映射成本地的guest用戶,而形如*/[email protected] 的principal會被映射成本地的admin帳號
怎麼找到指定用戶的組
上述方式只是找到操作對應的用戶。如果操作的用戶不是對應文件、文件夾的owner, 那麼需要判斷該用戶是否擁有指定文件、文件夾的組許可權。
那首先,我們要知道該用戶的有哪些組,以便讓hdfs知道,該用戶是否在文件所屬組中,如果文件所屬組,在用戶的組列表中,說明該用戶擁有文件的組許可權。
那麼怎麼找到用戶所屬的組列表呢?
配置hadoop.security.group.mapping
具體的mapping來找,可以配置的mapping有
- org.apache.hadoop.security.JniBasedUnixGroupsMappingWithFallback
- org.apache.hadoop.security.JniBasedUnixGroupsNetgroupMappingWithFallback
- org.apache.hadoop.security.ShellBasedUnixGroupsMapping
- org.apache.hadoop.security.ShellBasedUnixGroupsNetgroupMapping
- org.apache.hadoop.security.LdapGroupsMapping
- org.apache.hadoop.security.CompositeGroupsMapping
具體每個mapping的mapping策略,可看文檔和具體的hadoop源碼實現://hadoop.apache.org/docs/stable/hadoop-project-dist/hadoop-common/GroupsMapping.html#Composite_Groups_Mapping
靜態mapping
還可以通過 hadoop.user.group.static.mapping.overrides
來靜態指定一個用戶對應的group list。 如果一個用戶在靜態mapping中找到對應的組,就不會走上述的動態mapping
hadoop整體的安全模式
kerberos認證
採用kerberos作為hadoop各組件之間的許可權認證。首先在部署的時候,將hadoop的各組件採用不同的linux用戶和組進行部署。
hdfs文件系統,推薦的posix許可權限制
配置core-site.xml
配置如何映射一個用戶
配置整個集群啟用kerberos許可權認證。其中auth_to_local表示,當有其它組件請求當前服務時,如何將其映射成為本地的用戶某個用戶。一個demo配置為
<property>
<name>hadoop.security.auth_to_local</name>
<value>
RULE:[2:$1/$2@$0]([ndj]n/.*@REALM.\TLD)s/.*/hdfs/
RULE:[2:$1/$2@$0]([rn]m/.*@REALM\.TLD)s/.*/yarn/
RULE:[2:$1/$2@$0](jhs/.*@REALM\.TLD)s/.*/mapred/
DEFAULT
</value>
</property>
其中,來至於namenode、datanode、journal node的請求,會被映射成為hdfs用戶
來至於resource manger、node manager的請求,會被映射成本地的yarn用戶
來至於job history server的請求,會被映射成為mapred用戶
配置如何知道一個用戶對應的分組
文檔前面有提到,有哪幾種基於用戶找到分組的方式。一般配安全集群,都會跟公司的LDAP整合起來,這裡就以使用LDAP來找組為例看配置
<property>
<name>hadoop.security.group.mapping.ldap.url</name>
<value>ldap://server1,ldap://server2,ldap://server3</value>
<description>
The URL of the LDAP server(s) to use for resolving user groups when using
the LdapGroupsMapping user to group mapping. Supports configuring multiple
LDAP servers via a comma-separated list.
</description>
</property>
<property>
<name>hadoop.security.group.mapping.ldap.num.attempts</name>
<value>6</value>
<description>
This property is the number of attempts to be made for LDAP operations.
If this limit is exceeded, LdapGroupsMapping will return an empty
group list.
</description>
</property>
<property>
<name>hadoop.security.group.mapping.ldap.num.attempts.before.failover</name>
<value>2</value>
<description>
This property is the number of attempts to be made for LDAP operations
using a single LDAP instance. If multiple LDAP servers are configured
and this number of failed operations is reached, we will switch to the
next LDAP server. The configuration for the overall number of attempts
will still be respected, failover will thus be performed only if this
property is less than hadoop.security.group.mapping.ldap.num.attempts.
</description>
</property>
配置各組件自己的配置文件比如hdfs-site.xml , yarn-site.xml , mapred-site.xml
前面是配置整個集群服務,再接受到請求後,怎麼辨別這個請求是哪個用戶的,該用戶屬於哪個組的。而這裡的配置,主要用來指定該組件自己的憑證文件也即kerberos的keytab存在什麼地方,以及使用其中哪個principal作為當前組件的principal(一個keytab文件中,可以存儲多個principal的認證資訊)
下面以namenode為例,看其需要的配置
其餘各組件的相關配置大體類似。參考鏈接:
//hadoop.apache.org/docs/stable/hadoop-project-dist/hadoop-common/SecureMode.html
授權
kerberos只是提供集群互訪的認證,具體到認證用戶的授權,又得單獨配置。hadoop自己支援在 $HADOOP_CONF_DIR下配置hadoop-policy.xml文件來指定訪問控制列表,實現授權控制。 而我們準備使用ranger來做授權控制,所以這裡不再對這種方式贅述
一些錯誤
錯誤1
在某台機器上,以命令行查詢文件系統是報錯-ls: java.net.UnknownHostException: 具體的集群名稱
這個錯誤是由於對應的機器上的hdfs-site.xml高可用配置沒有配置連接namenode失敗後的失敗策略。
解決辦法是在該機器的hdfs-site.xml中加入對應配置
<property>
<name>dfs.client.failover.proxy.provider.haixue-hadoop</name>
<value>org.apache.hadoop.hdfs.server.namenode.ha.ConfiguredFailoverProxyProvider</value>
</property>
重啟該機器的組件,如果該機器只有datanode,那重啟datanode即可
一些冷門知識
如何將hdfs做成任意路徑敲擊皆可執行的命令
update-alternatives --install \
/usr/bin/hdfs \
hdfs \
/opt/hadoop-3.2.1/bin/hdfs \
100
hdfs相關文檔
datanode 的管理
可以將指定datanode進行下線,維護
//hadoop.apache.org/docs/stable/hadoop-project-dist/hadoop-hdfs/HdfsDataNodeAdminGuide.html
使用Erasure Coding對存儲進行優化
有些冷門的數據,存三個副本,有些浪費
//hadoop.apache.org/docs/stable/hadoop-project-dist/hadoop-hdfs/HDFSErasureCoding.html
對namenode性能進行壓測Synthetic Load Generator
//hadoop.apache.org/docs/stable/hadoop-project-dist/hadoop-hdfs/SLGUserGuide.html
將數據寫入暫存記憶體,提高數據寫入速度
數據寫入記憶體,再非同步寫磁碟,有丟數據的風險
//hadoop.apache.org/docs/stable/hadoop-project-dist/hadoop-hdfs/MemoryStorage.html
Centralized Cache Management in HDFS
讓datanode快取部分熱數據,來提升數據讀取速度
//hadoop.apache.org/docs/stable/hadoop-project-dist/hadoop-hdfs/CentralizedCacheManagement.html
hdfs的兩種web訪問方式
- HttpFS 單獨搭一套web server,http請求打到它,他再去代理到hdfs。httpFs是單點,讀寫性能會瓶頸在這個單點
- WebHDFS hdfs namenode內置的訪問服務,實際訪問是直接達到某台具體的datanode,沒有性能瓶頸,具體缺點再調研
怎麼知道一個具體的配置該放到哪個xml
hadoop的文檔左側,有一個configuration 列表,其中有所有配置項對應的xml,以及其默認值和釋義
參考資料
//hadoop.apache.org/docs/stable/hadoop-project-dist/hadoop-common/ClusterSetup.html
//data-flair.training/blogs/hadoop-hdfs-namenode-high-availability/
歡迎關注我的個人公眾號”西北偏北UP”,記錄程式碼人生,行業思考,科技評論