
搞過Hadoop集群的人都清楚第一次啟動(dòng)分布式節(jié)點(diǎn)時(shí)最煩的就是每臺(tái)機(jī)器都要輸密碼。不管你是用sbin/start-dfs.sh啟動(dòng)HDFS還是跑一條MapReduce任務(wù)只要腳本涉及跨節(jié)點(diǎn)遠(yuǎn)程執(zhí)行命令就會(huì)卡在“Password”的提示上。尤其是三層結(jié)構(gòu)跑起來之后NameNode要跟每臺(tái)DataNode通信一次啟動(dòng)輸十幾次密碼手都酸而且腳本后臺(tái)執(zhí)行根本沒法交互輸入。這時(shí)候給Hadoop用戶配好SSH免密登錄就是正兒八經(jīng)的剛需。這篇文章主要圍繞“為hadoop用戶配置SSH免密登錄”這件事把原理、實(shí)操步驟、權(quán)限細(xì)節(jié)、常見坑全部拆開講。適合剛剛搭好Hadoop集群的小白也適合在運(yùn)維過程中想重新梳理SSH配置的人??赐昴悴粌H能照著敲命令配好還能明白為什么目錄權(quán)限差一點(diǎn)都不行以及遇到“免密失效”“連接被拒絕”時(shí)該從哪里下手排查。1. 理解需求為什么Hadoop一定要配免密登錄1.1 從NameNode到DataNode的巡檢式通信先說一個(gè)最核心的場(chǎng)景。Hadoop集群?jiǎn)?dòng)之后主節(jié)點(diǎn)NameNode、ResourceManager需要主動(dòng)連接到從節(jié)點(diǎn)DataNode、NodeManager去執(zhí)行一些遠(yuǎn)端命令比如啟動(dòng)DataNode進(jìn)程、刷新節(jié)點(diǎn)狀態(tài)、做元數(shù)據(jù)檢查。這個(gè)連接不是用戶手動(dòng)敲的而是腳本里通過ssh hostname去觸發(fā)的。如果每臺(tái)機(jī)器都需要密碼那腳本在執(zhí)行到遠(yuǎn)程部分時(shí)就僵住了。尤其是start-dfs.sh它會(huì)遍歷slaves文件里列出的每一個(gè)節(jié)點(diǎn)逐個(gè)嘗試SSH連接。以前我見過有人在非交互環(huán)境下配錯(cuò)了密鑰結(jié)果啟動(dòng)腳本卡在某個(gè)節(jié)點(diǎn)上半個(gè)小時(shí)最后超時(shí)失敗日志里全是“Permission denied, please try again.”。所以免密登錄是Hadoop偽分布式和全分布式集群能夠正常啟動(dòng)、管理的前提不是可選項(xiàng)。1.2 公鑰認(rèn)證原理簡(jiǎn)單回顧SSH免密登錄本質(zhì)上是基于公鑰加密的身份認(rèn)證??蛻舳松梢粚?duì)密鑰公鑰放到服務(wù)端的~/.ssh/authorized_keys文件里私鑰留在客戶端。當(dāng)客戶端發(fā)起SSH連接時(shí)服務(wù)端會(huì)拿著公鑰去驗(yàn)證客戶端的身份如果匹配通過就不再要求輸密碼了。這個(gè)過程中權(quán)限是個(gè)極其敏感的校驗(yàn)條件。OpenSSH對(duì)密鑰文件和.ssh目錄的權(quán)限有嚴(yán)格檢查如果權(quán)限過寬比如authorized_keys被設(shè)為644以外的“其他人可寫”狀態(tài)服務(wù)端會(huì)直接忽略這個(gè)文件哪怕你的公鑰內(nèi)容完全正確也會(huì)退回密碼登錄。這個(gè)問題我在后面詳細(xì)講。提示這里說的都是Hadoop用戶自己的配置不要?jiǎng)酉到y(tǒng)里root的SSH配置。Hadoop的守護(hù)進(jìn)程如果以hadoop用戶運(yùn)行那么免密登錄就是hadoop用戶的事配錯(cuò)賬號(hào)會(huì)引發(fā)權(quán)限混亂。2. 準(zhǔn)備工作與約定2.1 集群角色與網(wǎng)絡(luò)規(guī)劃在動(dòng)手前先把角色理清。你需要確認(rèn)誰(shuí)是客戶端誰(shuí)是服務(wù)端。在Hadoop集群里通常有三類節(jié)點(diǎn)NameNode / ResourceManager作為主節(jié)點(diǎn)需要免密SSH到所有從節(jié)點(diǎn)執(zhí)行遠(yuǎn)程命令。DataNode / NodeManager作為從節(jié)點(diǎn)一般不需要反向免密??蛻舳斯?jié)點(diǎn)提交作業(yè)的機(jī)器如果你經(jīng)常手動(dòng)ssh到集群其他節(jié)點(diǎn)也可以一并配置。但為了省事我建議在一個(gè)集群里把所有機(jī)器的hadoop用戶都互相配好免密至少?gòu)母髦鞴?jié)點(diǎn)到各從節(jié)點(diǎn)要通。假設(shè)集群有三臺(tái)機(jī)器master01、worker01、worker02操作系統(tǒng)為L(zhǎng)inux使用同一個(gè)hadoop用戶名并且已用相同的hadoop用戶登錄所有機(jī)器。網(wǎng)絡(luò)層先確認(rèn)機(jī)器之間可以互ping/etc/hosts里也寫好了主機(jī)名映射。2.2 確認(rèn)基礎(chǔ)環(huán)境確認(rèn)以下兩點(diǎn)再開始所有機(jī)器都裝了openssh-server并且SSH服務(wù)已啟動(dòng)。用systemctl status sshd查看如果沒有安裝就先用yum install -y openssh-serverDebian系是apt install openssh-server裝好。每臺(tái)機(jī)器上hadoop用戶的home目錄/home/hadoop存在且hadoop用戶可以正常登錄。如果還沒有創(chuàng)建用戶先執(zhí)行useradd hadoop passwd hadoop。另外建議先手動(dòng)用密碼登錄一遍所有機(jī)器把known_hosts文件生成出來這樣后續(xù)配置過程中能少遇到host key確認(rèn)的干擾。我這套流程是在常見的Linux發(fā)行版上跑的Mac系統(tǒng)略有差異但核心邏輯一樣。3. 核心實(shí)操一步步配置免密登錄3.1 生成密鑰對(duì)登錄到master01機(jī)器并切換到hadoop用戶或者直接用hadoop用戶登錄審計(jì)。然后執(zhí)行su - hadoop ssh-keygen -t rsa -b 4096 -P -f ~/.ssh/id_rsa參數(shù)里-P 表示私鑰文件不設(shè)置密碼這樣后續(xù)腳本自動(dòng)連接時(shí)不需要再手動(dòng)輸入私鑰口令。如果這里你設(shè)置了密碼那免密就會(huì)變成“免輸賬號(hào)密碼但要輸私鑰密碼”等于沒免。-f指定生成路徑放在hadoop用戶的.ssh目錄下。執(zhí)行完成后確認(rèn)ls -l ~/.ssh/你會(huì)看到id_rsa私鑰和id_rsa.pub公鑰兩個(gè)文件。注意集群規(guī)模大或者安全意識(shí)強(qiáng)的環(huán)境里有人會(huì)傾向給私鑰加口令并配合ssh-agent。但在Hadoop自動(dòng)化場(chǎng)景里腳本執(zhí)行是非交互式的加密私鑰會(huì)導(dǎo)致agent被發(fā)布后無法自動(dòng)解鎖非常麻煩。生產(chǎn)環(huán)境如果一定要加需要配上ssh-agent和ssh-add并把密碼預(yù)置到keychain里這個(gè)復(fù)雜度不建議新手碰。3.2 分發(fā)公鑰并配置authorized_keys現(xiàn)在你的master01上有公鑰需要把公鑰內(nèi)容追加到所有目標(biāo)機(jī)器hadoop用戶的~/.ssh/authorized_keys中。包括它自己也要配一份因?yàn)橛行┠_本也會(huì)往本機(jī)做SSH循環(huán)。最簡(jiǎn)單的辦法是使用ssh-copy-id它在Linux下默認(rèn)自帶很好用ssh-copy-id hadoopmaster01 ssh-copy-id hadoopworker01 ssh-copy-id hadoopworker02執(zhí)行這個(gè)過程時(shí)會(huì)要求輸入一次hadoop用戶在目標(biāo)機(jī)器上的密碼輸入后工具會(huì)自動(dòng)把公鑰追加到對(duì)方~/.ssh/authorized_keys并做權(quán)限收斂。一切正常后驗(yàn)證一下ssh hadoopworker01 echo ok: $(hostname)如果直接輸出ok: worker01說明master01到worker01的免密已經(jīng)通了。如果ssh-copy-id不可用也可以手工方式。一條命令完成cat ~/.ssh/id_rsa.pub | ssh hadoopworker01 mkdir -p ~/.ssh cat ~/.ssh/authorized_keys需要注意如果是第一次連接會(huì)彈出Are you sure you want to continue connecting (yes/no)輸入yes。這種方式不會(huì)自動(dòng)收斂權(quán)限你之后需要到每一臺(tái)機(jī)器上手動(dòng)執(zhí)行chmod。所以ssh-copy-id優(yōu)先。3.3 批量分發(fā)腳本可選集群節(jié)點(diǎn)多的時(shí)候一個(gè)個(gè)ssh-copy-id也挺煩??梢詫懸粋€(gè)簡(jiǎn)單的for循環(huán)腳本放在比如/home/hadoop/bin/目錄下#!/bin/bash # 需要在每臺(tái)機(jī)器hadoop用戶下執(zhí)行將本機(jī)公鑰分發(fā)到所有節(jié)點(diǎn) NODESmaster01 worker01 worker02 for node in $NODES; do echo Copy public key to $node... ssh-copy-id -i ~/.ssh/id_rsa.pub hadoop$node done分發(fā)時(shí)依然需要逐臺(tái)輸入一次密碼。這是不可避免的除非你用配置管理工具Ansible之類去集中分發(fā)但那要另起一套帶認(rèn)證的通道不在本文范圍內(nèi)。這里把腳本內(nèi)容給你結(jié)合hosts文件的寫法以后加新節(jié)點(diǎn)時(shí)執(zhí)行一遍就夠。3.4 驗(yàn)證免密登錄在所有節(jié)點(diǎn)上都完成上述配置后從master01依次執(zhí)行for node in master01 worker01 worker02; do echo $node ; ssh hadoop$node hostname whoami; done理想輸出是三行主機(jī)名加hadoop。如果一切正常你還可以繼續(xù)做一個(gè)更貼近Hadoop場(chǎng)景的驗(yàn)證切換到Hadoop安裝目錄比如/usr/local/hadoop執(zhí)行sbin/start-dfs.sh觀察是否不再卡在密碼提示。這一步才是真正的驗(yàn)收。4. 權(quán)限與配置文件細(xì)節(jié)避坑重點(diǎn)4.1 權(quán)限為何必須嚴(yán)格前面提到OpenSSH會(huì)檢查文件權(quán)限這里要展開說。很多新手配了半天authorized_keys里有公鑰但就是免密失敗90%的原因是權(quán)限問題。下面是一張標(biāo)準(zhǔn)權(quán)限表照著設(shè)置基本不會(huì)錯(cuò)路徑/文件屬主權(quán)限說明~/.sshhadoop700目錄不能組/其他用戶有寫權(quán)限~/.ssh/authorized_keyshadoop600公鑰文件不能組/其他用戶可寫~/.ssh/id_rsahadoop600私鑰必須只有屬主可讀寫~home目錄hadoop755不能被組/其他用戶寫否則SSH會(huì)拒絕我見過最典型的一個(gè)錯(cuò)誤是有人將整個(gè)home目錄遞歸做了chmod -R 777然后所有權(quán)限校驗(yàn)全掛。OpenSSH有一個(gè)StrictModes設(shè)置默認(rèn)是yes它會(huì)拒絕任何它認(rèn)為權(quán)限過松的密鑰認(rèn)證。你可以臨時(shí)把StrictModes改成no來驗(yàn)證但這不是“修復(fù)”是繞過治標(biāo)不治本而且會(huì)引入風(fēng)險(xiǎn)。正確做法就是把權(quán)限掰正。如果遇到權(quán)限導(dǎo)致的失敗可以檢查服務(wù)端的日志通常是/var/log/secure或/var/log/auth.log里面會(huì)明確寫Authentication refused: bad ownership or modes for file /home/hadoop/.ssh/authorized_keys看到這句話直接chmod 600 ~/.ssh/authorized_keys再確認(rèn).ssh目錄是700基本就能解決。4.2 SSH配置項(xiàng)影響除了權(quán)限/etc/ssh/sshd_config里的幾項(xiàng)直接影響免密是否生效PubkeyAuthentication yes必須啟用公鑰認(rèn)證。有些默認(rèn)配置為了安全會(huì)關(guān)閉需要手動(dòng)打開。AuthorizedKeysFile .ssh/authorized_keys指定服務(wù)端認(rèn)可的公鑰文件路徑。如果你的配置被修改過比如寫成了絕對(duì)路徑或別的文件名就要調(diào)整。PasswordAuthentication no如果服務(wù)端直接把密碼登錄禁掉了而且公鑰又沒配好那你會(huì)連登錄都登不進(jìn)去。建議先把免密打通再考慮是否關(guān)掉密碼登錄。StrictModes yes前面提到的權(quán)限嚴(yán)格檢查。修改配置后記得重啟sshd服務(wù)sudo systemctl restart sshd如果你愿意也可以先做sshd -t檢查配置語(yǔ)法避免重啟失敗。4.3 known_hosts和StrictHostKeyChecking免密登錄成功后另一個(gè)經(jīng)常出現(xiàn)的坑是主機(jī)密鑰確認(rèn)。當(dāng)SSH客戶端第一次連接一臺(tái)新機(jī)器時(shí)會(huì)詢問是否接受該主機(jī)的主機(jī)公鑰。批量和腳本場(chǎng)景下這個(gè)詢問會(huì)卡住。處理方案有兩類。第一類是正規(guī)做法提前把所有目標(biāo)主機(jī)密鑰插入到~/.ssh/known_hosts讓客戶端不再詢問。你可以這樣ssh-keyscan master01 worker01 worker02 ~/.ssh/known_hosts第二類是降低客戶端檢查級(jí)別。在~/.ssh/config里為特定主機(jī)設(shè)置Host *.example.com StrictHostKeyChecking no UserKnownHostsFile /dev/null或者臨時(shí)在命令行加-o StrictHostKeyCheckingno。但是要清楚關(guān)閉主機(jī)密鑰檢查會(huì)降低安全性所以建議只在受信任的內(nèi)網(wǎng)測(cè)試環(huán)境使用生產(chǎn)環(huán)境還是用ssh-keyscan預(yù)置為好。5. 常見問題與排查實(shí)錄5.1 問題速查表下面這些是我在多個(gè)模擬項(xiàng)目環(huán)境里實(shí)際踩過的狀況你也可以直接對(duì)照排查現(xiàn)象直接原因排查/解決提示“Permission denied (publickey,password)”沒配好公鑰或權(quán)限不對(duì)在目標(biāo)機(jī)上重新ssh-copy-id檢查.ssh權(quán)限卡在“yes/no”主機(jī)確認(rèn)提示known_hosts沒有目標(biāo)主機(jī)記錄執(zhí)行ssh-keyscan填充或臨時(shí)關(guān)閉StrictHostKeyChecking免密登錄本機(jī)可以遠(yuǎn)程不行只需把本機(jī)公鑰分發(fā)到遠(yuǎn)程機(jī)器檢查authorized_keys是否包含對(duì)應(yīng)公鑰配置沒問題但隔幾天又失效home目錄權(quán)限被動(dòng)過或賬號(hào)被鎖重新執(zhí)行chmod檢查密碼策略Hadoop啟動(dòng)腳本部分節(jié)點(diǎn)卡住某個(gè)節(jié)點(diǎn)網(wǎng)絡(luò)/password/公鑰未同步先從該節(jié)點(diǎn)手動(dòng)ssh看具體報(bào)錯(cuò)執(zhí)行腳本時(shí)私鑰提示輸入Passphrase生成密鑰時(shí)加了密碼重新生成帶-P 的密鑰對(duì)或者刪除私鑰密碼5.2 一個(gè)完整的排查案例說一個(gè)當(dāng)時(shí)的真實(shí)情況。有次我?guī)团笥颜{(diào)一套三節(jié)點(diǎn)的集群hadoop用戶配了免密master01能ssh到worker01但ssh到worker02每次還要密碼。我先在master01上確認(rèn)~/.ssh/id_rsa.pub內(nèi)容再去worker02比對(duì)~/.ssh/authorized_keys最后一行發(fā)現(xiàn)公鑰是有的。繼續(xù)查權(quán)限代碼如下ls -ld /home/hadoop /home/hadoop/.ssh ls -l /home/hadoop/.ssh/authorized_keys結(jié)果發(fā)現(xiàn)/home/hadoop/.ssh目錄權(quán)限是775不是700。問題就出在這里。因?yàn)镾SH的權(quán)限校驗(yàn)會(huì)檢查hadoop用戶所在組是否擁有寫權(quán)限即使你當(dāng)前不是組內(nèi)用戶它仍然會(huì)拒絕。我執(zhí)行chmod 700 /home/hadoop/.ssh chmod 600 /home/hadoop/.ssh/authorized_keys再試免密立即通過了。所以很多免密失敗真的不是“公鑰沒配好”而是“就差一個(gè)數(shù)字權(quán)限”。另外還有一個(gè)容易忽略的如果你曾經(jīng)以root身份對(duì)hadoop用戶的文件做過chown -R導(dǎo)致.ssh目錄的屬主變成root那公鑰認(rèn)證一樣會(huì)失敗。正確屬主必須始終是hadoop用戶自己。你可以在客戶端用ssh -v查看debug信息服務(wù)端看auth.log兩邊對(duì)一下問題很快定位。6. 收尾擴(kuò)展維護(hù)層面的幾點(diǎn)體會(huì)免密配好不是終點(diǎn)后續(xù)維護(hù)中還要注意幾件事。隨著集群擴(kuò)容新節(jié)點(diǎn)的免密配置要納入初始化流程別等啟動(dòng)失敗才想起來。我一般會(huì)寫一個(gè)setup_ssh.sh把ssh-keygen、ssh-copy-id、權(quán)限修正全部串在一起每次加節(jié)點(diǎn)后跑一遍能省很多事。另外盡量別把hadoop用戶的私鑰復(fù)制到不穩(wěn)定或不受控的第三方機(jī)器上。私鑰一旦泄露等于所有節(jié)點(diǎn)都能被登錄。對(duì)于重要集群可以在防火墻層面限制SSH的訪問來源并把sshd_config里的AllowUsers hadoop網(wǎng)段加上把風(fēng)險(xiǎn)收斂到一個(gè)相對(duì)小的范圍。我個(gè)人在實(shí)際操作中最深的體會(huì)是配置SSH免密難的不是敲命令而是理解“權(quán)限到底在保護(hù)什么”。很多教程只給命令不給原因?qū)е鲁隽藛栴}只能瞎撞。把公鑰認(rèn)證的校驗(yàn)流程和文件的ownership、permission對(duì)應(yīng)起來想清楚之后這套配置基本就是一次搞定。希望這篇文章能幫你少走彎路。