【Docker x Hadoop】使用 Docker 搭建 Hadoop 集群(從零開始保姆級)



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)	首先拉取 centos
	docker pull centos

2)	創建一個 centos
!!!	后來補充,在這里添加端口映射,hadoop001 要用到的端口是: 98708020,主機端口自定義

	docker run --privileged=true --name=hadoop001 -p xxx:9870 xxx:8020 -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 文件內容如下

# Java
export JAVA_HOME=<jdk在容器的路徑>
export PATH=$PATH:$JAVA_HOME/bin

# Hadoop
export HADOOP_HOME=<hadoop在容器的路徑>
export PATH=$PATH:$HADOOP_HOME/bin
export PATH=$PATH:$HADOOP_HOME/sbin

# Constant
export HDFS_NAMENODE_USER=root
export HDFS_DATANODE_USER=root
export HDFS_SECONDARYNAMENODE_USER=root
export YARN_RESOURCEMANAGER_USER=root
export YARN_NODEMANAGER_USER=root

第一第二個是兩個環境,最后一個是一些常量,在啟動集群的時候,還要用到這些常量,否則可能啟動失敗
最后執行 source /etc/profile 使配置文件生效


3. 配置允許外界通過 ssh 連接容器

我們需要讓各個容器產生聯系,才能構成集群,但默認情況下,容器並不能被其他容器直接通過 ssh 訪問,所以這里需要配置

1)	首先需要設置密碼(輸入以下命令,回車設置密碼即可)
	passwd root
	大概率會提示沒有該命令,就得下載它,然后再設置就好了
	yum install passwd

2)	然后下載 ssh,以下三步(安裝了服務端和客戶端)
	yum install openssh
	yum install openssh-server
	yum install openssh-clients

3)	然后檢查配置文件,查看以下兩個配置是否一樣(默認應該都是這樣的)
	vim /etc/ssh/sshd_config
	  PermitRootLogin yes
	  PasswordAuthentication yes
	這兩個配置允許外網通過 ssh 連接該服務器(容器)

4)	如果發現不是這樣,就修改它,同時需要重啟 ssh 是指生效
	service sshd restart
	同樣該命令可能不存在,就下載它
	yum install initscripts

通過上面一頓操作,外網已經可以通過 ssh 訪問該容器了,我們可以試試:

1)	首先在容器內,使用 ifconfig 查看 IP 地址
	ifconfig
	沒有這個命令的話,就下載他[doge]
	yum install net-tools

2)	在服務器本機中,通過 ssh 訪問該 IP 地址嘗試連接
	ssh <IP>
	然后要求輸入密碼,就是上面我們已經設置了的密碼

ohhh 然后我們會發現,成功進入容器內部了,這次時通過 ssh 而不是通過 docker 了
在這里插入圖片描述


4. 由該容器克隆出多個容器

首先要克隆出多個容器,就需要將該容器打包成鏡像,再由該鏡像創建出多個容器,步驟如下:

1)	創建鏡像
	docker commit -a='IceClean' -m='Hadoop cluster example through docker by IceClean' 5a8 hadoop-docker

2)	由該進項克隆多個容器模擬集群(這里以三台服務器的集群為例)
!!!	后來補充: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/pipework
	cp ~/pipework/pipework /usr/local/bin/

2)	安裝 bridge-utils
	yum -y install bridge-utils

3)	創建網絡(這里 IP 地址自定義)
	brctl addbr br0
	ip link set dev br0 up
	ip addr add 172.16.10.1 dev br0

4)	為各個容器設置固定的 IP
	pipework br0 <容器名> IP/掩碼,如:
	pipework br0 hadoop001 172.16.10.10/24
	pipework br0 hadoop002 172.16.10.11/24
	pipework br0 hadoop003 172.16.10.12/24

5)	測試這幾個 IP 是否可用
	ping 172.16.10.10

6)	中途如果不小心操作錯了(比如說我--),想刪除網絡或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 hadoop001
		172.16.10.11 hadoop002
		172.16.10.12 hadoop003

3)	配置完畢后,我們就可以直接通過名字輕松連接各個容器了,如:
	ssh hadoop003

5. 為各個容器配置 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 的公鑰拷貝到 hadoop002
	ssh-copy-id hadoop002

