Hadoop學習筆記—HDFS

西北偏北UP 發表於 2021-04-03
Hadoop

目錄

上一份工作主要負責大資料平臺的建設,在這個過程中積累了一些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的字尾有

file

比如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上執行

命令

文件地址:https://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

file

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 命令查詢配合時,如果配額沒有設定,會顯示noneinf
可以使用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

將指定檔案頭一千行資料輸出到終端
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,實際的資料儲存節點。資料的直接讀寫,都是在這上面進行的
    file

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.
file

該圖上半部分,顯示的是檔案在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副本

主動健壯性

  1. 往hdfs中檔案的時候,存一份chcksum, 讀檔案時,校驗checksum
  2. fsImage和editLog非常重要,即便寫磁碟,都有可能損壞,為了保證其可用性,多寫幾個副本
  3. namenode本身配置高可用
  4. 定時使用snapshot備份叢集資料,使得資料可恢復

資料的組織

hdfs中將檔案預設拆分為 128 MB的block

當像hdfs中寫一個需副本檔案時,namenode首選選取一組datanode給到客戶端,客戶端將資料寫第一個datanode, 第一個datanode寫完後,將該資料分發給第二個datanode ,依次類推,像一個鏈式管道

資料的訪問

支援以命令、api、web瀏覽器的方式訪問hdfs檔案系統

空間回收

以下兩種回收方式,都是有一定延遲的,不是操作後,就能看到多出的空間。

刪除檔案

如果垃圾桶功能開啟後,刪除的檔案會先到/user/<username>/.Trash,每個使用者都有一個自己的垃圾桶。
使用者最近刪除的檔案在/user/<username>/.Trash/Current

當到了一定時間後,垃圾桶中的檔案會被徹底刪除。這個時候,hdfs會真正回收這部分空間

減少副本

將副本個數減少,也會促使叢集回收對應檔案的空間

editLog和fsImage的高可用

https://hadoop.apache.org/docs/stable/hadoop-project-dist/hadoop-hdfs/HdfsUserGuide.html#Secondary_NameNode

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

file
從上可以看到。為了保證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元件的對應關係為
file

配置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免密登入的配置參考:https://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叢集的升級回滾

https://hadoop.apache.org/docs/stable/hadoop-project-dist/hadoop-hdfs/HdfsUserGuide.html#Secondary_NameNode

對DataNode新增、更換磁碟

image.png
https://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整個叢集相關命令

https://hadoop.apache.org/docs/stable/hadoop-project-dist/hadoop-hdfs/HDFSCommands.html

參考資料
https://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.shsbin/stop-dfs.sh兩個指令碼去啟停hdfs相關的所有元件:比如namenode、datanode、journalnode, zkfc 。

他實現的原理是,基於hadoop安裝包中的/opt/hadoop-3.2.1/etc/hadoop/workers檔案,去登入到相應的機器,完成元件的執行。workers中定義了所有datanode的機器host。 登入方式是基於SSH的免密登入方式,具體配置參見:https://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許可權模型參考資料
https://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賬號

https://ssimo.org/blog/id_016.html

怎麼找到指定使用者的組

上述方式只是找到操作對應的使用者。如果操作的使用者不是對應檔案、資料夾的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原始碼實現:https://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使用者和組進行部署。
file

hdfs檔案系統,推薦的posix許可權限制
file

配置core-site.xml

配置如何對映一個使用者

file

配置整個叢集啟用kerberos許可權認證。其中auth_to_local表示,當有其它元件請求當前服務時,如何將其對映成為本地的使用者某個使用者。一個demo配置為

<property>
  <name>hadoop.security.auth_to_local</name>
  <value>
    RULE:[2:$1/[email protected]$0]([ndj]n/.*@REALM.\TLD)s/.*/hdfs/
    RULE:[2:$1/[email protected]$0]([rn]m/.*@REALM\.TLD)s/.*/yarn/
    RULE:[2:$1/[email protected]$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為例,看其需要的配置
file
其餘各元件的相關配置大體類似。參考連結:
https://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進行下線,維護
https://hadoop.apache.org/docs/stable/hadoop-project-dist/hadoop-hdfs/HdfsDataNodeAdminGuide.html

使用Erasure Coding對儲存進行優化

有些冷門的資料,存三個副本,有些浪費
https://hadoop.apache.org/docs/stable/hadoop-project-dist/hadoop-hdfs/HDFSErasureCoding.html

對namenode效能進行壓測Synthetic Load Generator

https://hadoop.apache.org/docs/stable/hadoop-project-dist/hadoop-hdfs/SLGUserGuide.html

將資料寫入暫存記憶體,提高資料寫入速度

資料寫入記憶體,再非同步寫磁碟,有丟資料的風險
https://hadoop.apache.org/docs/stable/hadoop-project-dist/hadoop-hdfs/MemoryStorage.html

Centralized Cache Management in HDFS

讓datanode快取部分熱資料,來提升資料讀取速度
https://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

file
hadoop的文件左側,有一個configuration 列表,其中有所有配置項對應的xml,以及其預設值和釋義

參考資料

https://hadoop.apache.org/docs/stable/hadoop-project-dist/hadoop-common/ClusterSetup.html

https://data-flair.training/blogs/hadoop-hdfs-namenode-high-availability/

歡迎關注我的個人公眾號"西北偏北UP",記錄程式碼人生,行業思考,科技評論