- 积分
- 16844
在线时间 小时
最后登录1970-1-1
|

楼主 |
发表于 2022-11-15 10:00:33
|
显示全部楼层
一、高可用简介
( A& s- x6 C; Y% z% h二、集群规划
( i) ]( G$ a% T1 P三、前置条件/ ?9 A+ p4 }8 O+ L |( r9 d
四、集群配置' R8 m! |) R$ l4 u% L* a
五、启动集群
, p+ Y" u5 w2 [- c4 o& w& d& r六、查看集群
& ^$ x9 H& |: J9 }七、集群的二次启动
9 g' r# d; o/ [, V6 _: d5 T. U一、高可用简介1 N7 p+ A) i- `! G
Hadoop 高可用 (High Availability) 分为 HDFS 高可用和 YARN 高可用,两者的实现基本类似,但 HDFS NameNode 对数据存储及其一致性的要求比 YARN ResourceManger 高得多,所以它的实现也更加复杂,故下面先进行讲解:/ r3 o* w; T# s6 p, \
6 L, r$ X3 L+ {1.1 高可用整体架构$ \$ }. j, _/ z# n" P4 `. i
HDFS 高可用架构如下:' m, z# f$ M; h( G( L$ |1 _
8 ~& {8 h& t: O
. G. L+ o" [& ]) W图片引用自:https://www.edureka.co/blog/how- ... -high-availability/
% p* M) d7 a Z+ b2 T# D& {* b5 [
HDFS 高可用架构主要由以下组件所构成:
3 V4 z! W- s. {
0 S5 p! v" [ q6 L/ S. CActive NameNode 和 Standby NameNode:两台 NameNode 形成互备,一台处于 Active 状态,为主 NameNode,另外一台处于 Standby 状态,为备 NameNode,只有主 NameNode 才能对外提供读写服务。* x0 ?. p6 A6 Y8 Y% o, E8 M: M2 }
+ i. T1 w3 G6 x1 e9 |4 p6 R7 m
主备切换控制器 ZKFailoverController:ZKFailoverController 作为独立的进程运行,对 NameNode 的主备切换进行总体控制。ZKFailoverController 能及时检测到 NameNode 的健康状况,在主 NameNode 故障时借助 Zookeeper 实现自动的主备选举和切换,当然 NameNode 目前也支持不依赖于 Zookeeper 的手动主备切换。
. j' Q4 N: D6 h
/ {5 D% b% w) j4 Y* d) VZookeeper 集群:为主备切换控制器提供主备选举支持。. I% E0 G( w2 S4 n( o7 N
. \6 q7 L, e- U" X$ L' L' t, C: A
共享存储系统:共享存储系统是实现 NameNode 的高可用最为关键的部分,共享存储系统保存了 NameNode 在运行过程中所产生的 HDFS 的元数据。主 NameNode 和 NameNode 通过共享存储系统实现元数据同步。在进行主备切换的时候,新的主 NameNode 在确认元数据完全同步之后才能继续对外提供服务。. ~/ Z1 g( i. `
8 G; Y4 v3 V: v" ^- r9 M; S
DataNode 节点:除了通过共享存储系统共享 HDFS 的元数据信息之外,主 NameNode 和备 NameNode 还需要共享 HDFS 的数据块和 DataNode 之间的映射关系。DataNode 会同时向主 NameNode 和备 NameNode 上报数据块的位置信息。
9 w; T3 O9 E2 \! ^ z" Z5 m u' }8 @* M( W4 w" F+ D" Z8 j
1.2 基于 QJM 的共享存储系统的数据同步机制分析
) U; V( N" D# a t; R; _- {5 \目前 Hadoop 支持使用 Quorum Journal Manager (QJM) 或 Network File System (NFS) 作为共享的存储系统,这里以 QJM 集群为例进行说明:Active NameNode 首先把 EditLog 提交到 JournalNode 集群,然后 Standby NameNode 再从 JournalNode 集群定时同步 EditLog,当 Active NameNode 宕机后, Standby NameNode 在确认元数据完全同步之后就可以对外提供服务。
. \8 P$ q$ B& B& }" t9 h3 y/ r! j$ J) u% l+ s
需要说明的是向 JournalNode 集群写入 EditLog 是遵循 “过半写入则成功” 的策略,所以你至少要有 3 个 JournalNode 节点,当然你也可以继续增加节点数量,但是应该保证节点总数是奇数。同时如果有 2N+1 台 JournalNode,那么根据过半写的原则,最多可以容忍有 N 台 JournalNode 节点挂掉。
0 b$ b. H1 u1 T4 P
% S# O" ]& q2 d; t1 Q: @2 z. b1 Z' J$ v* R& G! [
1.3 NameNode 主备切换( ]5 \ M, t1 Q7 Y
NameNode 实现主备切换的流程下图所示:. [1 I U7 G. t! G6 K+ I8 l: j
' P( z6 R: j. s% Y1 _* y$ m8 d( }+ D. c5 b# e% [
1. HealthMonitor 初始化完成之后会启动内部的线程来定时调用对应 NameNode 的 HAServiceProtocol RPC 接口的方法,对 NameNode 的健康状态进行检测。 2. HealthMonitor 如果检测到 NameNode 的健康状态发生变化,会回调 ZKFailoverController 注册的相应方法进行处理。 3. 如果 ZKFailoverController 判断需要进行主备切换,会首先使用 ActiveStandbyElector 来进行自动的主备选举。 4. ActiveStandbyElector 与 Zookeeper 进行交互完成自动的主备选举。 5. ActiveStandbyElector 在主备选举完成后,会回调 ZKFailoverController 的相应方法来通知当前的 NameNode 成为主 NameNode 或备 NameNode。 6. ZKFailoverController 调用对应 NameNode 的 HAServiceProtocol RPC 接口的方法将 NameNode 转换为 Active 状态或 Standby 状态。5 X* D r' |" y0 v/ u3 J: ^* U
1.4 YARN高可用
. b' y& A& c% ~. W$ M' G4 i1 k7 x AYARN ResourceManager 的高可用与 HDFS NameNode 的高可用类似,但是 ResourceManager 不像 NameNode ,没有那么多的元数据信息需要维护,所以它的状态信息可以直接写到 Zookeeper 上,并依赖 Zookeeper 来进行主备选举。3 `9 w" A: o: U$ C+ h7 |6 u) }
B9 V6 x1 D1 z& B2 x6 j4 J
; e6 |' s: Q0 `二、集群规划
6 p+ \) o) ~1 C- c按照高可用的设计目标:需要保证至少有两个 NameNode (一主一备) 和 两个 ResourceManager (一主一备) ,同时为满足“过半写入则成功”的原则,需要至少要有 3 个 JournalNode 节点。这里使用三台主机进行搭建,集群规划如下:
5 @1 |, A# z9 r1 |4 a
i. s: G9 F$ x7 R3 g/ D! n
5 C9 y$ o% k, O" U: k, u三、前置条件( G8 a2 } n4 n9 p0 M! ]
所有服务器都安装有 JDK,安装步骤可以参见:Linux 下 JDK 的安装;2 I+ X$ s9 G+ O* v9 h
搭建好 ZooKeeper 集群,搭建步骤可以参见:Zookeeper 单机环境和集群环境搭建' C2 r5 z) S0 \ v5 B6 O# y: W( E, o! r
所有服务器之间都配置好 SSH 免密登录。 k3 n- `# Z% e' [) C. M
四、集群配置
/ `2 v' O# K6 a& p* ]4.1 下载并解压
' E4 h! _# \) x3 I- `8 y下载 Hadoop。这里我下载的是 CDH 版本 Hadoop,下载地址为:http://archive.cloudera.com/cdh5/cdh/5/, D) F0 C5 k4 Y. b
2 D2 g9 Y# z- V. S6 G0 [4 d4 f5 {
# tar -zvxf hadoop-2.6.0-cdh5.15.2.tar.gz 0 V6 R% g! Y( b5 c
4.2 配置环境变量
6 n& q3 G# l$ ^% [编辑 profile 文件:
& b, q" f1 }- t# T- W% S) ~6 g7 Q; q
# vim /etc/profile! e# [3 F$ t% m" f
增加如下配置:
: H+ K7 U" z* }3 ]0 w7 ?& D& V! {* K! N' o$ v
export HADOOP_HOME=/usr/app/hadoop-2.6.0-cdh5.15.2
! `( C' F! C( s2 f5 |export PATH=${HADOOP_HOME}/bin:$PATH
2 E" `, w* Y4 H. S+ w9 B# u. c2 i执行 source 命令,使得配置立即生效:
& M# J& F7 V% e0 y) S
: z [1 \7 o2 Z% ^% |- n! n: e# source /etc/profile+ z! v$ `5 m) P: X, `! p
4.3 修改配置5 f/ ^9 T! u6 X& n
进入 ${HADOOP_HOME}/etc/hadoop 目录下,修改配置文件。各个配置文件内容如下:) G+ P+ O0 T1 v( T
: `. c, u( N4 m5 R& e, r
1. hadoop-env.sh- O4 ~$ I$ W5 T w: G
# 指定JDK的安装位置
/ v6 {8 O; v- G4 K$ O; g# ?6 B4 Uexport JAVA_HOME=/usr/java/jdk1.8.0_201/9 z7 ?, G6 C2 x- v) J& o% N8 b
2. core-site.xml
- m! l# w0 y) i9 m* Y<configuration>
" `. T Z' j3 m) D7 o <property>
3 ^4 V- j! E* C2 B7 w& R1 h <!-- 指定 namenode 的 hdfs 协议文件系统的通信地址 -->
1 r+ ~: O% x9 O8 `6 G <name>fs.defaultFS</name>
1 _$ v# R- ]8 B# y <value>hdfs://hadoop001:8020</value>$ b3 O8 X# e6 Y4 l7 V, Q
</property>2 i& y8 }( ~# n8 a" S+ k
<property>
, p y- S+ k: c# Z <!-- 指定 hadoop 集群存储临时文件的目录 -->0 T3 f5 m2 N8 n% X* E
<name>hadoop.tmp.dir</name>4 F) _4 _( }$ A+ }
<value>/home/hadoop/tmp</value>
+ \' P' e8 C0 Y8 }$ Y </property>
9 X0 }6 w$ V1 N) e7 e& [4 Z* s* D <property>* y5 M) Y+ p6 w$ d. S5 e: d" _- x
<!-- ZooKeeper 集群的地址 -->
/ k0 q( X3 r! @* f8 x4 T" j <name>ha.zookeeper.quorum</name>' u/ W" r- z; D9 u! _8 j
<value>hadoop001:2181,hadoop002:2181,hadoop003:2181</value>9 S) a e" X9 @
</property>
( s$ ~* O7 x: w) i <property>
* Q: g8 _7 O! Y! C- { <!-- ZKFC 连接到 ZooKeeper 超时时长 -->
4 x0 M% S) q5 p+ ^: f <name>ha.zookeeper.session-timeout.ms</name>; s6 M) B# l3 X A" z/ I
<value>10000</value>* e" U. }* C/ b
</property>) H2 b: y) j ]5 {
</configuration>2 E! u: e7 |; ?- z
3. hdfs-site.xml _- H' O" t9 n/ p; s+ G0 a1 z
<configuration>" L0 U w! ]2 m U2 b$ I. U6 T. a
<property>3 i) O. b% \) K3 d5 u! m
<!-- 指定 HDFS 副本的数量 -->
W+ y+ x6 _6 L E$ X <name>dfs.replication</name>
+ k9 n1 ~; R# K( h) Z9 i <value>3</value> Z- a* t1 R Q4 ~- B1 `. e6 E* E. x
</property>' O3 I' u5 _) M
<property>% y3 S7 O' t7 t- l8 J8 T+ v
<!-- namenode 节点数据(即元数据)的存放位置,可以指定多个目录实现容错,多个目录用逗号分隔 -->
s, `) h5 }6 ^9 o/ c# h; h0 ? <name>dfs.namenode.name.dir</name>
6 s/ d# T @2 f1 B l2 U <value>/home/hadoop/namenode/data</value>
# w5 L7 L5 u E( X) [+ P9 b </property>
+ T4 R! G5 j3 p1 j <property>
; c7 H9 b6 ]+ M7 |3 f <!-- datanode 节点数据(即数据块)的存放位置 -->
7 G$ M0 N8 Z+ a8 I- e5 F <name>dfs.datanode.data.dir</name>
1 D) f+ K: d: h) R; A! G2 { <value>/home/hadoop/datanode/data</value>" c/ i& G% \, X+ y0 ?2 d# v- E9 C
</property>6 a( m6 |7 g0 x, K) C
<property>
" L/ \* z# T9 U' E <!-- 集群服务的逻辑名称 -->, E$ c2 N6 B) [+ R: M
<name>dfs.nameservices</name>3 V8 u4 _# a% @5 Q0 v
<value>mycluster</value>
$ g1 |* [6 F% M% K% W8 l8 M </property>+ X d4 n+ t% a# ?" t
<property>6 }( X0 o" l: e
<!-- NameNode ID 列表-->
# z1 ]8 Q( z4 c; a <name>dfs.ha.namenodes.mycluster</name>
( r- R1 B1 e* X+ A7 I& \ <value>nn1,nn2</value>, d9 q9 N: j3 U& r& m0 e
</property>
5 C: S$ U: z) D) ~; K <property>
6 m, Q- M R) K" C- y4 n <!-- nn1 的 RPC 通信地址 -->4 I/ f8 b7 B ` V* H3 v# i6 j1 i
<name>dfs.namenode.rpc-address.mycluster.nn1</name>
6 Z1 p$ W! d- V X5 g5 h( m <value>hadoop001:8020</value>7 S# O3 m) F% \# s/ f3 E$ H7 C0 H
</property>4 a+ m" T: F. @$ _) V( y+ ?$ `
<property> Z7 Z. V* i/ c' z; c$ E; A
<!-- nn2 的 RPC 通信地址 -->
" N4 |- d6 i: M( q# a$ k* v9 C <name>dfs.namenode.rpc-address.mycluster.nn2</name>( E4 }3 B$ Z( g; s7 t. I
<value>hadoop002:8020</value>, v$ h3 z; r! `' B
</property>( R0 ?9 b4 M: \
<property>
; @( s- r% V: h9 x! Z <!-- nn1 的 http 通信地址 -->5 R( N: e3 o3 x7 ~) _( H: o/ L. y# X
<name>dfs.namenode.http-address.mycluster.nn1</name>
- S1 s! W! ~8 l. q# {% o <value>hadoop001:50070</value>- ]2 _/ @8 e# f+ R9 {% |
</property>
" u6 G4 p$ g8 }; e( g <property>
- |" [% p2 x5 T3 ~5 h) R <!-- nn2 的 http 通信地址 -->+ I Q: _* y* P- ~8 |
<name>dfs.namenode.http-address.mycluster.nn2</name>
6 d& F; @: C$ ?+ z, I* {; A" g0 G <value>hadoop002:50070</value>4 b9 c7 ~7 y# K' P- P1 ^
</property>
2 |+ S/ _0 {6 N3 ]" E <property>& m: i6 p/ m' ]1 w) Z/ N9 O& ~
<!-- NameNode 元数据在 JournalNode 上的共享存储目录 -->2 ^* V o/ m8 |* p6 p
<name>dfs.namenode.shared.edits.dir</name>4 _, S1 C; |% X% m3 Y2 [* _
<value>qjournal://hadoop001:8485;hadoop002:8485;hadoop003:8485/mycluster</value>
+ q& b8 q3 `' i, b* c </property>' M$ ~7 o3 }" L; \
<property>
: u4 o$ U/ ?( ?$ t* g4 V <!-- Journal Edit Files 的存储目录 -->5 p4 }7 u+ ?+ w) o
<name>dfs.journalnode.edits.dir</name>3 h0 E1 z4 }* w/ E6 H: H
<value>/home/hadoop/journalnode/data</value>4 r. U! \! d% ~) @
</property>* Z9 k2 R" h, _# q; h" H9 v/ I
<property>$ |% k* S7 _9 `6 L, I% l
<!-- 配置隔离机制,确保在任何给定时间只有一个 NameNode 处于活动状态 -->% }, D2 q8 U4 n8 v8 t- [
<name>dfs.ha.fencing.methods</name>1 u* y' Q, |. L/ Z
<value>sshfence</value>
$ I; g5 O- k# Z. R& \0 } </property>9 B- W% g! h3 ~
<property>$ l: Y. a" Z+ S& N- V6 `; W& Z% q
<!-- 使用 sshfence 机制时需要 ssh 免密登录 -->
/ n+ t2 W! `5 Q. H7 \& a6 A <name>dfs.ha.fencing.ssh.private-key-files</name>
+ L1 q/ Q; M2 ?* s- g6 V3 F0 R9 f <value>/root/.ssh/id_rsa</value>
) m8 k5 d; K9 o0 u: L1 d6 ^ </property>
" y/ x: `( k# |2 u* f <property>
, R: ^; u. M9 U: p; k <!-- SSH 超时时间 -->
9 J: w" O& z' H' k5 \ <name>dfs.ha.fencing.ssh.connect-timeout</name>
, j, d, |% S( s. m) G3 C8 h4 a: f <value>30000</value>* `# u; A* M8 |( C' f- {- l
</property>' h, q0 I# K( Y6 I
<property>& y' E4 Q/ A- `0 V% R2 p3 w# r- b
<!-- 访问代理类,用于确定当前处于 Active 状态的 NameNode -->
0 j ^ K$ Z$ Y; q1 N1 T+ U# e <name>dfs.client.failover.proxy.provider.mycluster</name>. ]( |2 _7 t; d7 q% X7 t$ I
<value>org.apache.hadoop.hdfs.server.namenode.ha.ConfiguredFailoverProxyProvider</value>
9 S. Q! S6 @- `, B$ V( p </property>
5 f- M# _; ^ O/ c <property>
2 j) c9 }, N' L$ d/ c: @( _( D <!-- 开启故障自动转移 -->
|" _* l8 l: E2 a0 c; P+ A <name>dfs.ha.automatic-failover.enabled</name>1 M# ?9 A5 z0 p# D1 t
<value>true</value>
$ K/ L+ [( |+ U7 L8 q: e0 ^. V5 B7 T, D </property>
/ c& j5 O9 g: V$ N, d) B) w</configuration>
: M9 m6 c8 J/ U* I% C" f6 U4. yarn-site.xml5 N# g' y7 t# Z9 T
<configuration>
& z& x( z P# o( }& z: Q0 ^2 H <property>) w( S$ `/ l; V0 v( A
<!--配置 NodeManager 上运行的附属服务。需要配置成 mapreduce_shuffle 后才可以在 Yarn 上运行 MapReduce 程序。-->
* |0 d/ i. s+ T& E0 O9 N5 O <name>yarn.nodemanager.aux-services</name>' V8 H/ _; n) a0 I, p
<value>mapreduce_shuffle</value>, v; c9 A* ^3 t4 ` f2 T
</property> q2 c& b& x1 i& u- O. ^0 j
<property>5 k9 i' f3 B4 S5 J! t# Q6 ]
<!-- 是否启用日志聚合 (可选) -->
: `/ R& `6 c0 J' [. t: ~/ J9 C <name>yarn.log-aggregation-enable</name>
, k) s0 T$ M8 x6 T9 T <value>true</value>
! S+ J' B: L" ~7 {0 c, |, R, F- `; G; R </property>
# f( ]/ V: h; I/ ]6 Z4 S# y# g9 q' F6 a <property>
2 o! Y# E+ A; j; m/ }& g <!-- 聚合日志的保存时间 (可选) -->' O; n: [- r- k( ~. t A
<name>yarn.log-aggregation.retain-seconds</name>
: e1 ^* U& S5 k2 S3 R0 U <value>86400</value>' D: Y! n# _+ z/ ~9 T* C
</property>9 N2 d$ n/ i) l7 J( I
<property>% ~: W8 ]6 {9 q# F! t! Q
<!-- 启用 RM HA -->6 r" j. f0 w. L+ k, v* G3 X' C
<name>yarn.resourcemanager.ha.enabled</name>6 c0 |" }* e4 F$ v# \
<value>true</value>; K& r$ W. p3 F7 {4 J, Z
</property>
! \( w: B6 s9 K <property>
) [) g; R& l# I# {, B; \3 B <!-- RM 集群标识 -->
9 d% H( ~# [. E! v+ t7 n <name>yarn.resourcemanager.cluster-id</name>
( |9 ~. s M; I6 K <value>my-yarn-cluster</value>
- L8 x& z, K! q7 n </property>/ Z- Q5 `& t1 b$ a x" S; J: u
<property>" k! l3 ~: c* Q; I/ K" d) O* G
<!-- RM 的逻辑 ID 列表 --> `1 T1 ~9 [: Y0 O0 v0 ^
<name>yarn.resourcemanager.ha.rm-ids</name>3 S, \ d6 y& d4 W
<value>rm1,rm2</value>* F1 p) [: j4 y- B U: f
</property>
8 p* f& ^4 u; E- W, k! L <property>9 _# k' V- x: C; M5 A
<!-- RM1 的服务地址 -->
" P) f# j( V7 Q, i o <name>yarn.resourcemanager.hostname.rm1</name>& _% ]/ F' K0 o! k1 X
<value>hadoop002</value>
( C: e& u X. }8 m+ E" p! g+ p3 o </property>* o( I8 @" s& }: n0 @" x9 s
<property>
d5 v; m( A1 {1 V <!-- RM2 的服务地址 -->
& N8 L. M6 I$ @9 s N <name>yarn.resourcemanager.hostname.rm2</name>
7 I# X& u" s7 E2 k <value>hadoop003</value>
" `, f8 z" I" |& Z0 X) H, ? </property>5 D8 T/ ~7 Z9 h) `
<property>9 G2 I) F8 h, f, v9 i, y
<!-- RM1 Web 应用程序的地址 -->
# Q6 ]( N. C3 j: H <name>yarn.resourcemanager.webapp.address.rm1</name>0 D) V: t/ b3 G
<value>hadoop002:8088</value>0 c D. v) X' R1 N9 W Y: l, N
</property>* B9 R& Y( U$ u8 F. {1 w8 O) l, R. F
<property>
! | ?3 @# O- u+ _ <!-- RM2 Web 应用程序的地址 -->& M6 Y) U1 e9 C& f4 B. C
<name>yarn.resourcemanager.webapp.address.rm2</name>
+ J7 b" n) T* H <value>hadoop003:8088</value>& N9 N4 m. r- J# |/ H% ~5 X& T
</property>
' j! h1 t& v4 a) w+ A6 R <property>$ ^! i5 m4 G1 Y; }8 \6 u
<!-- ZooKeeper 集群的地址 -->; a$ W2 `6 n& b- W. h/ `
<name>yarn.resourcemanager.zk-address</name>8 T S& u. u5 Z/ \$ @# H
<value>hadoop001:2181,hadoop002:2181,hadoop003:2181</value>
8 p! V+ q- v" C/ ^ </property>6 V- n5 h. u) V; d
<property>
: Q- Y8 T8 `; d6 h: E <!-- 启用自动恢复 -->6 c$ w/ {# Q1 ?- Y$ n4 v
<name>yarn.resourcemanager.recovery.enabled</name>
3 {& ~; d/ N1 N" S$ Y9 b) M <value>true</value>
% o- d. T) P3 h7 o+ n0 d </property>
/ S9 L; T5 q6 J, g2 ]6 g3 U <property>% b7 H7 a: ]4 G3 Z& R" Z1 q2 [( U
<!-- 用于进行持久化存储的类 -->/ q3 t; ~4 |! ~* X5 t4 t" g% a& w
<name>yarn.resourcemanager.store.class</name>
1 f% z! c4 M. t+ r8 R' J <value>org.apache.hadoop.yarn.server.resourcemanager.recovery.ZKRMStateStore</value>
+ E0 ]* i& e% B </property>
9 ^1 H* @" v# U7 x$ V</configuration>
( o: s3 @5 s/ v7 C- M; t5. mapred-site.xml+ N% Y' r" D9 @6 I7 Q" b' Q) b
<configuration>
( U* m0 S8 ?- C9 F6 R <property>
1 f. J r9 a- g7 F4 ^/ | <!--指定 mapreduce 作业运行在 yarn 上-->
4 e9 ~' E1 ^/ F/ k- _ <name>mapreduce.framework.name</name>
* L0 x; C! q" l* |1 B) v <value>yarn</value>7 M$ N9 m; } p& t) }/ B6 G3 {
</property>& V' c5 f6 K7 a, c2 A
</configuration>/ b3 n1 c" e4 {, f# E2 j9 ?
5. slaves
" C0 ~" V/ }4 ]1 Q: f1 G( A2 k配置所有从属节点的主机名或 IP 地址,每行一个。所有从属节点上的 DataNode 服务和 NodeManager 服务都会被启动。. f# @4 p' q9 J( g
5 a0 V+ l% a$ Y1 \# O% Phadoop001, N0 U' z$ O; |3 c8 ]& X
hadoop002
" f* v6 K) B6 F9 T5 _) _) uhadoop003" ?" @9 Q6 j, V1 t/ Q% q- i
4.4 分发程序
! \/ d- ?# H" c4 H- U. b$ `将 Hadoop 安装包分发到其他两台服务器,分发后建议在这两台服务器上也配置一下 Hadoop 的环境变量。
" w7 F$ {+ y+ z' }3 c$ v2 I: G* K; ~4 c3 Q& G' Y
# 将安装包分发到hadoop002
. w! \8 V5 G l' W) g# X Wscp -r /usr/app/hadoop-2.6.0-cdh5.15.2/ hadoop002:/usr/app/
% F" A! v/ t3 f& a. U( r# 将安装包分发到hadoop003
) l- e, N% G# ?, \; M3 ~scp -r /usr/app/hadoop-2.6.0-cdh5.15.2/ hadoop003:/usr/app/
) ?/ e9 h6 n+ Q6 {" S五、启动集群: b; J* x6 @( p$ ^
5.1 启动ZooKeeper- u1 \. o- ~. [' N% }$ Q
分别到三台服务器上启动 ZooKeeper 服务:
! F+ k' X3 {, r* o) V, I5 U& d6 y! C- J# K4 b8 _9 g
zkServer.sh start, s+ m" h: ~3 n( }- f% m6 B0 C
5.2 启动Journalnode, U; T5 p4 }9 Z9 Y3 M. G8 n
分别到三台服务器的的 ${HADOOP_HOME}/sbin 目录下,启动 journalnode 进程:6 [1 V. x) r9 x6 D
) |% A1 J8 g: u5 khadoop-daemon.sh start journalnode
$ m1 ?( x; {$ p! S) @% d% E$ I5.3 初始化NameNode
- h5 r# w& F( Y( ]# O; S/ [* J4 C在 hadop001 上执行 NameNode 初始化命令:0 e1 I3 e* c7 s; k3 _8 R! d: M
% L! m+ E+ w; t
hdfs namenode -format' ~, l/ [/ `( c7 o
执行初始化命令后,需要将 NameNode 元数据目录的内容,复制到其他未格式化的 NameNode 上。元数据存储目录就是我们在 hdfs-site.xml 中使用 dfs.namenode.name.dir 属性指定的目录。这里我们需要将其复制到 hadoop002 上:
$ E. A R4 U6 o9 ?' {$ V# l8 Y0 n( o( _/ }
scp -r /home/hadoop/namenode/data hadoop002:/home/hadoop/namenode/3 K) C" H+ K3 x2 ^% e5 Y% h
5.4 初始化HA状态' x0 C# s8 \0 r2 @8 T
在任意一台 NameNode 上使用以下命令来初始化 ZooKeeper 中的 HA 状态:' X( T7 N# @1 ~5 e m
. U0 r% }6 J. m
hdfs zkfc -formatZK
; t, L l: f) \2 h2 C! [5.5 启动HDFS& b) V, g+ q4 i w; q/ F
进入到 hadoop001 的 ${HADOOP_HOME}/sbin 目录下,启动 HDFS。此时 hadoop001 和 hadoop002 上的 NameNode 服务,和三台服务器上的 DataNode 服务都会被启动:
( F2 v/ P# Y5 W7 G: }7 |, o& c% y6 |
start-dfs.sh! n( Q4 f) L, D" q; {& e
5.6 启动YARN' L2 f, q' o% a* J8 n5 T' {3 t
进入到 hadoop002 的 ${HADOOP_HOME}/sbin 目录下,启动 YARN。此时 hadoop002 上的 ResourceManager 服务,和三台服务器上的 NodeManager 服务都会被启动:
7 R0 Y' J _4 K) Z6 T6 {* S1 S
3 c/ P0 r2 l' ], {, }5 Istart-yarn.sh
- j5 \. U; v# h' A1 L! R3 A需要注意的是,这个时候 hadoop003 上的 ResourceManager 服务通常是没有启动的,需要手动启动:( O2 \3 _# a. P4 N8 D
1 l2 s8 E, ?+ syarn-daemon.sh start resourcemanager
i& I! E# [- X9 `六、查看集群
/ H3 Y1 x3 M7 q, V m" _# _6.1 查看进程* g7 i7 z& ^- }& @: T1 N
成功启动后,每台服务器上的进程应该如下:
% @0 r0 E; `/ |3 e+ [* E
! v( S7 @- A" D! Q r( r1 @[root@hadoop001 sbin]# jps
% {7 Y7 o6 d! |/ }7 c2 Z6 l% ^5 X4512 DFSZKFailoverController3 {0 M% j2 b2 p; e7 ~
3714 JournalNode4 N p5 P1 V6 m- g7 y, a# S7 s6 N
4114 NameNode5 x3 d- b; I1 ?" i6 @5 u; C
3668 QuorumPeerMain
; e% y. Q9 x; [+ @6 g5 ?5012 DataNode
0 a ]" Q2 j u$ r/ V4639 NodeManager
: J9 s* H* y) e: i& d8 {+ S, b" g
1 @' o4 Y8 c5 ?0 {% w0 H+ o& P
. f4 j* |5 J7 b: W! Y- {[root@hadoop002 sbin]# jps: q' ~: N/ w: \' S+ z! k7 s1 O; S/ a
4499 ResourceManager
: V% W. u9 J* Q, ?4595 NodeManager
4 L8 `0 V4 t+ _4 {* ~' \0 @$ m4 Q3465 QuorumPeerMain* }6 b+ w2 c3 ]: Z/ x# c
3705 NameNode1 a5 I/ g. A( G6 c% K
3915 DFSZKFailoverController1 p' I3 y8 y+ G6 x5 s5 S6 g- G3 N6 \
5211 DataNode& u8 A' a" ^# H& z
3533 JournalNode- Y# [. P. [8 Z+ {% y
& l9 J7 ~* G0 T! g/ Y5 g. U. A( P0 z/ `
[root@hadoop003 sbin]# jps
& y( t1 v! @3 l- t0 I7 X3491 JournalNode' r: M( [; X0 Y. p# i( Q. \
3942 NodeManager
3 q5 a: U2 H; o0 T2 ~. z8 E' i4102 ResourceManager
& p: N3 R6 N( S2 _1 r; J% Q4201 DataNode
6 B. k2 }2 p; W8 ]3435 QuorumPeerMain( U& c" p* ~1 d- i- k: ?
6.2 查看Web UI
4 C' k! F: k% U) g: c; M; FHDFS 和 YARN 的端口号分别为 50070 和 8080,界面应该如下:
: T" B- Q t" p% _# P. E5 M2 o, Y9 q# g Y
此时 hadoop001 上的 NameNode 处于可用状态:0 ~/ i% s! F3 Q! x) B9 }& V9 ]. B
, S( W0 L' x0 z0 @
! \5 j/ h+ G) K3 R& I
而 hadoop002 上的 `NameNode` 则处于备用状态:2 z* p& ?+ k! e6 r6 ?' ~1 E
2 H3 Q$ D3 n: H$ ]2 h# `1 b( v9 b$ V2 R* y+ n, a( I) P0 \
hadoop002 上的 ResourceManager 处于可用状态:
" B& G. J5 L* B
- g" ~5 I( t* d! ~. |1 {3 j4 U
[) K# o( e; e9 @2 C
+ j; F3 t7 w! G
# e9 s9 m- f1 ohadoop003 上的 ResourceManager 则处于备用状态:
1 R) S# v1 h/ l" B7 {6 a W# u4 H4 G! X; Q/ |; p
3 p2 F& [3 v9 s1 L) }% |# E& W( v# J4 z1 i% E- L* P6 o5 m+ V
9 }$ r& B! G, _" G3 U7 E' u9 K
同时界面上也有 Journal Manager 的相关信息:0 C$ i# `1 {, K7 u8 X
5 f0 M- f, i! ], }5 I! m3 t0 }. j
8 x/ @* M2 |+ O% \8 B" c4 z# m; q7 y ^
## 七、集群的二次启动
' \+ f5 l7 @7 \+ _$ ^- M上面的集群初次启动涉及到一些必要初始化操作,所以过程略显繁琐。但是集群一旦搭建好后,想要再次启用它是比较方便的,步骤如下(首选需要确保 ZooKeeper 集群已经启动):. B( J; K* c+ N% F7 ^* S
. T7 x" M U, a# d* L! G在 hadoop001 启动 HDFS,此时会启动所有与 HDFS 高可用相关的服务,包括 NameNode,DataNode 和 JournalNode:
9 V$ k. r9 P& }" n3 C2 T5 P( H7 H, k$ h- _
start-dfs.sh
9 P# U. ]3 {$ C$ }在 hadoop002 启动 YARN:" t7 K1 N& J" Z* r6 d( r
; ^. N4 C x, j5 f, M- Z7 Q) ^, fstart-yarn.sh2 P" q# e- o6 g& Z# Q- @2 R& Z/ G
这个时候 hadoop003 上的 ResourceManager 服务通常还是没有启动的,需要手动启动: n3 f( [; v' C$ P& |0 {1 T$ o
! i9 F L# ]; q4 Z6 ]
yarn-daemon.sh start resourcemanager( P1 {3 Z8 V: j$ S1 q- U* p
; {) W4 J1 o/ g% F |
|