使用docker搭建Hadoop
Hadoop簡介
1、Hadoop的整體框架
Hadoop由HDFS、MapReduce、HBase、Hive和ZooKeeper等成員組成,其中最基礎最重要元素為底層用于存儲集群中所有存儲節點文件的文件系統HDFS(Hadoop Distributed File System)來執行MapReduce程序的MapReduce引擎。
(1)Pig是一個基于Hadoop的大規模數據分析平臺,Pig為復雜的海量數據并行計算提供了一個簡單的操作和編程接口;
(2)Hive是基于Hadoop的一個工具,提供完整的SQL查詢,可以將sql語句轉換為MapReduce任務進行運行;
(3)ZooKeeper:高效的,可拓展的協調系統,存儲和協調關鍵共享狀態;
(4)HBase是一個開源的,基于列存儲模型的分布式數據庫;
(5)HDFS是一個分布式文件系統,有著高容錯性的特點,適合那些超大數據集的應用程序;
(6)MapReduce是一種編程模型,用于大規模數據集(大于1TB)的并行運算。
下圖是一個典型的Hadoop集群的部署結構:
接著給出Hadoop各組件依賴共存關系:
2、Hadoop的核心設計
(1)HDFS
HDFS是一個高度容錯性的分布式文件系統,可以被廣泛的部署于廉價的PC上。它以流式訪問模式訪問應用程序的數據,這大大提高了整個系統的數據吞吐量,因而非常適合用于具有超大數據集的應用程序中。
HDFS的架構如圖所示。HDFS架構采用主從架構(master/slave)。一個典型的HDFS集群包含一個NameNode節點和多個DataNode節點。NameNode節點負責整個HDFS文件系統中的文件的元數據的保管和管理,集群中通常只有一臺機器上運行NameNode實例,DataNode節點保存文件中的數據,集群中的機器分別運行一個DataNode實例。在HDFS中,NameNode節點被稱為名稱節點,DataNode節點被稱為數據節點。DataNode節點通過心跳機制與NameNode節點進行定時的通信。
- NameNode
可以看作是分布式文件系統中的管理者,存儲文件系統的meta-data,主要負責管理文件系統的命名空間,集群配置信息,存儲塊的復制。
- DataNode
是文件存儲的基本單元。它存儲文件塊在本地文件系統中,保存了文件塊的meta-data,同時周期性的發送所有存在的文件塊的報告給NameNode。
- Client
就是需要獲取分布式文件系統文件的應用程序。
以下來說明HDFS如何進行文件的讀寫操作:
文件寫入:
文件讀取:
(2)MapReduce
MapReduce是一種編程模型,用于大規模數據集的并行運算。Map(映射)和Reduce(化簡),采用分而治之思想,先把任務分發到集群多個節點上,并行計算,然后再把計算結果合并,從而得到最終計算結果。多節點計算,所涉及的任務調度、負載均衡、容錯處理等,都由MapReduce框架完成,不需要編程人員關心這些內容。
下圖是MapReduce的處理過程:
用戶提交任務給JobTracer,JobTracer把對應的用戶程序中的Map操作和Reduce操作映射至TaskTracer節點中;輸入模塊負責把輸入數據分成小數據塊,然后把它們傳給Map節點;Map節點得到每一個key/value對,處理后產生一個或多個key/value對,然后寫入文件;Reduce節點獲取臨時文件中的數據,對帶有相同key的數據進行迭代計算,然后把終結果寫入文件。
如果這樣解釋還是太抽象,可以通過下面一個具體的處理過程來理解:(WordCount實例)
Hadoop的核心是MapReduce,而MapReduce的核心又在于map和reduce函數。它們是交給用戶實現的,這兩個函數定義了任務本身。
map函數:接受一個鍵值對(key-value pair)(例如上圖中的Splitting結果),產生一組中間鍵值對(例如上圖中Mapping后的結果)。Map/Reduce框架會將map函數產生的中間鍵值對里鍵相同的值傳遞給一個reduce函數。
reduce函數:接受一個鍵,以及相關的一組值(例如上圖中Shuffling后的結果),將這組值進行合并產生一組規模更小的值(通常只有一個或零個值)(例如上圖中Reduce后的結果)
但是,Map/Reduce并不是萬能的,適用于Map/Reduce計算有先提條件:
(1)待處理的數據集可以分解成許多小的數據集;
(2)而且每一個小數據集都可以完全并行地進行處理;
若不滿足以上兩條中的任意一條,則不適合適用Map/Reduce模式。
使用docker搭建Hadoop
使用Docker搭建Hadoop集群的過程包括:
安裝docker
參考學習筆記-搭建Docker
獲取centos鏡像
[root@ali-test~]# docker search centos # 查找centos鏡像 NAME DESCRIPTION STARS OFFICIAL AUTOMATED centos The official build of CentOS. 6255 [OK] [root@ali-test~]# docker pull centos # 拉取centos鏡像 [root@ali-test~]# docker images REPOSITORY TAG IMAGE ID CREATED SIZE centos latest 0d120b6ccaa8 2 months ago 215MB安裝SSH
以centos7鏡像為基礎,構建一個帶有SSH功能的centos
[root@ali-test~]# vim Dockerfile # 以 centos 鏡像為基礎,安裝SSH的相關包,設置了root用戶的密碼 FROM centos # 基于centos鏡像 MAINTAINER tian # 創建者信息# 執行的命令 RUN yum -y install openssh-server sudo RUN sed -i 's/UsePAM yes/UsePAM no/g' /etc/ssh/sshd_config RUN yum -y install openssh-clientsRUN echo "root:1" | chpasswd RUN echo "root ALL=(ALL) ALL" >> /etc/sudoers RUN ssh-keygen -t dsa -f /etc/ssh/ssh_host_dsa_key RUN ssh-keygen -t rsa -f /etc/ssh/ssh_host_rsa_keyRUN mkdir /var/run/sshd EXPOSE 22 # 開放的端口 CMD ["/usr/sbin/sshd","-D"] # 執行的命令,這里為啟動的命令,在/lib/systemd/system/sshd.service 可以查看到相應的啟動命令[root@ali-test ~]# docker build -t myos:ssh . # 構建基于centos的ssh鏡像 Successfully tagged myos:ssh[root@ali-test ~]# docker images # 查看鏡像列表,可以看到構建的新鏡像 REPOSITORY TAG IMAGE ID CREATED SIZE myos ssh e82288279686 About a minute ago 277MB centos latest 0d120b6ccaa8 2 months ago 215MB設置固定IP
需要用到 pipework,他用于給容器設置IP
[root@ali-test ~]# git clone https://github.com/jpetazzo/pipework.git [root@ali-test ~]# cd pipework/ [root@ali-test pipework]# cp pipework /usr/local/bin/ # 復制啟動命令# 下載bridge-utils網橋工具 [root@ali-test ~]# yum -y install bridge-utils# 創建網絡 [root@ali-test ~]# brctl addbr br1 # 添加bridge [root@ali-test ~]# ip link set dev br1 up # 激活網橋設備br1 [root@ali-test ~]# ip addr add 192.168.1.1/24 dev br1 # 給br1添加ip-----------------------------------------------------------------------------ps----------------------------------------------------------------------------------------------------------
| addbr <bridge> | 創建網橋 | brctl addbr br10 |
| delbr <bridge> | 刪除網橋 | brctl delbr br10 |
| addif <bridge> <device> | 將網卡接口接入網橋 | brctl addif br10 eth0 |
| delif <bridge> <device> | 刪除網橋接入的網卡接口 | brctl delif br10 eth0 |
| show <bridge> | 查詢網橋信息 | brctl show br10 |
| stp <bridge> {on|off} | 啟用禁用 STP | brctl stp br10 off/on |
| showstp <bridge> | 查看網橋 STP 信息 | brctl showstp br10 |
| setfd <bridge> <time> | 設置網橋延遲 | brctl setfd br10 10 |
| showmacs <bridge> | 查看 mac 信息 | brctl showmacs br10 |
-----------------------------------------------------------------------------ps----------------------------------------------------------------------------------------------------------
基于myos:ssh這個鏡像啟動一個容器,名為 myos.ssh
[root@ali-test ~]# docker run -d --name=myos.ssh myos:ssh # 后臺啟動 6dd5df3310da5fafdfb5e8d5833ae0ccfa9dd7120dbb2b8fba71ac85f8daa7f9[root@ali-test ~]# pipework br1 myos.ssh 192.168.1.2/24 # 設置該容器的ip[root@ali-test ~]# ping 192.168.1.2 # 在宿主機測試ping和ssh PING 192.168.1.2 (192.168.1.2) 56(84) bytes of data. 64 bytes from 192.168.1.2: icmp_seq=1 ttl=64 time=0.076 ms 64 bytes from 192.168.1.2: icmp_seq=2 ttl=64 time=0.048 ms ^C --- 192.168.1.2 ping statistics --- 2 packets transmitted, 2 received, 0% packet loss, time 999ms rtt min/avg/max/mdev = 0.048/0.062/0.076/0.014 ms [root@ali-test ~]# ssh 192.168.1.2 The authenticity of host '192.168.1.2 (192.168.1.2)' can't be established. RSA key fingerprint is SHA256:m4A8kQLWvbA/a+1wdwwrrbSmEDiyCWHQZT9xNg29UBg. RSA key fingerprint is MD5:59:60:02:77:8b:2e:8c:fe:d8:e8:5b:1b:5e:5e:d2:ec. Are you sure you want to continue connecting (yes/no)? yes Warning: Permanently added '192.168.1.2' (RSA) to the list of known hosts. root@192.168.1.2's password: [root@6dd5df3310da ~]# 退出以上證明一個容器啟動成功,接下來可以再運行2個容器、設置好IP,那么就相當于有了3臺服務器
[root@ali-test ~]# docker run -d --name=myos.ssh2 myos:ssh 87d0790f54072bc3289ae487733c0aecdebfb130a60cb939ce32a66d1440ba52 [root@ali-test ~]# docker run -d --name=myos.ssh3 myos:ssh 62eac2ea57f798066d6b21bd95d5a262cdf3a0eafe651913cd513207dc831521[root@ali-test ~]# pipework br1 myos.ssh2 192.168.1.3/24 [root@ali-test ~]# pipework br1 myos.ssh3 192.168.1.4/24# 測試驗證 [root@ali-test ~]# ping -c 2 192.168.1.3 PING 192.168.1.3 (192.168.1.3) 56(84) bytes of data. 64 bytes from 192.168.1.3: icmp_seq=1 ttl=64 time=0.074 ms 64 bytes from 192.168.1.3: icmp_seq=2 ttl=64 time=0.050 ms--- 192.168.1.3 ping statistics --- 2 packets transmitted, 2 received, 0% packet loss, time 999ms rtt min/avg/max/mdev = 0.050/0.062/0.074/0.012 ms [root@ali-test ~]# ping -c 2 192.168.1.4 PING 192.168.1.4 (192.168.1.4) 56(84) bytes of data. 64 bytes from 192.168.1.4: icmp_seq=1 ttl=64 time=0.081 ms 64 bytes from 192.168.1.4: icmp_seq=2 ttl=64 time=0.051 ms--- 192.168.1.4 ping statistics --- 2 packets transmitted, 2 received, 0% packet loss, time 999ms rtt min/avg/max/mdev = 0.051/0.066/0.081/0.015 ms[root@ali-test ~]# ssh 192.168.1.3 The authenticity of host '192.168.1.3 (192.168.1.3)' can't be established. RSA key fingerprint is SHA256:m4A8kQLWvbA/a+1wdwwrrbSmEDiyCWHQZT9xNg29UBg. RSA key fingerprint is MD5:59:60:02:77:8b:2e:8c:fe:d8:e8:5b:1b:5e:5e:d2:ec. Are you sure you want to continue connecting (yes/no)? yes Warning: Permanently added '192.168.1.3' (RSA) to the list of known hosts. root@192.168.1.3's password: [root@87d0790f5407 ~]# logout Connection to 192.168.1.3 closed. [root@ali-test ~]# ssh 192.168.1.4 The authenticity of host '192.168.1.4 (192.168.1.4)' can't be established. RSA key fingerprint is SHA256:m4A8kQLWvbA/a+1wdwwrrbSmEDiyCWHQZT9xNg29UBg. RSA key fingerprint is MD5:59:60:02:77:8b:2e:8c:fe:d8:e8:5b:1b:5e:5e:d2:ec. Are you sure you want to continue connecting (yes/no)? yes Warning: Permanently added '192.168.1.4' (RSA) to the list of known hosts. root@192.168.1.4's password: [root@62eac2ea57f7 ~]# logout Connection to 192.168.1.4 closed.[root@ali-test ~]# docker ps CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES 62eac2ea57f7 myos:ssh "/usr/sbin/sshd -D" 2 minutes ago Up 2 minutes 22/tcp myos.ssh3 87d0790f5407 myos:ssh "/usr/sbin/sshd -D" 2 minutes ago Up 2 minutes 22/tcp myos.ssh2 6dd5df3310da myos:ssh "/usr/sbin/sshd -D" 9 minutes ago Up 9 minutes 22/tcp myos.ssh這樣就有了3個可以SSH連接的容器,可以在上面安裝和配置集群環境了
構建Hadoop鏡像
上面是運行了3個centos容器,需要在每個容器中單獨安裝Hadoop環境,我們可以像構建SSH鏡像一樣,構建一個Hadoop鏡像,然后運行3個Hadoop容器,這樣就更簡單了
# 前提環境準備:在官網下載jdk包:https://www.oracle.com/java/technologies/javase/javase-jdk8-downloads.html和Hadoop包[root@ali-test ~]# mkdir Hadoop ;cd Hadoop [root@ali-test Hadoop]# wget wget https://mirrors.bfsu.edu.cn/apache/hadoop/common/hadoop-2.9.2/hadoop-2.9.2.tar.gz [root@ali-test Hadoop]# ll total 111176 -rw-r--r-- 1 root root 39119388 Nov 20 2018 hadoop-2.9.2-src.tar.gz -rw-r--r-- 1 root root 143142634 Oct 30 15:48 jdk-8u271-linux-x64.tar.gz[root@ali-test Hadoop]# vim Dockerfile # 編寫Dockerfile FROM myos:ssh ADD jdk-8u271-linux-aarch64.tar.gz /usr/local RUN mv /usr/local/jdk1.8.0_271 /usr/local/jdk1.8 ENV JAVA_HOME /usr/local/jdk1.8 ENV PATH $JAVA_HOME/bin:$PATHADD hadoop-2.9.2.tar.gz /usr/local RUN mv /usr/local/hadoop /usr/local/hadoop ENV HADOOP_HOME /usr/local/hadoop ENV PATH $HADOOP_HOME/bin:$PATHRUN yum -y install which sudo vim bash-completion[root@ali-test Hadoop]# docker build -t hadoop . # 構建基于ssh的Hadoop鏡像 Successfully tagged hadoop:latest# 運行三個容器,分別給每個容器命名 [root@ali-test ~]# docker run --name hadoop0 --hostname hadoop0 -d -p 50070:50070 -p 8088:8088 hadoop # -p映射端口 298a5fdb46e3d5928f676b003345727ed98ba8e55f9f6be9d653bd8965bb53e2 [root@ali-test ~]# docker run --name hadoop1 --hostname hadoop1 -d -P hadoop # -P隨機端口映射,容器內部端口隨機映射到主機的端口 fa064c46a171ea6c32f318e6021d2402879c04b97d16ff0f387c02e177b0f8b1 [root@ali-test ~]# docker run --name hadoop2 --hostname hadoop2 -d -P hadoop 2c724351eb71b10297553815d8537513aab303388d47a9b5f60c518648368e8f# 容器hadoop0啟動時,映射了端口號,50070和8088,是用來在瀏覽器中訪問hadoop WEB界面的配置Hadoop集群
新開3個終端窗口,分別連接到 hadoop0,hadoop1,hadoop2,便于操作 [root@ali-test ~]# docker exec -it hadoop0 /bin/bash [root@hadoop0 /]# ip a 1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1000link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00inet 127.0.0.1/8 scope host lovalid_lft forever preferred_lft forever 72: eth0@if73: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP group default link/ether 02:42:ac:11:00:05 brd ff:ff:ff:ff:ff:ff link-netnsid 0inet 172.17.0.5/16 brd 172.17.255.255 scope global eth0valid_lft forever preferred_lft forever[root@ali-test ~]# docker exec -it hadoop1 /bin/bash [root@hadoop1 /]# ip a 1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1000link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00inet 127.0.0.1/8 scope host lovalid_lft forever preferred_lft forever 74: eth0@if75: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP group default link/ether 02:42:ac:11:00:06 brd ff:ff:ff:ff:ff:ff link-netnsid 0inet 172.17.0.6/16 brd 172.17.255.255 scope global eth0valid_lft forever preferred_lft forever[root@ali-test ~]# docker exec -it hadoop2 /bin/bash [root@hadoop2 /]# ip a 1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1000link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00inet 127.0.0.1/8 scope host lovalid_lft forever preferred_lft forever 76: eth0@if77: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP group default link/ether 02:42:ac:11:00:07 brd ff:ff:ff:ff:ff:ff link-netnsid 0inet 172.17.0.7/16 brd 172.17.255.255 scope global eth0valid_lft forever preferred_lft forever[root@hadoop0 /]# vi /etc/hosts # 在每個容器修改/etc/hosts配置文件 172.17.0.5 hadoop0 172.17.0.6 hadoop1 172.17.0.7 hadoop2# 配置三臺主機互相免密登錄 [root@hadoop0 /]# ssh-keygen # 在每臺主機都執行該操作 [root@hadoop0 /]# for i in hadoop{0..2}; do ssh-copy-id root@$i; done # 將公鑰傳給包括自己的每臺主機,三個容器都要做!!!確保最終每臺主機都能免密訪問其他主機包括自己安裝配置Hadoop
以上,準備環節結束,接下來開始正片內容,不要走開,馬上回來!
# 進入容器,修改配置文件 [root@hadoop0 /]# cd /usr/local/hadoop/ [root@hadoop0 hadoop]# ls LICENSE.txt NOTICE.txt README.txt bin etc include lib libexec sbin share [root@hadoop0 hadoop]# mkdir tmp hdfs [root@hadoop0 hadoop]# mkdir hdfs/data hdfs/name# 修改配置文件 [root@hadoop0 hadoop]# vim etc/hadoop/core-site.xml 在 <configuration> 塊兒中添加:<property><name>fs.defaultFS</name><value>hdfs://hadoop0:9000</value></property><property><name>hadoop.tmp.dir</name><value>file:/home/hadoop/tmp</value></property><property><name>io.file.buffer.size</name><value>131702</value></property>[root@hadoop0 hadoop]# vim etc/hadoop/hdfs-site.xml 在 <configuration> 塊兒中添加:<property><name>dfs.namenode.name.dir</name><value>file:/home/hadoop/hdfs/name</value></property><property><name>dfs.datanode.data.dir</name><value>file:/home/hadoop/hdfs/data</value></property><property><name>dfs.replication</name><value>2</value></property><property><name>dfs.namenode.secondary.http-address</name><value>hadoop0:9001</value></property><property><name>dfs.webhdfs.enabled</name><value>true</value></property>[root@hadoop0 hadoop]# cp etc/hadoop/mapred-site.xml.template etc/hadoop/mapred-site.xml [root@hadoop0 hadoop]# vim etc/hadoop/mapred-site.xml 在 <configuration> 塊兒中添加:<property><name>yarn.nodemanager.aux-services</name><value>mapreduce_shuffle</value></property><property><name>yarn.nodemanager.auxservices.mapreduce.shuffle.class</name><value>org.apache.hadoop.mapred.ShuffleHandler</value></property><property><name>yarn.resourcemanager.address</name><value>hadoop0:8032</value></property><property><name>yarn.resourcemanager.scheduler.address</name><value>hadoop0:8030</value></property><property><name>yarn.resourcemanager.resource-tracker.address</name><value>hadoop0:8031</value></property><property><name>yarn.resourcemanager.admin.address</name><value>hadoop0:8033</value></property><property><name>yarn.resourcemanager.webapp.address</name><value>hadoop0:8088</value></property>[root@hadoop0 hadoop]# vim etc/hadoop/slaves 刪除已有內容,添加: hadoop1 hadoop2[root@hadoop0 hadoop]# vim etc/hadoop/hadoop-env.sh 找到 export JAVA_HOME=${JAVA_HOME},改為自己JAVA_HOME的絕對路徑 export JAVA_HOME=/usr/local/jdk1.8# 復制 hadoop目錄 到hadoop1,hadoop2 [root@hadoop0 ~]# scp -r /usr/local/hadoop root@hadoop1:/usr/local/hadoop [root@hadoop0 ~]# scp -r /usr/local/hadoop root@hadoop2:/usr/local/hadoop啟動 hadoop
在master啟動hadoop,從節點會自動啟動
初始化 [root@hadoop0 ~]# hdfs namenode -format /************************************************************ SHUTDOWN_MSG: Shutting down NameNode at hadoop0/172.17.0.5 ************************************************************/啟動 [root@hadoop0 ~]# cd /usr/local/hadoop/sbin/ [root@hadoop0 sbin]# ./hadoop-daemon.sh start namenode [root@hadoop0 sbin]# ./hadoop-daemon.sh start datanode [root@hadoop0 sbin]# ./start-dfs.sh [root@hadoop0 sbin]# ./start-yarn.sh [root@hadoop0 sbin]# ./mr-jobhistory-daemon.sh start historyserver測試
# 在三臺主機分別查看狀態 [root@hadoop0 ~]# jps 418 DataNode 324 NameNode 1685 JobHistoryServer 1397 ResourceManager 1150 SecondaryNameNode 1758 Jps[root@hadoop1 ~]# jps 550 Jps 312 DataNode 427 NodeManager[root@hadoop2 ~]# jps 548 Jps 310 DataNode 425 NodeManager瀏覽器中訪問:
http://ip:50070/
ps:在啟動docker容器的時候已經設置了本機和容器的映射,所以此時只需要在云主機當中設置安全組放開并進行訪問即可
http://ip:8088/
可以正常訪問的話,可以說明集群啟動成功了,但不一定可以正常運行,還需要下面的實際驗證
驗證
- (1)hdfs 操作
創建目錄
[root@hadoop0 ~]# hdfs dfs -mkdir -p /hadoop/input上傳文件,把現有的一些配置文件上傳到剛剛創建的目錄中
[root@hadoop0 ~]# vim test.txt hi,wo shi xiaotian [root@hadoop0 ~]# hdfs dfs -put /usr/local/hadoop/etc/hadoop/kms*.xml /hadoop/input [root@hadoop0 ~]# hdfs dfs -put test.txt /hadoop/input 如果沒有返回錯誤信息,說明操作成功訪問 http://master ip:50070/,在文件瀏覽頁面查看[外鏈圖片轉存失敗,源站可能有防盜鏈機制,建議將圖片保存下來直接上傳(img-I0DqT8Kh-1604558200656)(C:\Users\tian\AppData\Roaming\Typora\typora-user-images\image-20201030163830933.png)]
- (2)mapreduce 操作
hadoop 安裝包中提供了一個示例程序,我們可以使用它對剛剛上傳的文件進行測試
[root@hadoop0 ~]# hadoop jar /usr/local/hadoop/share/hadoop/mapreduce/hadoop-mapreduce-examples-2.9.2.jar grep /hadoop/input /hadoop/output 'dfs[a-z.]+'
在瀏覽器中進行驗證
注:在執行過程中,如果長時間處于 running 狀態不動,雖然沒有報錯,但實際上是出錯了,后臺在不斷重試,需要到 logs 目錄下查看日志文件中的錯誤信息
總結
以上是生活随笔為你收集整理的使用docker搭建Hadoop的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: Squid安装与配置
- 下一篇: 搭建glusterfs集群