出現這個提示說明添加成功了,以后我們可以直接通過 ssh hadoop002 連接 hadoop002
在這里插入圖片描述
注意啦:公鑰也需要拷貝到本服務器(如 hadoop001 將自己的公鑰拷貝到 hadoop001)不然自己五大免密登錄自己哦

然后對於其他的容器也是這樣做,把每個容器的公鑰都拷貝到自己以及另外兩台服務器上,就實現了三台服務器互相的免密登錄,完畢~


6. 開始編寫集群配置

前面做足了准備工作,把每一個容器都配置好了
現在要正式開始集群的搭建啦,首先是集群的配置:

安排一下集群的部署:

hadoop001 hadoop002 hadoop003
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 文件夾(如果不存在的話,會自動創建)

<configuration>
    <!-- 指定 NameNode 地址 -->
    <property>
        <name>fs.defaultFS</name>
        <value>hdfs://hadoop001:8020</value>
    </property>

    <!-- 指定 hadoop 數據存放的目錄 -->
    <property>
        <name>hadoop.tmp.dir</name>
        <value>/home/hadoop/hadoop-3.1.3/data</value>
    </property>
</configuration>

然后配置 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 也同理)

scp core-site.xml hdfs-site.xml yarn-site.xml mapred-site.xml root@hadoop002:/home/hadoop/hadoop-3.1.3/etc/hadoop

③ 配置 workers

同樣是在 hadoop001 中,修改文件 /etc/hadoop/workers
將里邊的內容去掉(把 localhost 刪掉)然后換成我們的三個容器:
注意:行末不能有空格,以及不能有空行的出現

hadoop001
hadoop002
hadoop003

然后將該文件同步到其他兩個容器

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

初始化完畢后,在配置文件指定的目錄下,就會生成 datalogs 兩個文件

———— 接下來正式啟動

① 首先啟動 DFS:
在 Hadoop001 中操作(配置了 NameNode 的)

進入 sbin,執行 ./start-dfs.sh 命令
然后執行 jps 看是否啟動成功,和下圖一樣說明成功了
在這里插入圖片描述
如果上面的配置都沒有出錯的話,這里應該是很順利就啟動的了
可能出現的錯誤有:
1、沒有配置免密登錄,權限不足導致啟動失敗
2、只把公鑰給了其他容器,沒有給自己,也會導致權限不足的失敗
所以說,免密登錄在這里,還是非常非常重要的!!!

② 然后啟動 YARN:
在 Hadoop002 中操作(配置了 ResourceManager的)

依舊在 sbin 中執行 ./start-yarn.sh
這個步驟,如果服務器性能不太行的話,會卡死(像我這樣—_—卡了兩個小時)
九點卡到十一點
從晚上九點卡到十一點,還好沒放棄 2333
不過在這里也要提醒一下,卡的時候還是經量別強制重啟服務器,就像我下午三點多那次,強制重啟導致集群出了點問題跑不起來,最后是清空了數據再重啟才解決的,慎重噢!

當時出現的錯誤,是這個
ssh: connect to host master port 22: No route to host

找了好久的解決方案,都是說什么防火牆、沒固定 IP,沒網等等的情況
但我這些都沒問題,還是不行,最后就只能重啟了(后來者如果出了這個問題,有解決方案的,也可以分享一下哦)

如果啟動完畢的話,就執行 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 窗口觀察:
在這里插入圖片描述

1)	創建文件夾(注意這里的根路徑 '/' 是指集群的根路徑,往后都是按照這個根路徑來)
	hadoop fs -mkdir /firstDir

2)	上傳文件(隨便上傳一個,一下表示將 README.txt 上傳到集群根目錄下的 firstDir 文件夾)
	hadoop fs -put README.txt /firstDir

3)	點擊文件,可以查看和下載文件,至此測試完畢(還存在問題的話,可以看下面黑框)

4)	執行 wordcount 函數,並將結果保存在 output 文件夾中
	

下面這部分是實操記錄,已經對上文有做修改了,可以跳過這個黑框往下看

——————	好叭,苦逼的我發現,文件內容預覽不了,到網上一查發現配少了個東西
		明明是一步步跟着視頻做的,不會又要等兩個小時把 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)


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM