【Docker x Hadoop】使用 Docker 搭建 Hadoop 集群(从零开始保姆级)
—— 步驟 ——
- 0. 背景
- 1. 創建出第一個容器
- 2. 為該容器配置 java 和 hadoop 環境
- 3. 配置允許外界通過 ssh 連接容器
- 4. 由該容器克隆出多個容器
- 5. 為各個容器配置 ssh 免密登錄
- 6. 開始編寫集群配置
- 7. 啟動集群
2021-10-7 補充(務必看一下)
又雙叒叕來填坑了,6 號的補充讓 java 可以成功訪問到集群,完成文件夾的創建和刪除,但文件的上傳和下載卻出問題了,根本原因是訪問不到 datanode 結點
后邊來的可以補救一下,也就是為 hadoop001 (datanode 結點中的一個)添加 9866 和主機的 9866 進行映射,由它完成數據的讀寫操作
 如果是需要補救或者想要進一步了解的話,可以看這篇文章,詳細介紹了補救方法以及問題分析:
 【Docker x Hadoop x Java API】xxx could only be written to 0 of the 1 minReplication nodes,There are 3
2021-10-6 補充(務必看一下)
好叭-- 我承認使用 nginx 進行代理是疏忽了,到后面使用 Java 訪問集群的時候會出現問題
 正確的方式應該是通過端口映射,將需要的端口(9870,9868,8088,8020)和主機端口進行映射,在外網直接訪問映射后的端口就 OK 了
所以在容器啟動(docker run)就可以為對應的容器映射端口了
 (下邊已作修改,添加了端口映射的,nginx 那一部分就可以不用看啦)
如果絨球已經啟動,又不想直接干掉的話(就像我—_—),也可以為容器動態添加端口映射
 可以參照這篇文章:【Docker之軌跡】為正在運行中的容器動態添加端口映射
0. 背景
看到網上的教程,都是使用虛擬機克隆出多臺虛擬機模擬集群
 但在真正的服務器上,發現這種方法行不通了
 這時候就想起 Docker 了,仔細想象 Docker 學完到現在還沒真正實戰過,這次正好是一個好機會
實現思路也很簡單,在 Docker 中創建多個 Centos 容器
 每個容器當作一臺服務器用,就可以模擬出集群環境了
好,動手!
 還不熟悉 Docker 的,可以參考這里:【Docker之軌跡】Docker 入門使用(穿插踩坑經歷)
本博客 Hadoop 版本為 3.1.3,參考尚硅谷視頻
1. 創建出第一個容器
1) 首先拉取 centosdocker pull centos2) 創建一個 centos !!! 后來補充,在這里添加端口映射,hadoop001 要用到的端口是: 9870 和 8020,主機端口自定義 !!! 后來補充,需要讀寫數據的 9866 端口,這里的主機映射端口只能設置為 9866,不能自定義docker run --privileged=true --name=hadoop001 -p xxx:9870 xxx:8020 9866:9866 -dit centos /sbin/init-dit 表示交互式且后臺運行,少了 -it 容器會自動停止--privileged=true 和 /sbin/init 表示特權啟動,后面可能需要實用到 service 命令,需要由這個權限才可以沒有上面這個,再使用時會報 PID 1 的錯誤哦2. 為該容器配置 java 和 hadoop 環境
將 jdk 和 hadoop 從主機復制到該容器中
docker cp <jdk路徑> <容器id>:<容器路徑> docker cp <hadoop路徑> <容器id>:<容器路徑>在 /etc/profile.d/ 下創建文件 mydev.sh
 vim mydex.sh 文件內容如下
第一第二個是兩個環境,最后一個是一些常量,在啟動集群的時候,還要用到這些常量,否則可能啟動失敗
 最后執行 source /etc/profile 使配置文件生效
3. 配置允許外界通過 ssh 連接容器
我們需要讓各個容器產生聯系,才能構成集群,但默認情況下,容器并不能被其他容器直接通過 ssh 訪問,所以這里需要配置
1) 首先需要設置密碼(輸入以下命令,回車設置密碼即可)passwd root大概率會提示沒有該命令,就得下載它,然后再設置就好了yum install passwd2) 然后下載 ssh,以下三步(安裝了服務端和客戶端)yum install opensshyum install openssh-serveryum install openssh-clients3) 然后檢查配置文件,查看以下兩個配置是否一樣(默認應該都是這樣的)vim /etc/ssh/sshd_configPermitRootLogin yesPasswordAuthentication yes這兩個配置允許外網通過 ssh 連接該服務器(容器)4) 如果發現不是這樣,就修改它,同時需要重啟 ssh 是指生效service sshd restart同樣該命令可能不存在,就下載它yum install initscripts通過上面一頓操作,外網已經可以通過 ssh 訪問該容器了,我們可以試試:
1) 首先在容器內,使用 ifconfig 查看 IP 地址ifconfig沒有這個命令的話,就下載他[doge]yum install net-tools2) 在服務器本機中,通過 ssh 訪問該 IP 地址嘗試連接ssh <IP>然后要求輸入密碼,就是上面我們已經設置了的密碼ohhh 然后我們會發現,成功進入容器內部了,這次時通過 ssh 而不是通過 docker 了
 
