前言
和小伙伴的一起參加的人工智能比賽進入了決賽之后的一段時間里面箭券,一直在構(gòu)思將數(shù)據(jù)預處理過程和深度學習這個階段合并起來净捅。然而在合并這兩部分代碼的時候,遇到了一些問題辩块,為此還特意寫了腳本文件進行處理』琢現(xiàn)在比賽過去,我覺得應該把這部分的東西寫出來废亭,看看是否有其他朋友會遇到這方面問題国章,希望對他們有幫助。如有不對之處豆村,請大家指正捉腥,謝謝!
比賽遇到的集群各節(jié)點的部署痛點
一個前提
在初賽的時候你画,為了快捷提供數(shù)據(jù)接口給后面的深度學習模型建立使用抵碟,我們將數(shù)據(jù)預處理獨立出來,使用了最為簡單的Python操作坏匪。在此拟逮,考慮到的是,我們的代碼需要移植到評委所用的電腦當中進行驗證适滓,可能存在沒有import某些庫的情況敦迄,最后導致程序運行失敗。
麻煩之處
在進入到?jīng)Q賽后,由于這兩塊的結(jié)合在一起的迫切需求罚屋,我們不得不又重新import我們庫苦囱。然而在這塊當中,如果我們只在Master節(jié)點脾猛,問題很簡單撕彤,直接將庫打包好,寫個腳本就完事了猛拴。而在百度的BMR的spark集群里面羹铅,因為Slaves節(jié)點不能訪問網(wǎng)絡(如下圖),因而我們要登錄了Master節(jié)點之后愉昆,然后通過Master內(nèi)網(wǎng)ssh到Slaves上职员,進而才能打開我們的腳本部署好我們的程序運行環(huán)境。
提出
這樣子來說跛溉,我們有沒有一個很好的辦法焊切,能通過Master上運行一個腳本,達到了整個集群的所有節(jié)點都自動部署我們的程序運行環(huán)境呢芳室?經(jīng)過閱讀書籍《spark最佳實踐》专肪,了解到了Python的第三方庫fabric。
fabric
首先請允許介紹一下fabric渤愁,具體使用方法可以查閱官方API Doc牵祟,在此我介紹一下我將使用到某一小部分深夯。
執(zhí)行本地任務
fabric提供了一個local("shell")
的接口抖格,shell就是Linux上的shell命令。例如
from fabric.api import local
local('ls /root/') #ls root文件夾下的文件列表
執(zhí)行遠程任務
fabric的強大之處咕晋,不是它在本地做到執(zhí)行命令雹拄,本地執(zhí)行的事兒可以用原生shell來解決,而是能在遠程的服務器上執(zhí)行命令掌呜,哪怕遠程的服務器上沒有安裝fabric滓玖。它是通過ssh方式實現(xiàn)的,因而我們需要定義一下三個參數(shù):
env.hosts = ['ipaddress1', 'ipaddress2']
env.user = 'root'
env.password = 'fuckyou.'
通過設(shè)置ip质蕉,用戶名以及用戶名密碼势篡,我們可以使用run("shell")
,達到在遠程服務器上執(zhí)行我們所需要執(zhí)行的任務模暗。例如
from fabric.api import run, env
env.hosts = ['ipaddress1', 'ipaddress2']
env.user = 'root'
env.password = 'fuckyou.'
run('ls /root/') #ls root文件夾下的文件列表
打開某一個文件夾
有時候我們需要精準地打開某一個文件夾禁悠,之后執(zhí)行該文件下的某一個腳本或者文件。這是兑宇,我們得使用以下兩個接口:
本地
with lcd('/root/local/'):
local('cat local.txt') # cat 本地'/root/local/'下的local.txt文件
遠程
with cd('/root/distance/'):
run('cat distance.txt') # cat 遠程'/root/distance/'下的distance.txt文件
執(zhí)行fabric任務
我們可以通過命令行
fab --fabfile=filename.py job_func
# filename.py為使用fabric寫的Python文件
# job_func 為帶有fabric的函數(shù)碍侦,即主要執(zhí)行的函數(shù)
# 以上兩個名稱都是可以自取,下面的介紹當中,我的為job.py 與 job
socket
為什么會用到socket呢瓷产?在上一篇文章當中站玄,我提及到在百度BMR的集群中,他們設(shè)置集群Slaves都是通過slaves的hostname的濒旦,而不是通過ip株旷。而因為在使用fabric設(shè)置環(huán)境中的hosts的時候需要用到ip,那我們得通過hostname疤估,進而找到ip灾常。
你或許有疑問,為什么不直接設(shè)定Slaves的IP呢铃拇?但是百度BMR每次創(chuàng)建spark集群钞瀑,它提供的內(nèi)網(wǎng)IP都是不斷在變動的,呈現(xiàn)出IP末端遞增慷荔。
綜上雕什,還是使用hostname獲取IP
gethostbyname接口
我們可以用過gethostbyname('hostname')
接口,傳入hostname显晶,然后得到一個IPV4的ip地址贷岸。
使用fabric編寫各節(jié)點自動部署腳本
獲取Slaves的hostname
和上一篇文章說道的一樣,我們Slaves的hostname是藏在了百度BMR的這里:
'/opt/bmr/hadoop/etc/hadoop/slaves'
將hostname轉(zhuǎn)化為ip磷雇,設(shè)置fabric的env參數(shù)
host_list = []
f = open(path, 'r')
slaves_name = f.read().split('\n')
for i in range(1, slaves_name.__len__()-1):
temp_name = slaves_name[i]
temp_ip = socket.gethostbyname(temp_name)
ip_port = temp_ip + ":22"
host_list.append(ip_port)
del temp_name
del temp_ip
del ip_port
env.user = 'root'
env.password = '*gdut728'
env.hosts = host_list
編寫需要自動部署的job
在這里偿警,我要自動部署的是:
1 下載Python第三方庫jieba
2 在本地解壓下載好的jieba壓縮包
3 在本地,進入到解壓好的文件夾中唯笙,安裝jieba
4 將下載好的壓縮包傳送到Slaves節(jié)點上
5 在遠程端螟蒸,解壓下載好的jieba壓縮包
6 在遠程端,進入到解壓好的文件夾中崩掘,安裝jieba
將上面步驟轉(zhuǎn)化為代碼七嫌,即
def job():
local_command = "wget https://pypi.python.org/packages/71/46/c6f9179f73b818d5827202ad1c4a94e371a29473b7f043b736b4dab6b8cd/jieba-0.39.zip#md5=ca00c0c82bf5b8935e9c4dd52671a5a9"
local(local_command)
jieba_unzip = "unzip jieba-0.39.zip"
jieba_path = "/root/jieba-0.39/"
jieba_install = "python setup.py install"
local(jieba_unzip)
with lcd(jieba_path):
local("ls")
local(jieba_install)
with lcd('/root/'):
put("jieba-0.39.zip", '/root')
run(jieba_unzip)
with cd(jieba_path):
run("ls")
run(jieba_install)
結(jié)言
最后,在我上篇文章提到的shell腳本中苞慢,最前面加上
yum -y install fabric && fab --fabfile=job.py job
輸入./start-hadoop-spark.sh
诵原,即可無憂無慮地部署好我要使用的程序運行環(huán)境。因為懶挽放,因為麻煩绍赛,于是用Python外加shell寫了自動部署的腳本。在這個過程中辑畦,學習到不少知識吗蚌,也遇到不少麻煩,寫下文章航闺,希望可以減輕大家配置的煩惱~
結(jié)果如下:
Master:
Slaves1:
Slaves2:
參照
Fabric 中文文檔 http://fabric-chs.readthedocs.io/zh_CN/chs/
Python遠程部署利器Fabric詳解 http://python.jobbole.com/87241/
socket.gethostbyname() https://docs.python.org/2/library/socket.html#socket.gethostbyname
文章出自kwongtai'blog[http://www.reibang.com/u/468497adc52c]褪测,轉(zhuǎn)載請標明出處猴誊!