CDH 的部署和 Apache Hadoop 的部署是沒有任何差別的。這裡着重的是 HA的部署,需要特殊說明的是NameNode HA 需要依賴 Zookeeper
準備
Hosts檔案配置:
cat > /etc/hosts << _HOSTS_
127.0.0.1 localhost
10.0.2.59 cdh-m1
10.0.2.60 cdh-m2
10.0.2.61 cdh-s1
_HOSTS_
各個節點服務情況
cdh-m1 Zookeeper JournalNode NameNode DFSZKFailoverController HMaster
cdh-m2 Zookeeper JournalNode NameNode DFSZKFailoverController HMaster
cdh-s1 Zookeeper JournalNode DataNode HRegionServer
對幾個新服務說明下:
- JournalNode 用于同步 NameNode 中繼資料,和 Zookeeper 一樣需要 2N+1個節點存活叢集才可用。
- DFSZKFailoverController(ZKFC) 用于主備切換,類似 Keepalived 所扮演的角色。
NTP 服務
設定時區
rm -f /etc/localtime
ln -s /usr/share/zoneinfo/UTC /etc/localtime
配置NTP Server
yum install -y ntp
cat > /etc/ntp.conf << _NTP_
driftfile /var/lib/ntp/drift
restrict default nomodify
restrict -6 default nomodify
server cn.ntp.org.cn prefer
server news.neu.edu.cn iburst
server dns.sjtu.edu.cn iburst
server 127.127.1.1 iburst
tinker dispersion 100
tinker step 1800
tinker stepout 3600
includefile /etc/ntp/crypto/pw
keys /etc/ntp/keys
_NTP_
# NTP啟動時立即同步
cat >> /etc/ntp/step-tickers << _NTP_
server cn.ntp.org.cn prefer
server news.neu.edu.cn iburst
server dns.sjtu.edu.cn iburst
_NTP_
# 同步硬體時鐘
cat >> /etc/sysconfig/ntpd << _NTPHW_
SYNC_HWCLOCK=yes
_NTPHW_
啟動并設定開機自啟動
/etc/init.d/ntpd start
chkconfig ntpd on
配置 NTP Client
yum install -y ntp
# 注意修改内網NTP Server位址
cat > /etc/ntp.conf << _NTP_
driftfile /var/lib/ntp/drift
restrict default nomodify
restrict -6 default nomodify
restrict 127.0.0.1
restrict -6 ::1
server 10.0.2.59 prefer
tinker dispersion 100
tinker step 1800
tinker stepout 3600
includefile /etc/ntp/crypto/pw
keys /etc/ntp/keys
_NTP_
# NTP啟動時立即同步
cat >> /etc/ntp/step-tickers << _NTP_
server 10.0.2.59 prefer
_NTP_
# 同步硬體時鐘
cat >> /etc/sysconfig/ntpd << _NTPHW_
SYNC_HWCLOCK=yes
_NTPHW_
/etc/init.d/ntpd start
chkconfig ntpd on
檢查 NTP 同步
ntpq -p
# 結果
remote refid st t when poll reach delay offset jitter
==============================================================================
*time7.aliyun.co 10.137.38.86 2 u 17 64 3 44.995 5.178 0.177
news.neu.edu.cn .INIT. 16 u - 64 0 0.000 0.000 0.000
202.120.2.90 .INIT. 16 u - 64 0 0.000 0.000 0.000
JDK
建立目錄
mkdir -p /data/{install,app,logs,pid,appData}
mkdir /data/appData/tmp
cd /data/install
wget -c http://oracle.com/jdk-7u51-linux-x64.gz
tar xf jdk-7u51-linux-x64.gz -C /data/app
cd /data/app
ln -s jdk1.7.0_51 jdk1.7
cat >> /etc/profile << _PATH_
export JAVA_HOME=/data/app/jdk1.7
export CLASSPATH=.:\$JAVA_HOME/lib/dt.jar:\$JAVA_HOME/lib/tools.jar
export PATH=\$JAVA_HOME/bin:\$PATH
_PATH_
source /etc/profile
建立運作賬戶
useradd -u 600 run
安裝包
http://archive.cloudera.com/cdh5/cdh/5/
cd /data/install
wget -c http://archive.cloudera.com/cdh5/cdh/5/hadoop-2.6.0-cdh5.4.5.tar.gz
wget -c http://archive.apache.org/dist/zookeeper/zookeeper-3.4.5/zookeeper-3.4.5.tar.gz
wget -c http://archive.cloudera.com/cdh5/cdh/5/hbase-1.0.0-cdh5.4.5.tar.gz
安裝 Zookeeper
cd /data/install
tar xf zookeeper-3.4.5.tar.gz -C /data/app
cd /data/app
ln -s zookeeper-3.4.5 zookeeper
設定環境變量
sed -i '/^export PATH=/i\export ZOOKEEPER_HOME=/data/app/zookeeper' /etc/profile
sed -i 's#export PATH=#&\$ZOOKEEPER_HOME/bin:#' /etc/profile
source /etc/profile
删除無用檔案
cd $ZOOKEEPER_HOME
rm -rf *xml *txt zookeeper-3.4.5.jar.* src recipes docs dist-maven contrib
rm -f $ZOOKEEPER_HOME/bin/*.cmd $ZOOKEEPER_HOME/bin/*.txt
rm -f $ZOOKEEPER_HOME/conf/zoo_sample.cfg
建立資料目錄
mkdir -p /data/appData/zookeeper/{data,logs}
配置
cat > $ZOOKEEPER_HOME/conf/zoo.cfg << _ZOO_
tickTime=2000
initLimit=10
syncLimit=5
clientPort=2181
dataDir=/data/appData/zookeeper/data
dataLogDir=/data/appData/zookeeper/logs
server.1=cdh-m1:2888:3888
server.2=cdh-m2:2888:3888
server.3=cdh-s1:2888:3888
_ZOO_
修改Zookeeper的日志列印方式,與日志路徑設定
編輯
$ZOOKEEPER_HOME/bin/zkEnv.sh
在27行後加入兩個變量
ZOO_LOG_DIR=/data/logs/zookeeper
ZOO_LOG4J_PROP="INFO,ROLLINGFILE"
建立 myid檔案
# 注意myid與配置檔案保持一緻
echo 1 >/data/appData/zookeeper/data/myid
設定目錄權限
chown -R run.run /data/{app,appData,logs}
啟動、停止
# 啟動
runuser - run -c 'zkServer.sh start'
# 停止
runuser - run -c 'zkServer.sh stop'
安裝 Hadoop
tar xf hadoop-2.6.0-cdh5.4.5.tar.gz -C /data/app
cd /data/app
ln -s hadoop-2.6.0-cdh5.4.5 hadoop
sed -i '/^export PATH=/i\export HADOOP_HOME=/data/app/hadoop' /etc/profile
sed -i 's#export PATH=#&\$HADOOP_HOME/bin:\$HADOOP_HOME/sbin:#' /etc/profile
source /etc/profile
cd $HADOOP_HOME
rm -rf *txt share/doc src examples* include bin-mapreduce1 cloudera
find . -name "*.cmd"|xargs rm -f
建立資料目錄
mkdir -p /data/appData/hdfs/{name,edits,data,jn,tmp}
切換到配置檔案目錄
cd $HADOOP_HOME/etc/hadoop
編輯 core-site.xml
<?xml version="1.0" encoding="UTF-8"?>
<?xml-stylesheet type="text/xsl" href="configuration.xsl"?>
<configuration>
<!-- HDFS 叢集名稱,可指定端口 -->
<property>
<name>fs.defaultFS</name>
<value>hdfs://hdfs-cdh</value>
</property>
<!-- 臨時檔案目錄 -->
<property>
<name>hadoop.tmp.dir</name>
<value>/data/appData/hdfs/tmp</value>
</property>
<!-- 資源回收筒設定,0不啟用資源回收筒,1440 表示1440分鐘後删除 -->
<property>
<name>fs.trash.interval</name>
<value>1440</value>
</property>
<!-- SequenceFiles在讀寫中可以使用的緩存大小,機關 bytes 預設 4096 -->
<property>
<name>io.file.buffer.size</name>
<value>131072</value>
</property>
<!-- 可用壓縮算法,啟用在hdfs-site.xml中,需要編譯動态連結庫才能用 -->
<property>
<name>io.compression.codecs</name>
<value>org.apache.hadoop.io.compress.SnappyCodec</value>
</property>
</configuration>
編輯 hdfs-site.xml
<?xml version="1.0" encoding="UTF-8"?>
<?xml-stylesheet type="text/xsl" href="configuration.xsl"?>
<configuration>
<!-- 指定hdfs 叢集名稱,需要和core-site.xml中的保持一緻 -->
<property>
<name>dfs.nameservices</name>
<value>hdfs-cdh</value>
</property>
<!-- 指定 Zookeeper 用于NameNode HA,預設官方配置在core-site.xml中,為了檢視清晰配置到hdfs-site.xml也是可用的 -->
<property>
<name>ha.zookeeper.quorum</name>
<value>cdh-m1:2181,cdh-m2:2181,cdh-s1:2181</value>
</property>
<!-- hdfs-cdh 下有兩個NameNode,分别為 nn1,nn2 -->
<property>
<name>dfs.ha.namenodes.hdfs-cdh</name>
<value>nn1,nn2</value>
</property>
<!-- nn1 RPC通信位址 -->
<property>
<name>dfs.namenode.rpc-address.hdfs-cdh.nn1</name>
<value>cdh-m1:9000</value>
</property>
<!-- nn1 HTTP通信位址 -->
<property>
<name>dfs.namenode.http-address.hdfs-cdh.nn1</name>
<value>cdh-m1:50070</value>
</property>
<!-- nn2 RPC通信位址 -->
<property>
<name>dfs.namenode.rpc-address.hdfs-cdh.nn2</name>
<value>cdh-m2:9000</value>
</property>
<!-- nn2 HTTP通信位址 -->
<property>
<name>dfs.namenode.http-address.hdfs-cdh.nn2</name>
<value>cdh-m2:50070</value>
</property>
<!-- 指定NameNode中繼資料在JournalNode上的存儲路徑 -->
<property>
<name>dfs.namenode.shared.edits.dir</name>
<value>qjournal://cdh-m1:8485;cdh-m2:8485;cdh-s1:8485;/hdfs-cdh</value>
</property>
<!-- 開啟NameNode失敗自動切換 -->
<property>
<name>dfs.ha.automatic-failover.enabled</name>
<value>true</value>
</property>
<!-- 配置主備切換實作方式 -->
<property>
<name>dfs.client.failover.proxy.provider.hdfs-cdh</name>
<value>org.apache.hadoop.hdfs.server.namenode.ha.ConfiguredFailoverProxyProvider</value>
</property>
<!-- 配置主備切換方法,每個方法一行-->
<property>
<name>dfs.ha.fencing.methods</name>
<value>
sshfence
shell(/bin/true)
</value>
</property>
<!-- 指定運作使用者的秘鑰,需要NameNode雙向免密碼登入,用于主備自動切換 -->
<property>
<name>dfs.ha.fencing.ssh.private-key-files</name>
<value>/home/run/.ssh/id_rsa</value>
</property>
<!-- 配置sshfence 逾時時間 -->
<property>
<name>dfs.ha.fencing.ssh.connect-timeout</name>
<value>50000</value>
</property>
<!-- NameNode 資料本地存儲路徑 -->
<property>
<name>dfs.namenode.name.dir</name>
<value>/data/appData/hdfs/name</value>
</property>
<!-- DataNode 資料本地存儲路徑 -->
<property>
<name>dfs.datanode.data.dir</name>
<value>/data/appData/hdfs/data</value>
</property>
<!-- JournalNode 資料本地存儲路徑 -->
<property>
<name>dfs.journalnode.edits.dir</name>
<value>/data/appData/hdfs/jn</value>
</property>
<!-- 修改檔案存儲到edits,定期同步到DataNode -->
<property>
<name>dfs.namenode.edits.noeditlogchannelflush</name>
<value>true</value>
</property>
<!-- edits 資料本地存儲路徑 -->
<property>
<name>dfs.namenode.edits.dir</name>
<value>/data/appData/hdfs/edits</value>
</property>
<!-- 開啟Block Location metadata允許impala知道資料塊在哪塊磁盤上 預設關閉 -->
<property>
<name>dfs.datanode.hdfs-blocks-metadata.enabled</name>
<value>true</value>
</property>
<!-- 權限檢查 預設開啟 -->
<property>
<name>dfs.permissions.enabled</name>
<value>false</value>
</property>
<!-- block 大小設定 -->
<property>
<name>dfs.blocksize</name>
<value>64m</value>
</property>
</configuration>
小于5個DataNode建議添加如下配置
<!-- 資料副本數量,不能超過DataNode數量,大叢集建議使用預設值 預設 3 -->
<property>
<name>dfs.replication</name>
<value>2</value>
</property>
<!-- 當副本寫入失敗時不配置設定新節點,小叢集适用 -->
<property>
<name>dfs.client.block.write.replace-datanode-on-failure.policy</name>
<value>NEVER</value>
</property>
在 hadoop-env.sh 中添加如下變量
export JAVA_HOME=/data/app/jdk1.7
export HADOOP_LOG_DIR=/data/logs/hadoop
export HADOOP_PID_DIR=/data/pid
# SSH端口 可選
export HADOOP_SSH_OPTS="-p 36000"
Heap 設定,機關 MB
export HADOOP_HEAPSIZE=1024
權限設定
chown -R run.run /data/{app,appData,logs}
chmod 777 /data/pid
格式化
格式化隻需要執行一次,格式化之前啟動Zookeeper
切換使用者
su - run
啟動所有 JournalNode
hadoop-daemon.sh start journalnode
格式化 Zookeeper(為 ZKFC 建立znode)
hdfs zkfc -formatZK
NameNode 主節點格式化并啟動
hdfs namenode -format
hadoop-daemon.sh start namenode
NameNode 備節點同步資料并啟動
hdfs namenode -bootstrapStandby
hadoop-daemon.sh start namenode
啟動 ZKFC
hadoop-daemon.sh start zkfc
啟動 DataNode
hadoop-daemon.sh start datanode
啟動與停止
su - run
叢集批量啟動
需要配置運作使用者ssh-key免密碼登入,與$HADOOP_HOME/etc/hadoop/slaves
# 啟動
start-dfs.sh
# 停止
stop-dfs.sh
單服務啟動停止
啟動HDFS
hadoop-daemon.sh start journalnode
hadoop-daemon.sh start namenode
hadoop-daemon.sh start zkfc
hadoop-daemon.sh start datanode
停止HDFS
hadoop-daemon.sh stop datanode
hadoop-daemon.sh stop namenode
hadoop-daemon.sh stop journalnode
hadoop-daemon.sh stop zkfc
測試
HDFS HA 測試
打開 NameNode 狀态頁:
http://cdh-m1:50010
http://cdh-m2:50010
在 Overview 後面能看見 active 或 standby,active 為目前 Master,停止 active 上的 NameNode,檢查 standby是否為 active。
HDFS 測試
hadoop fs -mkdir /test
hadoop fs -put /etc/hosts /test
hadoop fs -ls /test
結果:
-rw-r--r-- 2 java supergroup 89 2016-06-15 10:30 /test/hosts
# 其中權限後面的列(這裡的2)代表檔案總數,即副本數量。
HDFS 管理指令
# 動态加載 hdfs-site.xml
hadoop dfsadmin -refreshNodes
HBase安裝配置
cd /data/install
tar xf hbase-1.0.0-cdh5.4.5.tar.gz -C /data/app
cd /data/app
ln -s hbase-1.0.0-cdh5.4.5 hbase
sed -i '/^export PATH=/i\export HBASE_HOME=/data/app/hbase' /etc/profile
sed -i 's#export PATH=#&\$HBASE_HOME/bin:#' /etc/profile
source /etc/profile
cd $HBASE_HOME
rm -rf *.txt pom.xml src docs cloudera dev-support hbase-annotations hbase-assembly hbase-checkstyle hbase-client hbase-common hbase-examples hbase-hadoop2-compat hbase-hadoop-compat hbase-it hbase-prefix-tree hbase-protocol hbase-rest hbase-server hbase-shell hbase-testing-util hbase-thrift
find . -name "*.cmd"|xargs rm -f
進入配置檔案目錄
cd $HBASE_HOME/conf
編輯 hbase-site.xml
<?xml version="1.0"?>
<?xml-stylesheet type="text/xsl" href="configuration.xsl"?>
<configuration>
<!-- HBase 資料存儲路徑 -->
<property>
<name>hbase.rootdir</name>
<value>hdfs://hdfs-cdh/hbase</value>
</property>
<!-- 完全分布式模式 -->
<property>
<name>hbase.cluster.distributed</name>
<value>true</value>
</property>
<!-- HMaster 節點 -->
<property>
<name>hbase.master</name>
<value>cdh-m1:60000,cdh-m2:60000</value>
</property>
<!-- Zookeeper 節點 -->
<property>
<name>hbase.zookeeper.quorum</name>
<value>cdh-m1:2181,cdh-m2:2181,cdh-s1:2181</value>
</property>
<!-- znode 路徑,Zookeeper叢集中有多個HBase叢集需要設定不同znode -->
<property>
<name>zookeeper.znode.parent</name>
<value>/hbase</value>
</property>
<!-- HBase 協處理器 -->
<property>
<name>hbase.coprocessor.user.region.classes</name>
<value>org.apache.hadoop.hbase.coprocessor.AggregateImplementation</value>
</property>
</configuration>
在 hbase-env.sh 中添加如下變量
export JAVA_HOME=/data/app/jdk1.7
export HBASE_LOG_DIR=/data/logs/hbase
export HBASE_PID_DIR=/data/pid
export HBASE_MANAGES_ZK=false
# SSH 預設端口 可選
export HBASE_SSH_OPTS="-o ConnectTimeout=1 -p 36000"
export HBASE_HEAPSIZE=1024
可選設定 regionservers 中添加所有RegionServer主機名,用于叢集批量啟動、停止
su - run
需要配置運作使用者ssh-key免密碼登入,與$HBASE_HOME/conf/regionservers
# 啟動
start-hbase.sh
# 停止
stop-hbase.sh
HMaster
# 啟動
hbase-daemon.sh start master
# 停止
hbase-daemon.sh stop master
HRegionServer
# 啟動
hbase-daemon.sh start regionserver
# 停止
hbase-daemon.sh stop regionserver
HBase HA 測試
浏覽器打開兩個HMaster狀态頁:
http://cdh-m1:60010
http://cdh-m2:60010
可以在Master後面看見其中一個主機名,Backup Masters中看見另一個。
停止目前Master,重新整理另一個HMaster狀态頁會發現Master後面已經切換,HA成功。
HBase 測試
進入hbase shell 執行:
create 'users','user_id','address','info'
list
put 'users','anton','info:age','24'
get 'users','anton'
# 最終結果
COLUMN CELL
info:age timestamp=1465972035945, value=24
1 row(s) in 0.0170 seconds
清除測試資料:
disable 'users'
drop 'users'