4. 由該容器克隆出多個容器
首先要克隆出多個容器,就需要將該容器打包成鏡像,再由該鏡像創建出多個容器,步驟如下:
1) 創建鏡像docker commit -a='IceClean' -m='Hadoop cluster example through docker by IceClean' 5a8 hadoop-docker2) 由該進項克隆多個容器模擬集群(這里以三臺服務器的集群為例) !!! 后來補充:hadoop002 要用到的端口是: 8088,主機端口自定義docker run --privileged=true --name=hadoop002 -p xxx:8088 -dit hadoop-docker /sbin/init!!! 后來補充:hadoop003 要用到的端口是: 9868,主機端口自定義docker run --privileged=true --name=hadoop003 -p xxx:9868 -dit hadoop-docker /sbin/init在這些容器生成好后,為它們配置一個 IP 地址映射
 往后就不用去記住每一個容器的 IP 地址了
但同時由于 docker 網橋模式的特性,當容器重啟時,會按順序為該容器分配一個 IP,使得該 IP 地址不是固定的會變化,這對我們已經做的映射非常不友好,所以接下來的第一步,是為每個容器固定一個 IP 地址(這里需要借助 pipework)
1) 安裝 pipewoek(下載并復制可執行文件到 bin 目錄)git clone https://github.com/jpetazzo/pipeworkcp ~/pipework/pipework /usr/local/bin/2) 安裝 bridge-utilsyum -y install bridge-utils3) 創建網絡(這里 IP 地址自定義)brctl addbr br0ip link set dev br0 upip addr add 172.16.10.1 dev br04) 為各個容器設置固定的 IPpipework br0 <容器名> IP/掩碼,如:pipework br0 hadoop001 172.16.10.10/24pipework br0 hadoop002 172.16.10.11/24pipework br0 hadoop003 172.16.10.12/245) 測試這幾個 IP 是否可用ping 172.16.10.106) 中途如果不小心操作錯了(比如說我--),想刪除網絡或IP,可執行如下刪除網絡: ip link set dev br0 down brctl delbr刪除 IP: ip link set dev <名稱> down 其中<名稱>來自于 ifconfig 查找到的 veth1plxxx這樣就成功地為每一個容器固定好 IP 地址了,接下來就可以在容器內配置映射了
1) 在每一臺容器中,修改 hosts 文件vim /etc/hosts比如說我的,就在文件中增加:172.16.10.10 hadoop001172.16.10.11 hadoop002172.16.10.12 hadoop0033) 配置完畢后,我們就可以直接通過名字輕松連接各個容器了,如:ssh hadoop0035. 為各個容器配置 ssh 免密登錄
容器之間雖然能正常互相連接了,但如果每次都需要輸入密碼,那是及其不方便的
 再而,到后面啟動集群的時候,如果沒有免密登錄,既有可能會失敗噢
所以我們可以為各個集群中的容器配置免密登錄,實現各個容器之間的順暢連接
 首先我們來了解一下免密登錄的原理(以 hadoop001 和 hadoop002 為例)
在 hadoop001 中,可以使用 ssh-key-gen 生成密鑰
 —— 分為公鑰和私鑰,私鑰保密,公鑰可以給別人
 然后如果將 hadoop001 的公鑰拷貝給 hadoop002
 —— 通過命令拷貝,該公鑰會保存在 hadoop002 中的 Authorized_keys 中
 往后 hadoop001 想要連接 hadoop002,就可以直接通過公鑰連接,無需密碼
所以我們可以知道,免密登錄的實現,就是將目標服務器的公鑰拷貝到對方的服務器上,這樣對方即可免密登錄該目標服務器,而如果兩臺服務器要互相免密登錄,當然就要互相拷貝到對方的公鑰啦~ 開始行動!
1) 首先在 hadoop001 中,生成公鑰和私鑰(一路回車到底就行了,不需要輸入內容)ssh-keygen -t rsa其中 id_rsa 為私鑰,id_rsa.pub 為公鑰2) 將 hadoop001 的公鑰拷貝到 hadoop002ssh-copy-id hadoop002出現這個提示說明添加成功了,以后我們可以直接通過 ssh hadoop002 連接 hadoop002
 
 注意啦:公鑰也需要拷貝到本服務器(如 hadoop001 將自己的公鑰拷貝到 hadoop001)不然自己五大免密登錄自己哦
