|
|
楼主 |
发表于 2022-11-15 10:00:33
|
显示全部楼层
一、高可用简介3 s" M9 D' M4 ^. t" v; V3 F/ p
二、集群规划( F# E/ t' C3 ^$ h
三、前置条件' @. r4 g( b( Y3 s9 c5 [5 t, a% L
四、集群配置/ Y/ o* p5 h9 c& Y7 K, K F4 ?4 o
五、启动集群8 G7 S) a& J, [% J1 C( p6 N
六、查看集群
& @" z' a2 A9 y4 u) j七、集群的二次启动
! {! o. l6 d1 Q+ ^% S- V$ n一、高可用简介/ y a4 E3 `0 o* f
Hadoop 高可用 (High Availability) 分为 HDFS 高可用和 YARN 高可用,两者的实现基本类似,但 HDFS NameNode 对数据存储及其一致性的要求比 YARN ResourceManger 高得多,所以它的实现也更加复杂,故下面先进行讲解:; i! |6 U( L A9 z: v! I9 v
5 d& h, f( @2 v" i+ L
1.1 高可用整体架构& k( L/ V6 d5 ]( b! y5 ~
HDFS 高可用架构如下:
9 |% Q1 T2 R6 d, Q& i7 D+ h9 \# g Y% @5 k* w% Q
% k+ G" D h# s6 t: \/ G; H) |图片引用自:https://www.edureka.co/blog/how- ... -high-availability/2 m7 F: I. X. n! I" J
" _6 v+ h% e5 `+ L c VHDFS 高可用架构主要由以下组件所构成:8 U& j# f( V6 T }$ V, [% ?2 n: a
. L. g- X1 j9 OActive NameNode 和 Standby NameNode:两台 NameNode 形成互备,一台处于 Active 状态,为主 NameNode,另外一台处于 Standby 状态,为备 NameNode,只有主 NameNode 才能对外提供读写服务。
! Y) S6 g6 e( A
* ~) k+ J$ |( \2 H9 n8 T. |6 N主备切换控制器 ZKFailoverController:ZKFailoverController 作为独立的进程运行,对 NameNode 的主备切换进行总体控制。ZKFailoverController 能及时检测到 NameNode 的健康状况,在主 NameNode 故障时借助 Zookeeper 实现自动的主备选举和切换,当然 NameNode 目前也支持不依赖于 Zookeeper 的手动主备切换。: _0 ]6 ^/ }& k p. f0 Z3 a$ l
) C% r' ^$ E0 U& S
Zookeeper 集群:为主备切换控制器提供主备选举支持。2 s6 o" R8 i2 G; S9 d* J! G5 X5 M3 ~/ r
# E7 Y1 s+ u- M: q共享存储系统:共享存储系统是实现 NameNode 的高可用最为关键的部分,共享存储系统保存了 NameNode 在运行过程中所产生的 HDFS 的元数据。主 NameNode 和 NameNode 通过共享存储系统实现元数据同步。在进行主备切换的时候,新的主 NameNode 在确认元数据完全同步之后才能继续对外提供服务。8 j" J2 l0 k9 }
; D- I3 R/ _' {: C8 eDataNode 节点:除了通过共享存储系统共享 HDFS 的元数据信息之外,主 NameNode 和备 NameNode 还需要共享 HDFS 的数据块和 DataNode 之间的映射关系。DataNode 会同时向主 NameNode 和备 NameNode 上报数据块的位置信息。
, n% a) R+ H% l, H
3 V8 b: c7 Y# q1.2 基于 QJM 的共享存储系统的数据同步机制分析9 U9 W" X. Q* G, S2 b# u
目前 Hadoop 支持使用 Quorum Journal Manager (QJM) 或 Network File System (NFS) 作为共享的存储系统,这里以 QJM 集群为例进行说明:Active NameNode 首先把 EditLog 提交到 JournalNode 集群,然后 Standby NameNode 再从 JournalNode 集群定时同步 EditLog,当 Active NameNode 宕机后, Standby NameNode 在确认元数据完全同步之后就可以对外提供服务。- u" E7 |* {' y
; C# V* {4 d6 V" e. c需要说明的是向 JournalNode 集群写入 EditLog 是遵循 “过半写入则成功” 的策略,所以你至少要有 3 个 JournalNode 节点,当然你也可以继续增加节点数量,但是应该保证节点总数是奇数。同时如果有 2N+1 台 JournalNode,那么根据过半写的原则,最多可以容忍有 N 台 JournalNode 节点挂掉。
6 O+ J1 C8 s" O# C" ~4 I9 l+ T# W7 {" f5 s5 n) k& U
: H6 a; h# k) o( D8 k
1.3 NameNode 主备切换
% r6 o3 m; w" ~& Y3 ^NameNode 实现主备切换的流程下图所示:( g0 H5 @! d! F8 v* A* Y# a5 m$ U
: {) Z9 X( \7 ?% E3 z1 u& d: E8 |# h4 a1 H' |
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 状态。* Q2 a& q$ \" H. B
1.4 YARN高可用& H* a) O. o* f* `0 ?
YARN ResourceManager 的高可用与 HDFS NameNode 的高可用类似,但是 ResourceManager 不像 NameNode ,没有那么多的元数据信息需要维护,所以它的状态信息可以直接写到 Zookeeper 上,并依赖 Zookeeper 来进行主备选举。1 z" N0 R! }0 R5 Q$ w7 B" l# x
* c6 h4 J2 t( b8 ?; n! ^6 Z" @$ C. n3 L9 ?" R: v2 `
二、集群规划: \! T5 L& ~8 Y/ h" ?0 q
按照高可用的设计目标:需要保证至少有两个 NameNode (一主一备) 和 两个 ResourceManager (一主一备) ,同时为满足“过半写入则成功”的原则,需要至少要有 3 个 JournalNode 节点。这里使用三台主机进行搭建,集群规划如下:5 y. W" G% d1 b( z3 E' C' `; v, p
" m# `' i$ H7 g2 g
b+ R) ?3 ?. ~/ m& z! n三、前置条件
& N5 w) k3 C) X& _! d- ]所有服务器都安装有 JDK,安装步骤可以参见:Linux 下 JDK 的安装;6 `" H2 u9 [! E8 R
搭建好 ZooKeeper 集群,搭建步骤可以参见:Zookeeper 单机环境和集群环境搭建
& L) t1 ]" ?/ n" W所有服务器之间都配置好 SSH 免密登录。$ G7 p9 h$ n) c: B, o
四、集群配置
}; j5 }# Z6 S6 g; ?) E1 O4.1 下载并解压) y" L) |( ~+ J% N7 `2 l
下载 Hadoop。这里我下载的是 CDH 版本 Hadoop,下载地址为:http://archive.cloudera.com/cdh5/cdh/5/
7 j3 b8 t! S5 t" Q
0 }4 G" v5 _+ E6 A9 q6 X7 [2 n# tar -zvxf hadoop-2.6.0-cdh5.15.2.tar.gz
) Y4 U/ i6 V# x7 h3 W: ^5 ?! [: y3 `4.2 配置环境变量% Q/ m: M/ u" V$ y0 C3 E9 m
编辑 profile 文件:8 s' f2 y2 L! [: v
y4 K& \3 J6 h! O. k# vim /etc/profile
\* s- I: T+ J/ s; N4 ~) {* C增加如下配置:" t/ n( h' d3 ]1 h
^% r5 {3 T! z- C" N9 Q9 Fexport HADOOP_HOME=/usr/app/hadoop-2.6.0-cdh5.15.2
! p( C9 Y: h1 h' |; L% J; k0 h0 q0 j! ?export PATH=${HADOOP_HOME}/bin:$PATH
- {9 u: E. T! U/ Y4 ^; ?! y2 K. H执行 source 命令,使得配置立即生效:
j, i: W/ G& n. ?, x* [
! f) j }' s: R1 z# source /etc/profile, }& P) Z8 ^8 u* c E" c& w; S" E! M
4.3 修改配置
7 \: T% i$ G# q# z7 ?( O进入 ${HADOOP_HOME}/etc/hadoop 目录下,修改配置文件。各个配置文件内容如下:
* `2 m& Z) E. s: ^+ y( D
1 f- |, z1 D. A/ w1. hadoop-env.sh
+ c7 q% v& x/ H, P' I1 D! |# 指定JDK的安装位置
( E {5 V3 |6 o5 Fexport JAVA_HOME=/usr/java/jdk1.8.0_201/
. \" x( E3 q# U" ?* z& T2. core-site.xml" o/ x5 T" d+ A! {1 N( A
<configuration>4 ?$ ^9 z& V! `1 v, _& ^; x/ O) y
<property>$ U1 M4 b/ S& h! N% s3 c
<!-- 指定 namenode 的 hdfs 协议文件系统的通信地址 -->( N# k) X4 u% e- q6 z; n
<name>fs.defaultFS</name>
* Y( L5 u1 t8 {- X1 }7 r0 G( O <value>hdfs://hadoop001:8020</value>
9 Z; F% J: L Z& U1 Z; X </property>
% c+ ]& P) P! s* i8 R, t) `" g <property>; ^3 B' r: {( s& q1 R" A. d
<!-- 指定 hadoop 集群存储临时文件的目录 --> d5 M2 P) R( E3 a2 y
<name>hadoop.tmp.dir</name>' A2 K S2 O4 P8 a% d$ {
<value>/home/hadoop/tmp</value>- d4 J0 e" m6 |7 Q. j1 B: `
</property>
: n$ g# d6 E; J9 P% i* E' a <property>
0 f1 g: p6 S2 V# p- h# U' I <!-- ZooKeeper 集群的地址 -->% L0 Z6 P& B- c6 e4 {. I
<name>ha.zookeeper.quorum</name>4 `3 Q O. L% n9 h3 o- l% m
<value>hadoop001:2181,hadoop002:2181,hadoop003:2181</value>
$ f( n/ `3 {1 r% O: T </property>& j; _! O! \7 h2 d# v$ i
<property>2 `! f/ Y( ?( A2 m8 O) S3 Z* x: z: l
<!-- ZKFC 连接到 ZooKeeper 超时时长 -->8 n4 D: f; t- d
<name>ha.zookeeper.session-timeout.ms</name>4 @# {9 ]6 b- q' |/ ^. L
<value>10000</value>- B6 P# |6 }: x3 L7 [# a* m; `
</property>
# R1 L: u. f8 C3 d& q</configuration>
& h$ h9 ]8 ~" x4 [6 Y4 `6 q3. hdfs-site.xml
$ T5 S+ C# D& s' {! [8 W7 Z: t1 O' T<configuration>0 s2 {# X J7 m% X
<property>! j, K9 o; ]; H( b l! C
<!-- 指定 HDFS 副本的数量 -->
6 y6 ^! r# n* c) d% h5 X7 x <name>dfs.replication</name>$ n. r4 g, m' S
<value>3</value>6 j2 Y# O( v2 Y1 [% b
</property> x4 g/ Y& w# r& l6 ~" G3 V! c7 j
<property>
1 l# V* q9 L7 _% \) V9 x f; A <!-- namenode 节点数据(即元数据)的存放位置,可以指定多个目录实现容错,多个目录用逗号分隔 -->
, x* H9 b2 W5 G' g# S- v7 l <name>dfs.namenode.name.dir</name>
0 T. R$ J' l3 H/ L' B c <value>/home/hadoop/namenode/data</value>
& f& s/ I; q8 n </property>
/ u3 J% P$ ^1 q6 B" R& R <property>3 Z* F* K: j8 z" \; H
<!-- datanode 节点数据(即数据块)的存放位置 -->
( `/ }3 ]4 V, Z W6 B$ b) V <name>dfs.datanode.data.dir</name>
/ r- R! x" B9 ~ g. | <value>/home/hadoop/datanode/data</value>
! c4 e( E6 h- v7 p, e% @$ n </property>
3 A @$ Q1 _+ D" Z <property>
+ b. s1 k' e2 x% \" Y <!-- 集群服务的逻辑名称 -->
: g5 l# v S! i# [8 F( W. Z/ _ <name>dfs.nameservices</name>7 T/ q! Q" K- L. \# a5 x
<value>mycluster</value>
! S# T: _* S5 j' f9 X% l </property>
5 q& N6 e% }0 Y$ b; E5 N <property>
5 }" c1 P5 a1 l, u3 k1 \ <!-- NameNode ID 列表-->( j- l! j5 T& J1 s9 a% ~+ L% J
<name>dfs.ha.namenodes.mycluster</name>1 Z/ D/ h" J; E1 e3 j! f+ \% E! g) e
<value>nn1,nn2</value>
, F# U$ q( G, @ </property>
' k5 o1 p1 m6 L& T <property>
, q) m6 j( n+ q' L <!-- nn1 的 RPC 通信地址 -->
: x: N0 D( c, ?& C <name>dfs.namenode.rpc-address.mycluster.nn1</name>
) ^" P: T7 Q p8 z <value>hadoop001:8020</value>6 T! c. c+ _: L6 Z) F
</property>/ i: A* A. b, _& @
<property>1 Z/ h0 X1 O# \0 D7 X Z
<!-- nn2 的 RPC 通信地址 -->
# S1 k4 q) _; M0 }0 d5 I& _0 v- I <name>dfs.namenode.rpc-address.mycluster.nn2</name>9 B* n( k" L/ k) P# _
<value>hadoop002:8020</value>9 {) p6 s3 ?; V9 v/ y
</property>7 D1 Y& r7 ^/ E0 t2 Y
<property>7 {( a, ^ q% U: C# I" u- j0 O! c
<!-- nn1 的 http 通信地址 -->
& k9 D a6 m; s( e <name>dfs.namenode.http-address.mycluster.nn1</name>% }$ E8 |4 J, ^+ a3 f$ W$ Y [
<value>hadoop001:50070</value>
: a' s" c2 Z `1 \% n </property>
; C- P9 ?+ f6 w8 H+ X% k <property>
; O( A" i* B. }9 S0 b <!-- nn2 的 http 通信地址 -->0 R$ i2 ` P( O2 P: e
<name>dfs.namenode.http-address.mycluster.nn2</name>
- K5 a0 ?, \4 i9 @, ?7 ^ <value>hadoop002:50070</value>
: T7 @5 {) N7 r( M1 f8 H </property>
1 L+ s1 c' q3 A6 _/ T* i <property>- @5 [# `1 a4 k5 n
<!-- NameNode 元数据在 JournalNode 上的共享存储目录 -->
( E7 G7 r2 R2 _) E z/ H2 t <name>dfs.namenode.shared.edits.dir</name>
9 S! Y0 K: E3 [, ] N4 q. Z <value>qjournal://hadoop001:8485;hadoop002:8485;hadoop003:8485/mycluster</value>
+ J( o) c9 z3 \ t </property>- U. h8 g7 P! n+ E/ q
<property>
- F3 z l3 E# D& u- ` <!-- Journal Edit Files 的存储目录 -->
: n$ ^- E, c2 S- e; E) B <name>dfs.journalnode.edits.dir</name>
$ C: J0 X( q- ?( U t$ w. G <value>/home/hadoop/journalnode/data</value>3 U% p; H- v$ Y. P" [
</property>
- h) m3 h; o0 E <property>
- C$ E- N( h7 J. Z4 j9 e <!-- 配置隔离机制,确保在任何给定时间只有一个 NameNode 处于活动状态 -->
5 w2 Z. }4 d% g$ |: p9 m- s% P <name>dfs.ha.fencing.methods</name>: n7 c. n4 V G5 j$ N K# t8 H; e7 s4 }
<value>sshfence</value>; z4 j2 T# { V6 R. v
</property>/ c; c% S$ B" j$ [6 j+ u; ^6 T4 k
<property>
" t i( P6 d1 i+ S$ A8 v- M <!-- 使用 sshfence 机制时需要 ssh 免密登录 -->
# ^; U, z6 ?; h% Z8 `1 x <name>dfs.ha.fencing.ssh.private-key-files</name>
* }' h0 x6 ]2 W, O. T <value>/root/.ssh/id_rsa</value>
, }; ~7 Q2 H. s( Q- e" k </property>
4 G+ G8 O4 [3 [ D6 l; v6 N* r' ^ <property>+ w# c- B4 g5 R7 ?5 ~, w
<!-- SSH 超时时间 -->8 V; W, W) r, t) B1 f+ c
<name>dfs.ha.fencing.ssh.connect-timeout</name>$ d4 d# i2 A1 E% Z h/ O' h9 k Q
<value>30000</value>7 p' o' U; J1 h2 [" W
</property>
! l" \- j" V, ?1 p* ^) H5 @$ A <property>
! w2 |- R. v- n+ V8 h L* ] <!-- 访问代理类,用于确定当前处于 Active 状态的 NameNode -->' l# W" k' F6 Z9 l7 m9 ~
<name>dfs.client.failover.proxy.provider.mycluster</name>& @; C$ `4 y7 Q6 S
<value>org.apache.hadoop.hdfs.server.namenode.ha.ConfiguredFailoverProxyProvider</value>
4 b( H0 F5 p! e, v </property>
5 G* v( ~, s% ~& x1 D0 G$ _ T6 |4 u <property>" g3 p* ]+ S# o! ^, {+ O
<!-- 开启故障自动转移 -->* A7 Q3 ^) y/ b8 K0 N
<name>dfs.ha.automatic-failover.enabled</name>
# a: G% R/ t, z b `! [ <value>true</value>, }, B' G2 s$ d: b: I- N! x% ^8 b
</property>
" X+ I+ `. Z N; F3 q( y) g- ^</configuration>
$ p. g; B4 U7 G+ ]! G& k4. yarn-site.xml
" C h6 w" p; q. m" ~1 U* r' ~8 ^<configuration>
# W! O: h' m- h2 J+ J7 P8 @- n* j <property>2 w5 Q( { ]% W X8 l
<!--配置 NodeManager 上运行的附属服务。需要配置成 mapreduce_shuffle 后才可以在 Yarn 上运行 MapReduce 程序。-->
3 e" Y8 U5 {3 ^; t# z <name>yarn.nodemanager.aux-services</name>
" c5 i, W3 t# C( b, v, M6 W <value>mapreduce_shuffle</value>
+ {, ~: P" C0 s& ]! _ n/ Z' o </property>& ?$ z9 w0 \! [
<property>! l6 `& O, |/ o3 T
<!-- 是否启用日志聚合 (可选) -->6 u# @. Q$ m8 ^& A
<name>yarn.log-aggregation-enable</name>5 D$ Q! _4 a F% ] D& C
<value>true</value>, e; ]& d! w7 O
</property>4 y7 s @1 H1 I# K) P& F( ?2 a4 b
<property>
) j; ^9 g* ^4 g- ] <!-- 聚合日志的保存时间 (可选) -->
: U% W: U3 c7 W% U <name>yarn.log-aggregation.retain-seconds</name>
6 V6 L; ^; }1 Z/ ]% L* s0 v1 b <value>86400</value>
% X Y. Q4 S) o k" e0 j </property>- x; q7 l" f' ]7 g
<property>, R' B. }) I. V& T% @6 l
<!-- 启用 RM HA -->
* O% M( i5 a& i9 |" x! c# J L0 | <name>yarn.resourcemanager.ha.enabled</name>4 |1 i; l8 ?7 h7 j
<value>true</value># {) m9 _* N5 T A
</property>; Y# d/ ^+ v* F) [( m; {) ]
<property>" n, c9 ]6 g* K4 W
<!-- RM 集群标识 -->
$ Y5 i" q' b) ]% _5 t* R <name>yarn.resourcemanager.cluster-id</name>( _+ V/ l+ g. n+ k: ~
<value>my-yarn-cluster</value>% P0 D' Z, P5 t4 o
</property>8 |2 S1 @; T) y! q( p7 v7 M
<property>4 a0 P% J+ W9 K% e
<!-- RM 的逻辑 ID 列表 -->7 V" @- w" w; T, N: U6 _$ S
<name>yarn.resourcemanager.ha.rm-ids</name> S3 g& e7 z' u" _/ U
<value>rm1,rm2</value># c+ z( i* J4 N9 a+ g$ t+ n/ Y0 }
</property># s4 o! [! m/ [5 }9 k
<property>
% z w& ~8 m* W <!-- RM1 的服务地址 -->
7 ]0 M8 ^6 k' ]( v <name>yarn.resourcemanager.hostname.rm1</name>6 B* o0 `0 Y% e$ D
<value>hadoop002</value>" t9 q$ j8 P, i5 e+ {) N
</property> I$ ]# M5 e/ d/ V: A. g. t
<property>
2 F( T, l& o9 G <!-- RM2 的服务地址 -->
/ E5 D5 t1 |8 a+ {: q$ k W" c <name>yarn.resourcemanager.hostname.rm2</name>& i1 W ?$ S- g( h- p( K% M+ Q
<value>hadoop003</value># a) a9 R. V; n/ e: L j+ R( V
</property>! c8 O( A$ G' p) N: X1 q4 m
<property>% i' ^0 E D: b/ c; R. S8 F
<!-- RM1 Web 应用程序的地址 -->
1 \! X& ~ `. x' _' O5 v5 H$ g <name>yarn.resourcemanager.webapp.address.rm1</name>
6 x: m" b) U& ]3 o <value>hadoop002:8088</value>
/ {$ S( ~! j4 G& W/ l! N) [: M: ^1 J1 T </property>" n7 }( j0 D( Q9 z6 l
<property>; @4 W# u# N0 y# s
<!-- RM2 Web 应用程序的地址 -->
6 L2 `7 |6 j3 e$ U <name>yarn.resourcemanager.webapp.address.rm2</name>- k6 S( P2 z+ s8 T; `0 `
<value>hadoop003:8088</value>5 k* l( `' e7 g% V' V/ H
</property>9 X7 C3 X# p' Q' M$ w% Z" R$ i
<property>* z& b! c, Z0 X* y) p: P
<!-- ZooKeeper 集群的地址 -->+ s2 i3 _ r6 _ U5 J
<name>yarn.resourcemanager.zk-address</name>
( i4 U D- |0 j/ M4 v* F# E <value>hadoop001:2181,hadoop002:2181,hadoop003:2181</value>
1 J9 R: I6 C+ t5 t4 x, i </property>1 l! r4 T1 A) X2 i- s
<property>, ?5 {5 _8 M+ k- P+ x0 E4 R
<!-- 启用自动恢复 -->. H" _$ {4 _- z x3 V4 n
<name>yarn.resourcemanager.recovery.enabled</name>' Z& ]$ Z) p1 e$ G2 L/ Q6 G$ G) P
<value>true</value>
% f8 b5 r+ }& u) V: I/ D! k# d; T$ v: y: O </property>' i9 F9 S1 R. P/ f2 t+ p4 B% D
<property>
4 L' g$ i/ W- X/ g) s, |) J5 s <!-- 用于进行持久化存储的类 -->
# E% O7 M* t$ {* F <name>yarn.resourcemanager.store.class</name>
7 K! R! @! t+ g: \ <value>org.apache.hadoop.yarn.server.resourcemanager.recovery.ZKRMStateStore</value>
7 t- T9 q; R" U </property>* \ I" k4 a- \" d- G5 H* C% K
</configuration>
. S* Q' d' N+ A5. mapred-site.xml
4 B: R0 U2 _' U<configuration>) \! g. s/ q9 R/ t0 _* F3 [
<property>
" F/ @4 F/ \7 h9 l" ~ <!--指定 mapreduce 作业运行在 yarn 上-->) N5 g0 e4 d3 U9 H9 E! M5 m
<name>mapreduce.framework.name</name>+ s) J) |0 R' n# i; R. g
<value>yarn</value>
- O7 {0 l: C; H: u </property>
6 C5 c# O' _% B# k7 A( q5 f0 w</configuration>
! e& _4 D2 ^4 U: ]/ v+ L5 J& c5. slaves
1 j, V2 T; R' d; ~7 Y配置所有从属节点的主机名或 IP 地址,每行一个。所有从属节点上的 DataNode 服务和 NodeManager 服务都会被启动。
5 j& l2 |8 @8 \7 c2 v
9 r9 ^& F& f6 J7 `* ?0 jhadoop001
; u/ K3 V5 h1 i+ qhadoop002
9 t4 D' B/ }$ f$ p1 h6 x) Uhadoop003
' a6 h7 M8 v k4.4 分发程序, F$ d d! y) k5 z/ Y" K" ^) s
将 Hadoop 安装包分发到其他两台服务器,分发后建议在这两台服务器上也配置一下 Hadoop 的环境变量。
% e; u1 t4 q. W. F( i# C
% E* j" V. b+ e$ N& ]: x6 ?# 将安装包分发到hadoop0024 a2 z3 v+ F6 r6 f3 I j8 E w
scp -r /usr/app/hadoop-2.6.0-cdh5.15.2/ hadoop002:/usr/app/
7 A% p9 @8 ]6 c# n, P A) p# 将安装包分发到hadoop003
. u4 v. ]5 s: N R1 ]scp -r /usr/app/hadoop-2.6.0-cdh5.15.2/ hadoop003:/usr/app/2 a1 l: |! Q6 { E9 \" H9 h: u+ S0 m
五、启动集群
+ m: y" v/ c9 S9 e; o- z* {5.1 启动ZooKeeper0 r" q# B, |5 \5 f% q' o! E% h5 i
分别到三台服务器上启动 ZooKeeper 服务:& T U' e5 r# Z6 p" B" U, d' ~
; ]. ^" R. ]8 _! T( O" t) J7 i zkServer.sh start1 R6 v! U' s* ^) H
5.2 启动Journalnode
|( M( r( g5 b' ^: C# E分别到三台服务器的的 ${HADOOP_HOME}/sbin 目录下,启动 journalnode 进程:
/ s$ y2 Z$ }- l) [$ X* J# z1 g
" ]: P: q8 ^$ b1 P$ z& [9 Q Shadoop-daemon.sh start journalnode
8 S: g& v. y/ ^1 @: P. O% \: I) U5.3 初始化NameNode
) V% }6 p3 t3 I' I' l! a在 hadop001 上执行 NameNode 初始化命令:
1 X, t; l1 P( N# Q S3 I1 W5 V( @4 j9 }9 g
hdfs namenode -format2 X$ K9 e; u' s" [! f
执行初始化命令后,需要将 NameNode 元数据目录的内容,复制到其他未格式化的 NameNode 上。元数据存储目录就是我们在 hdfs-site.xml 中使用 dfs.namenode.name.dir 属性指定的目录。这里我们需要将其复制到 hadoop002 上:, T( ~( q' z7 C
7 W" N- K! \3 G5 ~, a- | scp -r /home/hadoop/namenode/data hadoop002:/home/hadoop/namenode/' i! N" o R* Q, h `
5.4 初始化HA状态1 L5 L6 l* @ L# Z' X* @8 ?
在任意一台 NameNode 上使用以下命令来初始化 ZooKeeper 中的 HA 状态:
. |. `, T3 |6 ?* V+ Z/ Y& X/ d
: E3 S1 a# k) j! C/ Bhdfs zkfc -formatZK
" k) s/ ], ], D# B# g3 {; p5.5 启动HDFS8 @5 ?0 [" S B0 f
进入到 hadoop001 的 ${HADOOP_HOME}/sbin 目录下,启动 HDFS。此时 hadoop001 和 hadoop002 上的 NameNode 服务,和三台服务器上的 DataNode 服务都会被启动:5 w" i/ `, O$ D# k* N3 ?. _1 S {
, c, M' ?) @) n4 G/ G$ n8 [start-dfs.sh. |, R1 ?7 ~. ]. S/ m! D! Z; q
5.6 启动YARN3 L4 {1 ?, L8 u2 p6 S1 o' J W
进入到 hadoop002 的 ${HADOOP_HOME}/sbin 目录下,启动 YARN。此时 hadoop002 上的 ResourceManager 服务,和三台服务器上的 NodeManager 服务都会被启动:
. [. J4 f, P% N; _' j8 o# h V* w* V# q. s1 `( d
start-yarn.sh
0 `" L; G2 L% K* U需要注意的是,这个时候 hadoop003 上的 ResourceManager 服务通常是没有启动的,需要手动启动:
) x2 q# j. s1 W# n2 g0 O% K: `( `7 U9 P! v& g {& `- Q
yarn-daemon.sh start resourcemanager( s& v0 z) P" O" u( m
六、查看集群: S* d, d6 Q8 x9 r6 m
6.1 查看进程7 F+ b* o7 s8 o; i
成功启动后,每台服务器上的进程应该如下:
; n: V2 K; K4 d. R' m3 f1 }5 Z( @4 ?" S
[root@hadoop001 sbin]# jps
6 o( Y9 W9 A/ N) u* n0 K4512 DFSZKFailoverController# }% |% H# ]# `+ U! P1 B) f7 }
3714 JournalNode r) v R2 ~: p2 Y
4114 NameNode: C# ^8 K+ m( Y- E. c6 f" K+ [
3668 QuorumPeerMain# O/ ?4 f3 E$ [: z9 j; W, G" U
5012 DataNode* t. {# i1 [; G2 ^$ g `$ {
4639 NodeManager! P% {/ L& z) z, ~* K5 j
( U+ V2 h5 m. I F/ h8 u0 G8 w$ E) _% A2 N
[root@hadoop002 sbin]# jps
# V* g6 ^9 d5 [* x6 b& p# G: _* D4499 ResourceManager' V, U, F/ a! Y' i0 N: B
4595 NodeManager* _ a3 `9 X+ C
3465 QuorumPeerMain: X2 w' G& m8 N9 n- x
3705 NameNode0 G2 G# y0 ]4 b8 V
3915 DFSZKFailoverController
/ I, b( }& S+ W- l4 p4 {5211 DataNode' w/ S. p/ w% v7 W* u" F! t7 X# \' m; i
3533 JournalNode
5 B, {% @1 F4 }0 c8 Y
5 u( \& n# `$ y6 {1 K: {* N) [, A: g, E# {& l7 Z2 l
[root@hadoop003 sbin]# jps
+ \2 D! z- v; H3 Q5 b2 V- G3491 JournalNode) O. V1 l2 Y' W
3942 NodeManager2 u' u3 c4 p# a A; b5 Q
4102 ResourceManager
2 ~" o) S9 {6 m" N; E4201 DataNode
& o- v5 Y" n- a1 S% H3 f7 P: Z0 G: R3435 QuorumPeerMain
s# z: c6 f/ u1 r- U6.2 查看Web UI6 Y; [' x9 g4 _/ N2 M7 S4 q
HDFS 和 YARN 的端口号分别为 50070 和 8080,界面应该如下:
2 i& [& Q$ r6 u \9 \# p
: {; t9 N* X- W! S此时 hadoop001 上的 NameNode 处于可用状态:3 K4 b, t& E. [6 F
9 t4 L% z2 }& L# h9 b4 z
1 T {8 ^2 C3 p+ ?4 N3 b8 p/ l) D而 hadoop002 上的 `NameNode` 则处于备用状态:: p/ U& w- E" H9 c
3 l9 U0 I7 C" \; |0 t
% d, I7 Y/ C$ S T: Jhadoop002 上的 ResourceManager 处于可用状态:8 ^- P1 W6 C( _4 k% F7 M! j0 e2 e8 h
% T& Q) A# R D6 X; @6 {2 Q+ t) v* J0 B1 M! {
" L; u- U( B U
- F% [6 r8 W! q2 Fhadoop003 上的 ResourceManager 则处于备用状态:
2 j* Q( F2 @% Z5 i4 f# ~- z4 i( H# l; J; o1 O `( v
: ~& m- \8 Z$ L2 W, ?& ?1 T) y, ~" L( ^! N3 a% ]& L" J
2 T% l3 w+ i" ^- B+ B6 a同时界面上也有 Journal Manager 的相关信息:
: v, f4 c7 _' I2 j
9 X" y" S3 {& X, ?# i" h
% ?/ ^3 s; Q1 G" o6 O, P1 v
* [* w0 B" R( a- Y5 B) s* V% I## 七、集群的二次启动
* L' W9 i. ]( k) t$ T/ V9 p: g上面的集群初次启动涉及到一些必要初始化操作,所以过程略显繁琐。但是集群一旦搭建好后,想要再次启用它是比较方便的,步骤如下(首选需要确保 ZooKeeper 集群已经启动):, X3 R- E7 u% O; Q: v7 ~4 r
' Z5 ]7 R( G& z) k! ^$ f' m" g0 ~在 hadoop001 启动 HDFS,此时会启动所有与 HDFS 高可用相关的服务,包括 NameNode,DataNode 和 JournalNode:. t9 u/ E7 T8 S9 c' |6 L; i
. k* a* |9 t6 b8 `0 e
start-dfs.sh
$ g* Z8 M. f N- ~1 B& Q1 Y在 hadoop002 启动 YARN:
, I9 p. O" H+ G2 f( b) J
1 o; T7 x- k# t! H$ T: ostart-yarn.sh; I5 @ I* x+ }; T' @ ^2 j
这个时候 hadoop003 上的 ResourceManager 服务通常还是没有启动的,需要手动启动:0 y' J5 K! q0 E( ?
) f% z% t- w! _* p6 M+ ?yarn-daemon.sh start resourcemanager% K m6 N# e8 Q5 O" a; u0 a O9 q/ n' h" H
6 H* t# H8 d, x' M" b8 c |
|