胡必波,劉鐘凌,劉曉娟,焦花花
(廣州工商學(xué)院工學(xué)院,廣東 廣州 510850)
Docker 是一個開源的應(yīng)用容器引擎,讓開發(fā)者可以打包他們的應(yīng)用以及依賴包到一個可移植的容器中,然后發(fā)布到任何流行的 Linux 機(jī)器上,也可以實(shí)現(xiàn)虛擬化。容器是完全使用沙箱機(jī)制,相互之間不會有任何接口。當(dāng)前在Hadoop技術(shù)的發(fā)展中,如何把Docker技術(shù)應(yīng)用于Hadoop平臺的建立,尤其是對于Hadoop on Docker規(guī)模部署問題的解決,一直是一個備受關(guān)注的技術(shù)難點(diǎn)。以往Hadoop on Docker大數(shù)據(jù)平臺的部署,只在單機(jī)情況下實(shí)現(xiàn)過,而且過程繁瑣,耗時很長,而借助Docker作為優(yōu)化手段,在大規(guī)模多機(jī)器的情況下進(jìn)行一鍵部署,降低了企業(yè)安裝和使用的成本,是目前Hadoop系統(tǒng)架構(gòu)方面最受關(guān)注的技術(shù)熱點(diǎn)之一。
Docker不同于模擬硬件的虛擬機(jī),它是一種對進(jìn)程進(jìn)行隔離的虛擬化技術(shù),被隔離的進(jìn)程獨(dú)立于宿主操作系統(tǒng)和其他隔離的進(jìn)程。使用 Docker 可以不修改應(yīng)用程序代碼,就能夠?qū)F(xiàn)有的應(yīng)用程序部署在其他機(jī)器上,具有啟動速度快,占用資源少,部署方便,成本較低等優(yōu)勢,適于解決環(huán)境配置問題?;贒ocker的一鍵部署自底向上分為7個層次,如圖1所示。最底層為安裝Windows10操作系統(tǒng)的物理主機(jī)(宿主機(jī)),第二層安裝虛擬機(jī)軟件Wmware WorkStation 15,第三層定制Linux虛擬機(jī),第四層安裝Centos8操作系統(tǒng)的客戶機(jī),并安裝部署Docker 20.10.12服務(wù),第五層構(gòu)建用于集群Docker鏡像,第六層創(chuàng)建集群Docker容器,第七層部署Hadoop 2.7.2集群生態(tài)圈組件[1]。其中第三層Linux虛擬機(jī)和第一層Windows物理機(jī)采用NAT網(wǎng)絡(luò)模式,虛擬機(jī)要聯(lián)網(wǎng)得先通過宿主機(jī)才能和外面進(jìn)行通信,第六層Docker容器集群與第三層Linux虛擬機(jī)采用橋接模式,相對虛擬機(jī)和物理機(jī)所處網(wǎng)段,獨(dú)立為一個192.168.2.0虛擬網(wǎng)段。
圖1 基于Docker一鍵部署Hadoop集群
Docker 基礎(chǔ)鏡像是指一個包含最基本應(yīng)用的鏡像,通常只有最基本的 Linux 環(huán)境,和一些基礎(chǔ)的應(yīng)用。根據(jù)部署圖規(guī)劃按自底向上的順序,創(chuàng)建的Linux虛擬機(jī),安裝CentOS8操作系統(tǒng),修改主機(jī)名為node01,在網(wǎng)卡中設(shè)置固定IP地址:192.168.137.226,配置IP地址映射。下載docker-ce.repo后執(zhí)行“docker-ce-cli containerd.io --allowerasing”命令,成功安裝Docker后,還需要進(jìn)行鏡像倉庫源的配置,將官方公共倉庫Docker Hub替換為國內(nèi)的公共倉庫,例如阿里云、網(wǎng)易源等,便于加快鏡像拉取速度。Docker鏡像含有啟動容器所需要的文件系統(tǒng)及其內(nèi)容,用于創(chuàng)建并啟動容器。在分層構(gòu)建機(jī)制中,最底層為bootfs,用于系統(tǒng)引導(dǎo)的文件系統(tǒng),例如aufs、overlay2等,容器啟動完成之后會被卸載以節(jié)約內(nèi)存資源。位于bootfs之上一層是rootfs,為docker容器的根文件系統(tǒng)。rootfs由內(nèi)核掛載為“只讀”模式,而后通過“聯(lián)合掛載”技術(shù)額外掛載一個“可寫”層。執(zhí)行“docker pull centos:centos8.2.2004”命令,拉取最小化基礎(chǔ)鏡像(FROM scratch)。
執(zhí)行“docker run -it centos:centos8.2.2004 /bin/bash”命令,創(chuàng)建一個ID 為d7a9959168b5的容器。Docker支持四種網(wǎng)絡(luò)模式分別是 bridge,默認(rèn)網(wǎng)絡(luò)模型,Docker啟動后默認(rèn)會創(chuàng)建一個docker0網(wǎng)橋,默認(rèn)創(chuàng)建的容器也是添加到這個網(wǎng)橋中;host,容器和宿主機(jī)共享一個網(wǎng)絡(luò)名稱空間Network namespace;container,和已經(jīng)存在的容器使用同一個網(wǎng)絡(luò)名稱空間,網(wǎng)卡配置也都是相同的;none,不為容器進(jìn)行任何網(wǎng)絡(luò)配置。執(zhí)行“ping 192.168.2.1”命令,查看該容器是否能夠ping通網(wǎng)橋,執(zhí)行“ping www.baidu.com”命令,查看該容器是否能夠ping通外網(wǎng)。
Secure Shell(SSH)是由 IETF制定的建立在應(yīng)用層基礎(chǔ)上的安全網(wǎng)絡(luò)協(xié)議。它采用了非對稱加密技術(shù)(RSA)加密了所有傳輸?shù)臄?shù)據(jù),并提供基于口令的安全驗(yàn)證和基于密鑰的安全驗(yàn)證兩種級別的驗(yàn)證方法。與第一種級別相比,采用第二種級別不僅加密所有傳輸?shù)臄?shù)據(jù),也不需要在網(wǎng)絡(luò)上傳送口令,因此安全性更高,可以有效防止中間人攻擊。由于Hadoop集群節(jié)點(diǎn)比較多且頻繁,需要在這些節(jié)點(diǎn)之間執(zhí)行指令時采用無須輸入密碼的認(rèn)證方式。執(zhí)行“ssh-keygen -t rsa”命令,連續(xù)按4次回車,生成兩個文件id_rsa(私鑰)、id_rsa.pub(公鑰),可在隱藏文件夾/root/.ssh/下查看上述兩個文件,再執(zhí)行“ssh-copy-id node01”命令復(fù)制.ssh/id_rsa.pub 至遠(yuǎn)程主機(jī)節(jié)點(diǎn)的.ssh /authorized _ keys 文 件中,實(shí)現(xiàn)集群任意兩節(jié)點(diǎn)的無密碼登錄。Docker 提供兩種制作鏡像的方法:一種是基于官方鏡像,按照生產(chǎn)環(huán)境的需求編寫 Dockerfile文件,以此作為依據(jù)生成新的鏡像;另一種是基于官方鏡像創(chuàng)建容器后進(jìn)行相關(guān)環(huán)境的部署,然后使用commit命令將配置好的容器封裝成一個新的鏡像。執(zhí)行“docker commit d7a9959168b5 centos8_ssh”命令,將配置好的容器保存為一個新鏡像[2]。圖2為 Docker容器網(wǎng)絡(luò)連接示意圖。
圖2 Docker容器網(wǎng)絡(luò)連接
Hadoop是一個由Apache基金會開發(fā)的開源軟件,具有可靠性、擴(kuò)展性的分布式的計(jì)算存儲系統(tǒng)。Hadoop的框架核心的設(shè)計(jì)是HDFS、MapReduce,其中HDFS為海量的數(shù)據(jù)提供了存儲,而MapReduce為海量的數(shù)據(jù)提供了計(jì)算。Hadoop2.0以后MapReduce1.0中的資源管理調(diào)度功能,被單獨(dú)分離出來形成了YARN,它是一個純粹的資源管理調(diào)度框架,而不是一個計(jì)算框架。被剝離了資源管理調(diào)度功能的MapReduce 框架就變成了MapReduce2.0,它是運(yùn)行在YARN之上的一個純粹的計(jì)算框架,不再自己負(fù)責(zé)資源調(diào)度管理服務(wù),而是由YARN為其提供資源管理調(diào)度服務(wù)[3-5]。
Docker數(shù)據(jù)卷的設(shè)計(jì)目的就是數(shù)據(jù)的持久化,可用于持續(xù)存儲或共享數(shù)據(jù)。數(shù)據(jù)卷完全獨(dú)立于容器的生命周期,docker不會在刪除容器時刪除其掛載的數(shù)據(jù)卷。執(zhí)行“docker run -v /usr/local/myshare/nn01:/usr/local/dfs/centos8_ssh /usr/sbin/sshd -D”命令,重啟一個ID為64f2889ebb77新容器。將Hadoop安裝包解壓到虛擬機(jī)node01的/usr/local目錄下,修改/hadoop/etc/hadoop/目錄下core-site.xml、hadoop-env.sh、hdfs-site.xml等配置文件后,掛載到Docker容器映射目錄/usr/local/myshare下,執(zhí)行“cp -r hadoop /usr/local/”命令,復(fù)制到容器/usr/local目錄下。執(zhí)行“./hdfs namenode -format”命令格式化,執(zhí)行“./start-dfs.sh”命令,啟動hdfs集群測試。執(zhí)行“docker commit 64f2889ebb77 centos8_hadoop:v3”命令,將配置好的容器保存為一個新鏡像。執(zhí)行“./hdfs.sh”腳本命令后,部署效果如圖3所示,實(shí)現(xiàn)一鍵部署HDFS集群的hdfs.sh腳本代碼如下:
圖3 一鍵部署HDFS
#!/bin/bash
#刪除本機(jī)已有的容器,防止和新啟動的容器沖突
……
#創(chuàng)建Bridge網(wǎng)絡(luò)cluster_bridge,并設(shè)置子網(wǎng)
bridge_name=cluster_bridge
……
#指定鏡像名
IMG=centos8_hadoop
#腳本第一個參數(shù)為集群節(jié)點(diǎn)個數(shù),賦值給total_node_num(默認(rèn)值為1)
total_node_num=1
……
host_node="node01"
#設(shè)置集群的起始IP為192.168.2.1,cluster_bridge設(shè)備地址占用
start_ip=192.168.2.1
#獲取起始IP的前綴,即192.168.2
……
node_num=0
#循環(huán)執(zhí)行total_node_num次
let start_ip_num++
node_name="nn01"
#合成容器IP
nn01_ip=${ip_prefix}.${start_ip_num}
cmd="docker run --network $bridge_name --ip $nn01_ip --add-host $host_node:$start_ip -h $node_name --name $node_name -v /usr/local/myshare/$node_name:/usr/local/dfs -p 50070∶50070 $IMG /usr/sbin/sshd -D"
$cmd &
echo $cmd
#刪除原有從節(jié)點(diǎn)文件
rm slaves
#echo $node_name >> workers
while [ $i -lt $total_node_num ]
do
#start_ip_num加一
let start_ip_num++
#node_num加一
let node_num++
#合成節(jié)點(diǎn)主機(jī)名
node_name="dn"$node_num
#合成容器IP
container_ip=${ip_prefix}.${start_ip_num}
#創(chuàng)建Host上的映射目錄,每個容器會在Host的/usr/local/myshare下主機(jī)名目錄,以此映射到容器的/usr/local/dfs/datanode下
mkdir -p /usr/local/myshare/$node_name
#合成容器啟動命令,命令末行傳入兩個參數(shù),用來測試容器默認(rèn)程序,能否接收用戶參數(shù)
cmd="docker run --network $bridge_name --ip $container_ip --add-host $host_node:$start_ip -h $node_name --name $node_name -v /usr/local /share/$node_name:/usr/local/dfs $IMG /usr/sbin/sshd -D"
echo $cmd
#運(yùn)行容器
$cmd &
#等待1秒啟動下一個容器
sleep 1
let i++
echo $node_name >>slaves
done
sleep 15
#重新設(shè)置從節(jié)點(diǎn)文件
scp slaves ${nn01_ip}:/usr/local/hadoop/etc/hadoop/
#啟動HDFS集群
ssh $nn01_ip "cd /usr/local/hadoop;./sbin/start-dfs.sh"
執(zhí)行“./hdfs.sh 1”腳本命令,啟動ID為7013a665bd3a新容器。切換到/usr/local目錄下,修改/hadoop/etc/hadoop/目錄下yarn-env.sh、mapred-site.xml、yarn-site.xml等配置文件后,執(zhí)行“docker commit 7013a665bd3a centos8_hadoop:v4”,將配置好的容器保存為一個新鏡像。容器中可以運(yùn)行一些網(wǎng)絡(luò)應(yīng)用,要讓外部也可以訪問這些應(yīng)用,可以通過 -P(大寫)或 -p (小寫)參數(shù)來指定端口映射。執(zhí)行“.yarn.sh”腳本命令后,實(shí)現(xiàn)一鍵部署YARN集群的yarn.sh腳本代碼與hdfs.sh腳本代碼類似,YARN集群服務(wù)需要映射8088端口,日志服務(wù)需要映射19888端口,腳本末尾增加兩行啟動YARN集群代碼如下:
#!/bin/bash
……
cmd="docker run --network $bridge_name --ip $nn01_ip --add-host $host_node:$start_ip -h $node_name --name $node_name -v /usr/local/myshare/$node_name:/usr/local/dfs -p 50070∶50070 -p 8088∶8088 -p 19888∶19888 $IMG /usr/sbin/sshd -D"
……
ssh $nn01_ip " cd /usr/local/hadoop;./sbin/mr-jobhistory-daemon.sh start historyserver"
ssh $nn01_ip " cd /usr/local/hadoop;./sbin/start-yarn.sh"
在系統(tǒng)部署前先進(jìn)行集群規(guī)劃,然后再定制Linux虛擬機(jī)并采用NAT網(wǎng)絡(luò)模式安裝Centos8客戶機(jī)操作系統(tǒng),完成更新安裝源、卸載防火墻、配置固定IP地址以及SSH無密碼登錄等基礎(chǔ)操作,如果帶圖形化界面安裝還需要先刪除 podman組件,避免和Docker發(fā)生沖突。安裝Docker后可選擇阿里云、網(wǎng)易源等鏡像倉庫源完成鏡像加速。以橋接模式啟動容器后,需要保證容器所在網(wǎng)段與Host宿主機(jī)所在的網(wǎng)段網(wǎng)絡(luò)暢通并可連接外網(wǎng)[6,7]。Hadoop一鍵安裝部署圍繞HDFS集群和YARN集群展開。Docker容器對于宿主機(jī)器來說只是一個運(yùn)行在Linux上的應(yīng)用,因此它的數(shù)據(jù)存儲還是會依賴宿主機(jī)器,Docker是通過掛載宿主機(jī)文件系統(tǒng)或內(nèi)存的方式來實(shí)現(xiàn)數(shù)據(jù)存儲,掛載方式有3種:volume,bind mount和tmpfs。
bind mounts(綁定掛載)可以存儲在宿主機(jī)器任何一個地方,依賴宿主機(jī)器的目錄結(jié)構(gòu),非docker進(jìn)程和docker進(jìn)程都可以修改該路徑下的文件。使用綁定安裝時,會將主機(jī)上的文件或目錄安裝到容器中,文件或目錄由主機(jī)上的完整或相對路徑引用,該文件或目錄不需要在Docker主機(jī)上已經(jīng)存在,如果不存在,則按需創(chuàng)建。bind mounts性能非常好,因此一鍵部署時可通過bind mount方式完成Hadoop集群的數(shù)據(jù)持久化存儲,確保集群數(shù)據(jù)不會丟失。Hadoop on Docker規(guī)模一鍵快速部署可以在一個虛擬機(jī)上,使用一個命令快速構(gòu)建指定數(shù)量的HDFS、YARN集群。與傳統(tǒng)VMware部署上百集群相比,它只需要一個存儲鏡像即可部署上萬集群,具有靈活方便、開銷更小、效率更高、可擴(kuò)展性強(qiáng)等優(yōu)勢,在Hadoop on Docker基礎(chǔ)上,后續(xù)可在學(xué)習(xí)和生產(chǎn)環(huán)境下實(shí)現(xiàn)任意節(jié)點(diǎn)HBase,Hive,Spark等生態(tài)圈組件一鍵部署。