然后對于其他的容器也是這樣做,把每個容器的公鑰都拷貝到自己以及另外兩臺服務器上,就實現了三臺服務器互相的免密登錄,完畢~
6. 開始編寫集群配置
前面做足了準備工作,把每一個容器都配置好了
 現在要正式開始集群的搭建啦,首先是集群的配置:
安排一下集群的部署:
| HDFS | NameNode DataNode | DataNode | SecondaryNameNode DataNode | 
| YARN | NodeManager | ResourceManager NodeManager | NodeManager | 
hadoop001 兼任主節點,配置 NameNode
 hadoop002 兼任資源管理,配置 ResourceManager
 hadoop003 兼任備份結點,配置 SecondaryNameNode
接著按照這個規劃,修改 hadoop 配置文件
 先說明一下各個配置文件及其位置(~ 表示 hadoop 所在目錄)
 系統配置文件:~/share/doc/hadoop
 用戶自定義配置文件:~/etc/hadoop
需要我們自定義配置的文件在 etc 目錄下,總共有四個,分別是:
 core-site.xml,``
① 配置 hadoop001
首先到主節點 hadoop001 里邊,配置 core-site.xml
 下面是我自己的配置,需要配置兩個東西
 ① 將 hadoop001 設置為主節點,端口推薦為 8020
 ② 將數據的默認存儲位置改為 hadoop 目錄下的 data 文件夾(如果不存在的話,會自動創建)
然后配置 hdfs-site.xml
<configuration><!-- nn web 端訪問地址 --><property><name>dfs.namenode.http-address</name><value>hadoop001:9870</value></property><!-- 2nn web 端訪問地址--><property><name>dfs.namenode.secondary.http-address</name><value>hadoop003:9868</value></property><!-- 添加 web 端訪問文件的權限 --><!-- 這時后面補充上來的 2333,這里先天坑啦~ --><property><name>dfs.webhdfs.enabled</name><value>true</value></property> </configuration>然后是 yarn-site.xml
<configuration><!-- 指定 MR 走 shuffle --><property><name>yarn.nodemanager.aux-services</name><value>mapreduce_shuffle</value></property><!-- 指定 ResourceManager 的地址 --><property><name>yarn.resourcemanager.hostname</name><value>hadoop002</value></property><!-- 環境變量的繼承 --><property><name>yarn.nodemanager.env-whitelist</name><value>JAVA_HOME,HADOOP_COMMON_HOME,HADOOP_HDFS_HOME,HADOOP_CONF_DIR,CLASSPATH_PREPEND_DISTCACHE,HADOOP_YARN_HOME,HADOOP_MAPRED_HOME</value></property> </configuration>最后配置 mapred-site.xml
<configuration><!-- 指定 MapReduce 程序運行在 Yarn 上 --><property><name>mapreduce.framework.name</name><value>yarn</value></property> </configuration>② 將編寫好的四個配置文件,同步到其他兩臺服務器上(hadoop002,hadoop003)
只需執行下面這一句,就能將四個配置文件遠程復制到另外一個容器中
 由于之前設置了免密登錄,所以它可以直接遠程復制,而不需要輸入密碼,可以很方便地在哥哥容器之間拷貝文件(hadoop003 也同理)
③ 配置 workers
同樣是在 hadoop001 中,修改文件 /etc/hadoop/workers
 將里邊的內容去掉(把 localhost 刪掉)然后換成我們的三個容器:
 注意:行末不能有空格,以及不能有空行的出現
然后將該文件同步到其他兩個容器
scp workers root@hadoop002:/home/hadoop/hadoop-3.1.3/etc/hadoop/ scp workers root@hadoop003:/home/hadoop/hadoop-3.1.3/etc/hadoop/7. 啟動集群
第一次啟動時,需要進行初始化(往后就不用了,再初始化會清空數據哦)
hdfs namenode -format初始化完畢后,在配置文件指定的目錄下,就會生成 data 和 logs 兩個文件
———— 接下來正式啟動
① 首先啟動 DFS:
 在 Hadoop001 中操作(配置了 NameNode 的)
進入 sbin,執行 ./start-dfs.sh 命令
 然后執行 jps 看是否啟動成功,和下圖一樣說明成功了
 
 如果上面的配置都沒有出錯的話,這里應該是很順利就啟動的了
 可能出現的錯誤有:
 1、沒有配置免密登錄,權限不足導致啟動失敗
 2、只把公鑰給了其他容器,沒有給自己,也會導致權限不足的失敗
 所以說,免密登錄在這里,還是非常非常重要的!!!
