• <big id="iig5e"><em id="iig5e"></em></big>

  • <big id="iig5e"><em id="iig5e"></em></big>
    <th id="iig5e"><option id="iig5e"></option></th>
    <th id="iig5e"><option id="iig5e"></option></th>
    <th id="iig5e"><video id="iig5e"></video></th>

  • 景安微信
    右側QQ聯系不上,可以加我微信
    您好,歡迎來到景安網絡!
    加盟景安
    主頁 >服務器教程 >Hadoop運行在Kubernetes平臺實踐

    Hadoop運行在Kubernetes平臺實踐


    來源:景安網絡發表日期:2018-12-17瀏覽次數:Tags:Hadoop,Kubernetes
    景安網絡專業的數據中心服務商,長期提供數據中心托管服務,私有云,互聯網解決方案,互聯網增值服務。針對工信委大力實施“萬企業上云”計劃,景安以我所能,為你而+,推出上云特惠,核心云計算產品降幅達50%!!也歡迎來聊右側qq

    Hadoop與Kubernetes就好像江湖里的兩大絕世高手,一個是成名已久的長者,至今仍然名聲遠揚,一個則是初出茅廬的青澀少年,骨骼驚奇,不走尋常路,一出手便驚詫了整個武林。Hadoop與Kubernetes之間有很深的淵源,因為都出自IT豪門——Google,只不過,后者是親兒子,正因為有大佬背書,所以Kubernetes一出山,江湖各路門派便都蜂擁而至,擁護稱王。

    不知道是因為Hadoop是干兒子的緣故還是因為“廉頗老矣”,總之,Hadoop朋友圈的后輩們如Spark、Storm等早都有了在Kubernetes上部署運行的各種資料和案例,但Hadoop卻一直游離于Kubernetes體系之外,本文我們給出Hadoop在Kubernetes上的實踐案例,以彌補這種缺憾。

    Hadoop容器化的資料不少,但Hadoop部署在Kubernetes上的資料幾乎沒有,這主要是以下幾個原因導致的:

    • 第一, Hadoop集群重度依賴DNS機制,一些組件還使用了反向域名解析,以確定集群中的節點身份,這對Hadoop在Kubernetes上的建模和運行帶來極大挑戰,需要深入了解Hadoop集群工作原理并且精通Kubernetes,才能很好解決這一難題。
    • 第二, Hadoop新的Map-Reduce計算框架Yarn的模型出現的比較晚,它的集群機制要比HDFS復雜,資料也相對較少,增加了Hadoop整體建模與遷移Kubernetes平臺的難度。
    • 第三, Hadoop與Kubernetes分別屬于兩個不同的領域,一個是傳統的大數據領域,一個是新興的容器與微服務架構領域,這兩個領域之間交集本來很小,加之Hadoop最近幾年已經失去焦點(這點從百度搜索關鍵詞就能發現),所以,沒有多少人關注和研究Hadoop在Kubernetes的部署問題,也是情理之中的事情。

    Hadoop 2.0其實是由兩套完整的集群所組成,一個是基本的HDFS文件集群,一個是YARN資源調度集群,如下圖所示:

    因此在Kubernetes建模之前,我們需要分別對這兩種集群的工作機制和運行原理做出深入的分析,下圖是HDFS集群的架構圖:

    Hadoop 運行在 Kubernetes平臺實踐

    我們看到,HDFS集群是由NameNode(Master節點)和Datanode(數據節點)等兩類節點所組成,其中,客戶端程序(Client)以及DataNode節點會訪問NameNode,因此,NameNode節點需要建模為Kubernetes Service以提供服務,以下是對應的Service定義文件:

    
    
    1. apiVersion: v1 
    2. kind: Service 
    3. metadata: 
    4. name: k8s-hadoop-master 
    5. spec: 
    6. type: NodePort 
    7. selector: 
    8. app: k8s-hadoop-master 
    9. ports: 
    10. name: rpc 
    11.   port: 9000 
    12.   targetPort: 9000 
    13. name: http 
    14.   port: 50070 
    15.   targetPort: 50070 
    16.   nodePort: 32007 

    其中,NameNode節點暴露2個服務端口:

    • 9000端口用于內部IPC通信,主要用于獲取文件的元數據
    • 50070端口用于HTTP服務,為Hadoop 的Web管理使用

    為了減少Hadoop鏡像的數量,我們構建了一個鏡像,并且通過容器的環境變量HADOOP_NODE_TYPE來區分不同的節點類型,從而啟動不同的Hadoop組件,下面是鏡像里的啟動腳本startnode.sh的內容:

    
    
    1. #!/usr/bin/env bash 
    2. sed -i "s/@HDFS_MASTER_SERVICE@/$HDFS_MASTER_SERVICE/g" $HADOOP_HOME/etc/hadoop/core-site.xml 
    3. sed -i "s/@HDOOP_YARN_MASTER@/$HDOOP_YARN_MASTER/g" $HADOOP_HOME/etc/hadoop/yarn-site.xml 
    4. yarn-master 
    5. HADOOP_NODE="${HADOOP_NODE_TYPE}" 
    6. if [ $HADOOP_NODE = "datanode" ]; then 
    7.     echo "Start DataNode ..." 
    8.     hdfs datanode  -regular 
    9.  
    10. else 
    11. if [  $HADOOP_NODE = "namenode" ]; then 
    12.     echo "Start NameNode ..." 
    13.     hdfs namenode 
    14. else 
    15.     if [ $HADOOP_NODE = "resourceman" ]; then 
    16.         echo "Start Yarn Resource Manager ..." 
    17.         yarn resourcemanager 
    18.     else 
    19.  
    20.          if [ $HADOOP_NODE = "yarnnode" ]; then 
    21.              echo "Start Yarn Resource Node  ..." 
    22.              yarn nodemanager    
    23.          else               
    24.             echo "not recoginized nodetype " 
    25.          fi 
    26.     fi 
    27. fi   
    28.  
    29. fi 

    我們注意到,啟動命令里把Hadoop配置文件(core-site.xml與yarn-site.xml)中的HDFS Master節點地址用環境變量中的參數HDFS_MASTER_SERVICE來替換,YARN Master節點地址則用HDOOP_YARN_MASTER來替換。下圖是Hadoop HDFS 2節點集群的完整建模示意圖:

    Hadoop 運行在 Kubernetes平臺實踐

    圖中的圓圈表示Pod,可以看到,Datanode并沒有建模Kubernetes Service,而是建模為獨立的Pod,這是因為Datanode并不直接被客戶端所訪問,因此無需建模Service。當Datanode運行在Pod容器里的時候,我們需要修改配置文件中的以下參數,取消DataNode節點所在主機的主機名(DNS)與對應IP地址的檢查機制:

    
    
    1. dfs.namenode.datanode.registration.ip-hostname-check=false 

    如果上述參數沒有修改,就會出現DataNode集群“分裂”的假象,因為Pod的主機名無法對應Pod的IP地址,因此界面會顯示2個節點,這兩個節點都狀態都為異常狀態。

    下面是HDFS Master節點Service對應的Pod定義:

    
    
    1. apiVersion: v1 
    2. kind: Pod 
    3. metadata: 
    4. name: k8s-hadoop-master 
    5. labels: 
    6. app: k8s-hadoop-master 
    7. spec: 
    8. containers: 
    9. name: k8s-hadoop-master 
    10.   image: kubeguide/hadoop 
    11.   imagePullPolicy: IfNotPresent 
    12.   ports: 
    13.     - containerPort: 9000 
    14.     - containerPort: 50070     
    15.   env: 
    16.     - name: HADOOP_NODE_TYPE 
    17.       value: namenode 
    18.     - name: HDFS_MASTER_SERVICE 
    19.       valueFrom: 
    20.         configMapKeyRef: 
    21.           name: ku8-hadoop-conf 
    22.           key: HDFS_MASTER_SERVICE 
    23.     - name: HDOOP_YARN_MASTER 
    24.       valueFrom: 
    25.         configMapKeyRef: 
    26.           name: ku8-hadoop-conf 
    27.           key: HDOOP_YARN_MASTER 
    28. restartPolicy: Always 

    下面是HDFS的Datanode的節點定義(hadoop-datanode-1):

    
    
    1. apiVersion: v1 
    2. kind: Pod 
    3. metadata: 
    4. name: hadoop-datanode-1 
    5. labels: 
    6.   app: hadoop-datanode-1 
    7. spec: 
    8. containers: 
    9. name: hadoop-datanode-1 
    10.   image: kubeguide/hadoop 
    11.   imagePullPolicy: IfNotPresent 
    12.   ports: 
    13.     - containerPort: 9000 
    14.     - containerPort: 50070     
    15.   env: 
    16.     - name: HADOOP_NODE_TYPE 
    17.       value: datanode 
    18.     - name: HDFS_MASTER_SERVICE 
    19.       valueFrom: 
    20.         configMapKeyRef: 
    21.           name: ku8-hadoop-conf 
    22.           key: HDFS_MASTER_SERVICE 
    23.     - name: HDOOP_YARN_MASTER 
    24.       valueFrom: 
    25.         configMapKeyRef: 
    26.           name: ku8-hadoop-conf 
    27.           key: HDOOP_YARN_MASTER         
    28. restartPolicy: Always 

    實際上,Datanode可以用DaemonSet方式在每個Kubernerntes節點上部署一個,在這里為了清晰起見,就沒有用這個方式 定義。接下來,我們來看看Yarn框架如何建模,下圖是Yarn框架的集群架構圖:

    Hadoop 運行在 Kubernetes平臺實踐

    我們看到,Yarn集群中存在兩種角色的節點:ResourceManager以及NodeManger,前者屬于Yarn集群的頭腦(Master),后者是工作承載節點(Work Node),這個架構雖然與HDFS很相似,但因為一個重要細節的差別,無法沿用HDFS的建模方式,這個細節就是Yarn集群中的ResourceManager要對NodeManger節點進行嚴格驗證,即NodeManger節點的節點所在主機的主機名(DNS)與對應IP地址嚴格匹配,簡單來說,就是要符合如下規則:

    NodeManger建立TCP連接時所用的IP地址,必須是該節點主機名對應的IP地址,即主機DNS名稱解析后返回節點的IP地址。

    所以我們采用了Kubernetes里較為特殊的一種Service——Headless Service來解決這個問題,即為每個NodeManger節點建模一個Headless Service與對應的Pod,下面是一個ResourceManager與兩個NodeManger節點所組成的Yarn集群的建模示意圖:

    Hadoop 運行在 Kubernetes平臺實踐

    Headless Service的特殊之處在于這種Service沒有分配Cluster IP,在Kuberntes DNS里Ping這種Service的名稱時,會返回后面對應的Pod的IP地址,如果后面有多個Pod實例,則會隨機輪詢返回其中一個的Pod地址,我們用Headless Service建模NodeManger的時候,還有一個細節需要注意,即Pod的名字(容器的主機名)必須與對應的Headless Service的名字一樣,這樣一來,當運行在容器里的NodeManger進程向ResourceManager發起TCP連接的過程中會用到容器的主機名,而這個主機名恰好是NodeManger Service的服務名,而這個服務名解析出來的IP地址又剛好是容器的IP地址,這樣一來,就巧妙的解決了Yarn集群的DNS限制問題。

    下面以yarn-node-1為例,給出對應的Service與Pod的YAM文件,首先是yarn-node-1對應的Headless Service的YAM定義:

    
    
    1. apiVersion: v1 
    2. kind: Service 
    3. metadata: 
    4. name: yarn-node-1 
    5. spec: 
    6. clusterIP: None 
    7. selector: 
    8. app: yarn-node-1 
    9. ports: 
    10.  - port: 8040 

    注意到定義中“clusterIP:None”這句話,表明這是一個Headless Service,沒有自己的Cluster IP地址,下面給出YAM文件定義:

    
    
    1. apiVersion: v1 
    2. kind: Pod 
    3. metadata: 
    4. name: yarn-node-1 
    5. labels: 
    6. app: yarn-node-1 
    7. spec: 
    8. containers: 
    9. name: yarn-node-1 
    10.   image: kubeguide/hadoop 
    11.   imagePullPolicy: IfNotPresent 
    12.   ports: 
    13.     - containerPort: 8040 
    14.     - containerPort: 8041    
    15.     - containerPort: 8042         
    16.   env: 
    17.     - name: HADOOP_NODE_TYPE 
    18.       value: yarnnode 
    19.     - name: HDFS_MASTER_SERVICE 
    20.       valueFrom: 
    21.         configMapKeyRef: 
    22.           name: ku8-hadoop-conf 
    23.           key: HDFS_MASTER_SERVICE 
    24.     - name: HDOOP_YARN_MASTER 
    25.       valueFrom: 
    26.         configMapKeyRef: 
    27.           name: ku8-hadoop-conf 
    28.           key: HDOOP_YARN_MASTER           
    29. restartPolicy: Always 

    ResourceManager的YAML定義沒有什么特殊的地方,其中Service定義如下:

    
    
    1. apiVersion: v1 
    2. kind: Service 
    3. metadata: 
    4. name: ku8-yarn-master 
    5. spec: 
    6. type: NodePort 
    7. selector: 
    8. app: yarn-master 
    9. ports: 
    10.  - name"8030"        
    11.    port: 8030 
    12.  - name"8031"      
    13.    port: 8031 
    14.  - name"8032" 
    15.    port: 8032      
    16.  - name: http 
    17.    port: 8088 
    18.    targetPort: 8088 
    19.    nodePort: 32088 

    對應的Pod定義如下:

    
    
    1. apiVersion: v1 
    2. kind: Pod 
    3. metadata: 
    4. name: yarn-master 
    5. labels: 
    6. app: yarn-master 
    7. spec: 
    8. containers: 
    9. name: yarn-master 
    10.   image: kubeguide/hadoop 
    11.   imagePullPolicy: IfNotPresent 
    12.   ports: 
    13.     - containerPort: 9000 
    14.     - containerPort: 50070     
    15.   env: 
    16.     - name: HADOOP_NODE_TYPE 
    17.       value: resourceman 
    18.     - name: HDFS_MASTER_SERVICE 
    19.       valueFrom: 
    20.         configMapKeyRef: 
    21.           name: ku8-hadoop-conf 
    22.           key: HDFS_MASTER_SERVICE 
    23.     - name: HDOOP_YARN_MASTER 
    24.       valueFrom: 
    25.         configMapKeyRef: 
    26.           name: ku8-hadoop-conf 
    27.           key: HDOOP_YARN_MASTER           
    28. restartPolicy: Always 

    目前這個方案,還遺留了一個問題有待解決:HDFS NameNode節點重啟后的文件系統格式化問題,這個問題可以通過啟動腳本來解決,即判斷HDFS文件系統是否已經格式化過,如果沒有,就啟動時候執行格式化命令,否則跳過格式化命令。

    安裝完畢后,我們可以通過瀏覽器訪問Hadoop的HDFS管理界面,點擊主頁上的Overview頁簽會顯示我們熟悉的HDFS界面:

    Hadoop 運行在 Kubernetes平臺實踐

    切換到Datanodes頁簽,可以看到每個Datanodes的的信息以及當前狀態:

    Hadoop 運行在 Kubernetes平臺實踐

    接下來,我們可以登錄到NameNode所在的Pod里并執行HDSF命令進行功能性驗證,下面的命令執行結果是建立一個HDFS目錄,并且上傳一個文件到此目錄中:

    
    
    1. root@hadoop-master:/usr/local/hadoop/bin# hadoop fs -ls  / 
    2. root@hadoop-master:/usr/local/hadoop/bin# hadoop fs -mkdir /leader-us 
    3. root@hadoop-master:/usr/local/hadoop/bin# hadoop fs -ls / 
    4. Found 1 items 
    5. drwxr-xr-x   - root supergroup          0 2017-02-17 07:32 /leader-us 
    6. root@hadoop-master:/usr/local/hadoop/bin# hadoop fs -put hdfs.cmd /leader-us 

    然后,我們可以在HDFS管理界面中瀏覽HDFS文件系統,驗證剛才的操作結果:

    Hadoop 運行在 Kubernetes平臺實踐

    接下來,我們再登錄到hadoop-master對應的Pod上,啟動一個Map-Reduce測試作業——wordcount,作業啟動后,我們可以在Yarn的管理界面中看到作業的執行信息,如下圖所示:

    Hadoop 運行在 Kubernetes平臺實踐

    當作業執行完成后,可以通過界面看到詳細的統計信息,比如wordcount的執行結果如下圖所示:

    Hadoop 運行在 Kubernetes平臺實踐

    最后,我們進行了裸機版Hadoop集群與Kubernetes之上的Hadoop集群的性能對比測試,測試環境為十臺服務器組成的集群,具體參數如下:

    硬件:

    • CPU:2*E5-2640v3-8Core
    • 內存:16*16G DDR4
    • 網卡:2*10GE多模光口
    • 硬盤:12*3T SATA

    軟件:

    • BigCloud Enterprise Linux 7(GNU/Linux 3.10.0-514.el7.x86_64 x86_64)
    • Hadoop2.7.2
    • Kubernetes 1.7.4+ Calico V3.0.1

    我們執行了以下這些標準測試項:

    • TestDFSIO:分布式系統讀寫測試
    • NNBench:NameNode測試
    • MRBench:MapReduce測試
    • WordCount:單詞頻率統計任務測試
    • TeraSort:TeraSort任務測試

    綜合測試下來,Hadoop跑在Kuberntes集群上時,性能有所下降,以TestDFSIO的測試為例,下面是Hadoop集群文件讀取的性能測試對比:

    Hadoop 運行在 Kubernetes平臺實踐

    我們看到,Kubernetes集群上的文件讀性能與物理機相比,下降了差不多30%左右,并且任務執行時間也增加不少,再來對比文件寫入的性能,測試結果如下下圖所示:

    Hadoop 運行在 Kubernetes平臺實踐

    我們看到,寫文件性能的差距并不大,這里的主要原因是在測試過程中,HDFS寫磁盤的速度遠遠低于讀磁盤的速度,因此無法拉開差距。

    之所以部署在Kuberntes上的Hadoop集群的性能會有所下降,主要一個原因是容器虛擬網絡所帶來的性能損耗,如果用Host Only模型,則兩者之間的差距會進一步縮小,下圖是TestDFSIO測試中Hadoop集群文件讀取的性能測試對比:

    Hadoop 運行在 Kubernetes平臺實踐

    因此我們建議在生產環境中采用Host Only的網絡模型,以提升Hadoop的集群性能。

    攻下Hadoop在Kubernetes上的部署,并且在生產中加以驗證,我們可以很自豪的說,現在沒有什么能夠難倒應用向Kubernetes的遷移的步伐,采用統一的PaaS構建企業的應用集群和大數據集群,實現資源的共享和服務的統一管理將會大大的提升企業的業務部署速度和管理的效率。

    0(好文)
    0(太水)
    版權聲明:部分文章源于網絡,如侵權請聯系我們刪除
    買購快云Plus,云服務器折上折

    專題頁

    色播