② 然后啟動 YARN:
 在 Hadoop002 中操作(配置了 ResourceManager的)
依舊在 sbin 中執行 ./start-yarn.sh
 這個步驟,如果服務器性能不太行的話,會卡死(像我這樣—_—卡了兩個小時)
 
 從晚上九點卡到十一點,還好沒放棄 2333
 不過在這里也要提醒一下,卡的時候還是經量別強制重啟服務器,就像我下午三點多那次,強制重啟導致集群出了點問題跑不起來,最后是清空了數據再重啟才解決的,慎重噢!
如果啟動完畢的話,就執行 jps 檢查下各個容器是否如我們規劃的那樣配置完畢
 像我下面這種情況就是 OK 的:
 
 ③ 測試集群
后面來的,有添加端口映射,就不需要 nginx 代理啦!!!
最后的最后,就可以通過外網訪問了
 如果直接使用容器的 IP 進行訪問,大概是不行的(不知道是不是我裝了 nginx 的原因)
 但使用 nginx 進行代理卻很方便解決這個問題,下面是實現的步驟
先將安全組和防火墻的 9870,9868 以及 8088 端口打
 分別對應 NameNode SecondaryNameNode ResourceManager
然后讓 nginx 代理這三個端口,轉發到對應的 hadoop 容器完成訪問,如下:
server {listen 9870;server_name www.xxx.xxx;location / {proxy_pass http://hadoop001:9870;} }server {listen 9868;server_name www.xxx.xxx;location / {proxy_pass http://hadoop003:9868;} } server {listen 8088;server_name www.xxx.xxx;location / {proxy_pass http://hadoop002:8088;} }# 這里也是后面發現,然后回來填坑的,將對容器的訪問交給 nginx 代理 server {listen 9864;server_name www.xxx.xxx;location / {proxy_pass http://hadoop001:9864;} }最后在外網,直接通過 域名+端口號 就可以訪問到 hadoop 集群啦!!看到一下的頁面算成功(三張圖對應端口順序:9870,9868,8088)
后面上來的填坑,需要修改本機的 hosts 文件(想要詳細了解的,看下邊實操記錄哦)
位置:C:\Windows\System32\drivers\etc\hosts 在這里邊加上(域名可以是服務器和虛擬機的) 域名 hadoop001 域名 hadoop002 域名 hadoop003
 
接著使用一些簡單的功能測試一下:上傳文件到集群(在 hadoop001 中執行)
 每一步都可以在 9870 的 Browse Directory 窗口觀察:
 
下面這部分是實操記錄,已經對上文有做修改了,可以跳過這個黑框往下看
—————— 好叭,苦逼的我發現,文件內容預覽不了,到網上一查發現配少了個東西明明是一步步跟著視頻做的,不會又要等兩個小時把 v…v不過還好,只需要重啟 NameNode,步驟如下(當然我已經在前面有補充了,這里應該不用管)在 hdfs-site.xml 添加如下配置,然后分發到各個容器,再重啟就行了<property><name>dfs.webhdfs.enabled</name><value>true</value></property>—————— Why?怎么還是訪問不了?這時的我終于打開了控制臺,發現了這個:http://hadoop001:9864/webhdfs/v1/firstDir/test.txt?op=OPEN&namenoderpcaddress=hadoop001:8020&offset=0噢,秒懂了我們之前是使用 nginx 代理的,有提到不能直接使用容器名訪問但這個請求是自動發起的,怎么讓它依舊訪問到我們自己的服務器,讓 nginx 代理呢?這時候就需要修改本機的 hosts 文件了,改變域名和 IP 地址的映射關系位置:C:\Windows\System32\drivers\etc\hosts在這里邊加上:域名 hadoop001域名 hadoop002域名 hadoop003其中域名是服務器的 IP (當然也可以是虛擬機的)這一段表示,將三個容器的名稱都變成我們的域名,這樣就能成功地走我們服務器的代理啦當然了,有了這個,以后我們也可以直接通過容器名,訪問到上面列出來的三個頁面了(突然發現在寫這篇博客的過程中,收獲了很多網絡的知識呀 2333)最后的最后,當然是配置 nginx 啦(這里我也有補充在上面了~)server {listen 9864;server_name www.xxx.xxx;location / {proxy_pass http://hadoop001:9864;}}至此,測試完畢!
每一把刀,都插在恰到合適的位置(IceClean)
總結
以上是生活随笔為你收集整理的【Docker x Hadoop】使用 Docker 搭建 Hadoop 集群(从零开始保姆级)的全部內容,希望文章能夠幫你解決所遇到的問題。
 
                            
                        - 上一篇: AHU HuffmanTree编码数据结
- 下一篇: XML学习笔记 第二记
