|
|
楼主 |
发表于 2022-11-15 10:00:33
|
显示全部楼层
一、高可用简介
* g2 d' ~/ J1 K7 K二、集群规划0 r6 a5 @; d& K6 w
三、前置条件+ L! l5 R% C% T. D& _# n+ C
四、集群配置
2 k1 \1 J6 u9 y/ J+ n9 u五、启动集群* b# z+ k0 e# o9 B+ X
六、查看集群* y4 y8 F" _( H/ ? Y
七、集群的二次启动7 ?* ~" q$ A7 B& i( u/ j- |
一、高可用简介
' M, {! E1 i2 zHadoop 高可用 (High Availability) 分为 HDFS 高可用和 YARN 高可用,两者的实现基本类似,但 HDFS NameNode 对数据存储及其一致性的要求比 YARN ResourceManger 高得多,所以它的实现也更加复杂,故下面先进行讲解:/ V( k5 \( i% F. l0 l x/ k
' F6 h. u0 m9 _( S2 `2 y. E
1.1 高可用整体架构7 t3 T; \4 H% q/ R4 |% {
HDFS 高可用架构如下:/ u9 J$ w( W# v( \4 a8 U6 Z
$ \6 q, z4 v0 S
7 n \- }, [% j9 l2 L7 f图片引用自:https://www.edureka.co/blog/how- ... -high-availability/0 W& _* K: n. N I5 e6 K {
! c4 `* y4 E$ I( \! o) e$ p/ p! k
HDFS 高可用架构主要由以下组件所构成:
8 [2 v1 e) j0 r. s
1 Y* k T3 n: ~! vActive NameNode 和 Standby NameNode:两台 NameNode 形成互备,一台处于 Active 状态,为主 NameNode,另外一台处于 Standby 状态,为备 NameNode,只有主 NameNode 才能对外提供读写服务。7 U. S( i, K+ W, |4 K! f- w0 D" p
' l) P# ]- F' Q/ E
主备切换控制器 ZKFailoverController:ZKFailoverController 作为独立的进程运行,对 NameNode 的主备切换进行总体控制。ZKFailoverController 能及时检测到 NameNode 的健康状况,在主 NameNode 故障时借助 Zookeeper 实现自动的主备选举和切换,当然 NameNode 目前也支持不依赖于 Zookeeper 的手动主备切换。/ s# E% M1 m- Q T& e& c
; j% A/ \+ O% v/ D, f* ]: MZookeeper 集群:为主备切换控制器提供主备选举支持。; R+ v% [& t$ o. A
2 F& M7 H- u: j5 ^( \共享存储系统:共享存储系统是实现 NameNode 的高可用最为关键的部分,共享存储系统保存了 NameNode 在运行过程中所产生的 HDFS 的元数据。主 NameNode 和 NameNode 通过共享存储系统实现元数据同步。在进行主备切换的时候,新的主 NameNode 在确认元数据完全同步之后才能继续对外提供服务。
- c' w2 R: E* T% m0 |+ ^7 Q& e k+ [0 g( }( {, V8 b% P$ @% z
DataNode 节点:除了通过共享存储系统共享 HDFS 的元数据信息之外,主 NameNode 和备 NameNode 还需要共享 HDFS 的数据块和 DataNode 之间的映射关系。DataNode 会同时向主 NameNode 和备 NameNode 上报数据块的位置信息。* c0 Z+ w% h7 Z, g& O
. y, M: o6 C8 \$ a5 j& g
1.2 基于 QJM 的共享存储系统的数据同步机制分析) [* [0 l/ k, D/ E( \0 p. k' |
目前 Hadoop 支持使用 Quorum Journal Manager (QJM) 或 Network File System (NFS) 作为共享的存储系统,这里以 QJM 集群为例进行说明:Active NameNode 首先把 EditLog 提交到 JournalNode 集群,然后 Standby NameNode 再从 JournalNode 集群定时同步 EditLog,当 Active NameNode 宕机后, Standby NameNode 在确认元数据完全同步之后就可以对外提供服务。3 |2 D6 l) z3 F7 I4 u G- J
4 @' v) r- T0 r* A, W
需要说明的是向 JournalNode 集群写入 EditLog 是遵循 “过半写入则成功” 的策略,所以你至少要有 3 个 JournalNode 节点,当然你也可以继续增加节点数量,但是应该保证节点总数是奇数。同时如果有 2N+1 台 JournalNode,那么根据过半写的原则,最多可以容忍有 N 台 JournalNode 节点挂掉。
9 ?- C6 b1 x. N7 I, t q, K& H' j" A/ P+ m' }7 \
- {' M# N8 @; f! R
1.3 NameNode 主备切换% M$ [8 R$ _. i# p
NameNode 实现主备切换的流程下图所示:
" r+ R' V$ _+ Q7 y7 M& q
0 b3 i) a% e5 k% B& u. r. s, z2 `; A
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 状态。
3 }! o: b" t7 {# ]4 l1.4 YARN高可用& ?' y2 y- V5 H
YARN ResourceManager 的高可用与 HDFS NameNode 的高可用类似,但是 ResourceManager 不像 NameNode ,没有那么多的元数据信息需要维护,所以它的状态信息可以直接写到 Zookeeper 上,并依赖 Zookeeper 来进行主备选举。) S: {8 p6 G$ i1 @+ b* q* t* W$ N
9 a! X" j6 L, [ I
; b1 f4 k/ C, y6 W1 w1 t8 ]/ l2 J二、集群规划- O/ P4 _7 w7 |3 f" Y7 f6 M9 o# u2 F
按照高可用的设计目标:需要保证至少有两个 NameNode (一主一备) 和 两个 ResourceManager (一主一备) ,同时为满足“过半写入则成功”的原则,需要至少要有 3 个 JournalNode 节点。这里使用三台主机进行搭建,集群规划如下:
! ]2 p" C! K* b/ ]7 d' @8 ~7 C: U. _# R! k, p& G
- p2 [0 N u' s7 t
三、前置条件
0 u! N; ^ ]# T& z1 e8 a: D所有服务器都安装有 JDK,安装步骤可以参见:Linux 下 JDK 的安装;; y* ~ ]1 f" F( c+ F
搭建好 ZooKeeper 集群,搭建步骤可以参见:Zookeeper 单机环境和集群环境搭建5 M$ R8 O6 r& }& [# V! o& M
所有服务器之间都配置好 SSH 免密登录。
) u C$ ~1 p) I# X( G' i9 }, K四、集群配置; s( o4 v H- ]7 w
4.1 下载并解压
/ T) b; z' B, a! o" s下载 Hadoop。这里我下载的是 CDH 版本 Hadoop,下载地址为:http://archive.cloudera.com/cdh5/cdh/5/: Z3 j, b3 D* X( F( s
- y' B6 @6 b4 G* W% q* d# |, `4 \# tar -zvxf hadoop-2.6.0-cdh5.15.2.tar.gz - H% i) ^& z; t" E( N; \
4.2 配置环境变量) E3 m) g) q8 i6 N9 b T2 {
编辑 profile 文件:% Y) ?) H! m; i
) i: C; e+ f2 o& ^3 S- K8 I
# vim /etc/profile
- |8 K! i6 `; i; P, H0 g8 @增加如下配置:/ ^3 l7 U/ v# w, B- L( t$ R" ]
: T- H3 Z k7 ^export HADOOP_HOME=/usr/app/hadoop-2.6.0-cdh5.15.2& F0 k: \% b/ e% ?
export PATH=${HADOOP_HOME}/bin:$PATH
$ s* \$ c; s6 ^% T* f: S1 m! b5 p3 k执行 source 命令,使得配置立即生效:
$ X. f& r, `6 J8 t$ F8 s
: }4 o7 o4 R) O) K# source /etc/profile7 a. x4 O* ^$ S+ B
4.3 修改配置8 m' f. B9 m: w4 d% y: t
进入 ${HADOOP_HOME}/etc/hadoop 目录下,修改配置文件。各个配置文件内容如下:
) z2 g4 X+ x5 w ?/ y) e( [+ ~/ u" r2 P* d- \2 o( c
1. hadoop-env.sh
0 {" A& R( @( r0 z% v" y( h( d# 指定JDK的安装位置- h8 W$ O, ]1 z
export JAVA_HOME=/usr/java/jdk1.8.0_201/# }+ P4 `' \4 i' }- z" R
2. core-site.xml; l. @$ z6 K. q" v+ N: b7 l" S
<configuration>5 ` u3 z4 A/ }: r" w
<property>9 X0 A6 H9 c2 s
<!-- 指定 namenode 的 hdfs 协议文件系统的通信地址 -->
5 c9 v1 Z: a1 A4 o* e% g a, @ [' D9 z <name>fs.defaultFS</name>
3 _) g5 T7 w! ?! ` <value>hdfs://hadoop001:8020</value>
8 f( l9 x9 m$ P' h9 x </property>* A/ |8 h9 R; p9 N Z
<property>
3 F' K8 u1 B+ ? <!-- 指定 hadoop 集群存储临时文件的目录 -->
5 o6 O: ], H9 u( ?) p6 G) q <name>hadoop.tmp.dir</name>$ S5 c& v$ d; H1 E6 g$ C# k
<value>/home/hadoop/tmp</value>
1 L& u0 b) M, }; [5 b- n6 X; ? </property>
& F% w/ s# v9 s& X, {7 x& c <property>" |, ^" V, i" {. y7 R
<!-- ZooKeeper 集群的地址 -->
/ \* M; D% [' S4 ^: C0 a" M8 b% B <name>ha.zookeeper.quorum</name>* b; o% I: |& t1 K) K3 l
<value>hadoop001:2181,hadoop002:2181,hadoop003:2181</value>
2 @: T1 J, G' r) X7 S </property>8 w' _+ j9 ~- |0 _, _( \
<property>! S9 C- c5 T. x& |( T
<!-- ZKFC 连接到 ZooKeeper 超时时长 -->
+ b8 ?" P+ W9 P8 G <name>ha.zookeeper.session-timeout.ms</name>7 s N7 Q5 A( l9 S: y
<value>10000</value>
7 Y; U* t4 G1 R: H </property>
% `! k# o2 ?; z: O4 o</configuration>
% P h2 N4 b1 O3. hdfs-site.xml
. ?5 m+ m8 `9 V& T9 D<configuration>
+ @8 Z- H# S6 Q$ S! d <property>
) K, O: r6 _+ F2 f3 F3 x' D/ } <!-- 指定 HDFS 副本的数量 -->6 ?5 w$ m1 ?9 Y3 K% G+ Y; B
<name>dfs.replication</name>: i" M4 f2 b1 Y' `- f3 h+ w0 P- ~
<value>3</value>
2 w$ ^# g$ G" W$ V% w/ m; U7 { </property>) _: w3 C5 t# p# A
<property>" p9 I9 _1 p* y! E3 H# G6 }
<!-- namenode 节点数据(即元数据)的存放位置,可以指定多个目录实现容错,多个目录用逗号分隔 -->, L: }" H6 o5 S6 C, H# X. j" S. c
<name>dfs.namenode.name.dir</name>. O0 P$ Y* T- H3 t
<value>/home/hadoop/namenode/data</value>) L/ E- E* D' w8 B
</property>, E" Y/ N' S' w) @4 c' o d
<property>6 V+ ~8 y7 \6 U7 s' | K( T
<!-- datanode 节点数据(即数据块)的存放位置 -->
- N$ J5 Y, A' K4 q <name>dfs.datanode.data.dir</name>
; F+ }- d: j. z <value>/home/hadoop/datanode/data</value>
. g- X. p5 F# ~) V- s/ e, p </property>& ~7 [9 \; q+ {9 F: E2 h8 D
<property>
4 p' y' W2 [& N7 p/ n* K+ w+ ] <!-- 集群服务的逻辑名称 -->
/ B4 R8 {- ~$ X6 _# S <name>dfs.nameservices</name>+ L" K' {7 Q& I9 J$ `
<value>mycluster</value>
8 Q G6 b# ?1 { </property>
' [6 h' Z3 h: ^5 T <property>
; h: N0 a4 M7 ?6 q, }$ z2 s <!-- NameNode ID 列表-->
0 |3 W d6 n. z* |+ i4 e( y$ Z <name>dfs.ha.namenodes.mycluster</name>9 ~* I z4 K: I) `2 \
<value>nn1,nn2</value>& t# n- z) E1 _8 I8 Y0 e
</property>6 B7 W* l/ |; J3 |- v. h9 e
<property>
6 i/ e1 u, f l; a) [$ f# @4 }$ F <!-- nn1 的 RPC 通信地址 -->3 G1 ^' R4 ^9 l* ^$ U
<name>dfs.namenode.rpc-address.mycluster.nn1</name>
# ^: t$ Z* f0 N5 W, B' l <value>hadoop001:8020</value>' t! n; [! r. {5 \% c, @8 B. N
</property>
1 O6 f8 Z1 Q1 `" F C# f! g <property># u4 T3 [6 t6 F2 Y5 b" V0 \8 {
<!-- nn2 的 RPC 通信地址 -->
# q3 O% L! l u2 F+ O. O B( H <name>dfs.namenode.rpc-address.mycluster.nn2</name>
% }) M2 ]2 x. A) S \- f <value>hadoop002:8020</value>6 P ~) K5 Q/ w. Q }8 b
</property>
) D( T6 i+ f$ \5 g1 j$ b3 C9 Z <property>
# U# W3 u+ K0 F* Z. N <!-- nn1 的 http 通信地址 -->! B: D. q/ E7 ~% A/ W6 x) E
<name>dfs.namenode.http-address.mycluster.nn1</name>
" P' p( O! w- y& f" | <value>hadoop001:50070</value>. y+ y! Z1 y2 _, J
</property>
" W" c. M3 M5 F$ R8 d+ z& B6 H, y <property># p) V0 u8 L9 C) y L: Y7 ^
<!-- nn2 的 http 通信地址 -->
9 H n5 ?2 b" p) H <name>dfs.namenode.http-address.mycluster.nn2</name>
! _+ N8 |9 A4 X7 G. u- ]2 y$ O <value>hadoop002:50070</value>/ m/ W8 z! V9 n2 S" _: _9 N H
</property>! b5 U( t, k8 d/ H
<property>$ E0 o W' y# h* x+ ^5 a" U
<!-- NameNode 元数据在 JournalNode 上的共享存储目录 -->, v; k8 z- |+ O4 ?
<name>dfs.namenode.shared.edits.dir</name>& A/ w$ [% j" K% |( {5 n( L4 S/ {
<value>qjournal://hadoop001:8485;hadoop002:8485;hadoop003:8485/mycluster</value># T3 r4 X, _! L/ B1 K( {
</property>/ j/ y) n3 U1 F1 a9 f. a1 p
<property>! v9 c6 w" c2 j4 \2 X$ m' Z
<!-- Journal Edit Files 的存储目录 -->
! Q, T( z% p3 C( c- }. I' F9 R <name>dfs.journalnode.edits.dir</name>( M& U1 O7 A2 J% l' r
<value>/home/hadoop/journalnode/data</value>, H% _6 w" x W' z7 z8 A
</property>' ^6 i, h* I. t5 o+ b
<property>( ~2 U) s- \$ k* [ J
<!-- 配置隔离机制,确保在任何给定时间只有一个 NameNode 处于活动状态 -->+ [. D4 S0 d k3 I
<name>dfs.ha.fencing.methods</name>
- R6 {' c7 ~! q( p <value>sshfence</value>
' P1 a" z" Z: M </property>
7 z0 w- O* H% u9 ~) g5 y <property>
4 Q6 e9 f" H. O7 R' j <!-- 使用 sshfence 机制时需要 ssh 免密登录 -->
; F; O6 T k/ c4 c, C/ g% H0 v# h <name>dfs.ha.fencing.ssh.private-key-files</name>2 r. j0 {% R/ N2 W J1 o
<value>/root/.ssh/id_rsa</value>- t; ~* l" C: G4 I/ _
</property>
2 Q- F/ P+ S3 W% T2 N <property>$ c/ p. X( z8 K/ d4 D+ `
<!-- SSH 超时时间 -->
/ g4 t$ I% u0 y1 q! B4 I. o9 H' _ <name>dfs.ha.fencing.ssh.connect-timeout</name>
3 V6 k& X' F @# K8 q <value>30000</value>* c. R! j. _8 d+ `
</property>
$ z( j# _& V8 V! r <property>' R$ }6 _4 x9 B
<!-- 访问代理类,用于确定当前处于 Active 状态的 NameNode -->& \- x' S$ d5 k$ ~1 H, B, A
<name>dfs.client.failover.proxy.provider.mycluster</name>
" {, r) x5 t1 d" _4 V4 ^ <value>org.apache.hadoop.hdfs.server.namenode.ha.ConfiguredFailoverProxyProvider</value>
6 c/ H2 E$ ?) E5 X, K; z. P& } </property>
$ V& R( ]$ I! n8 V <property>
$ M: y( s, h8 \2 v! I s <!-- 开启故障自动转移 -->
: m( P, G1 H+ |8 j8 a <name>dfs.ha.automatic-failover.enabled</name>
2 j, }6 v' U8 n0 o# O& r+ L <value>true</value>2 n+ ~' G- r( r) f5 d4 t
</property>
$ o/ F; `7 Z! p9 B$ {2 X/ u' i</configuration>" U5 _" y) _8 ^& D1 a
4. yarn-site.xml- I. u: k& n* A$ p
<configuration>
( o$ S4 S- T2 U! l- p <property>
3 q% N0 S0 I, n, S: E: u <!--配置 NodeManager 上运行的附属服务。需要配置成 mapreduce_shuffle 后才可以在 Yarn 上运行 MapReduce 程序。-->' C; N; x' K |; p. l D1 X4 F5 ]
<name>yarn.nodemanager.aux-services</name>
' d5 v: d8 V) I0 ?) |( ~% i5 k <value>mapreduce_shuffle</value>8 W1 V# P, p5 `0 L# v8 M
</property>- [; D( i4 s% h' x3 i, x7 Z* q
<property>) L2 S3 j' T; [5 T" Z: W! g5 V( M! H. ]
<!-- 是否启用日志聚合 (可选) -->% x6 K0 n: J) `/ m7 K. c. ?/ E
<name>yarn.log-aggregation-enable</name>
* J+ F9 ?" P4 W$ F$ R0 p" V+ n <value>true</value>
W, `1 [) P& B0 M </property>! E$ @2 G% U- O1 \4 y" {
<property>
" P: h' _* c7 U: t6 s& R1 N <!-- 聚合日志的保存时间 (可选) -->( P0 A5 Q9 H8 ~$ h1 D* J
<name>yarn.log-aggregation.retain-seconds</name>; y5 c4 V' n0 R3 I3 j' y. P
<value>86400</value>& C# f" H5 B6 N/ S( E+ o
</property>* d/ y& h: R. F: L w& H" O
<property>2 r5 {" s* e1 R: |: |1 y& P
<!-- 启用 RM HA -->
6 b4 M8 \( k7 _ <name>yarn.resourcemanager.ha.enabled</name>
9 D& z6 F6 ~% h1 n1 H7 S <value>true</value>
& b$ j. g+ c; z) Z$ W2 }7 ?' Z </property>0 B9 u# o' ^" E7 p( ]; C$ d! ]5 K6 e
<property>
1 w9 h T: O5 T7 [! Z F <!-- RM 集群标识 -->0 l: i; y& Y7 h. f0 W
<name>yarn.resourcemanager.cluster-id</name>9 m' O4 p/ |4 m P' L) Y0 z/ e* f
<value>my-yarn-cluster</value>6 f# a4 L4 v) ^5 B* `
</property>! ^5 u9 f6 @3 h2 U0 h7 I! L% C# Z
<property>( c3 }2 p6 d# I% w. ]
<!-- RM 的逻辑 ID 列表 -->* k- M: m: ?& e5 `" T7 p _9 t( R
<name>yarn.resourcemanager.ha.rm-ids</name>0 t4 H2 s1 n" U4 V- n: a
<value>rm1,rm2</value>
% i. r, }# l B5 L" s6 n. Y </property>2 W3 b9 y _. Z9 d9 Z# z: U5 k
<property>
! q. i% \' v( R4 | <!-- RM1 的服务地址 -->1 |0 \/ q0 o) Z" Z$ C' q! v) g
<name>yarn.resourcemanager.hostname.rm1</name>; a5 s n2 z9 F- t7 W. U
<value>hadoop002</value>9 ~% c. v) c7 I1 c) ]3 b7 n
</property>: q* O) G5 H+ f5 l( Q. e O# f
<property>
9 p2 v5 z# E& k, p <!-- RM2 的服务地址 -->6 g! I: @ D) ~" N% M0 D
<name>yarn.resourcemanager.hostname.rm2</name>
' J" T- z' |! N4 E* ^) A8 T/ S" u <value>hadoop003</value>9 n; A$ U5 H$ v7 Y
</property>
( z- V# b E2 M0 ]# T <property>9 V6 F/ o9 Z9 w4 K) t
<!-- RM1 Web 应用程序的地址 -->4 }9 ~6 Z3 R+ D9 s( N
<name>yarn.resourcemanager.webapp.address.rm1</name>/ b( G- d# m) K% z8 v
<value>hadoop002:8088</value>
) ~6 B& _ b- B8 H3 c" X' } </property>8 Q( V$ B) ^3 {" S9 @8 w6 z- }5 R
<property>% ]3 d$ w7 e% s; x: t* J3 F+ o
<!-- RM2 Web 应用程序的地址 -->) N: B) Q2 d( j( S- X
<name>yarn.resourcemanager.webapp.address.rm2</name>( @# k9 Z W6 }" e+ \4 i1 |5 d
<value>hadoop003:8088</value>" O Q4 m+ |! P0 o
</property>
+ z+ w1 n% o& b% r9 b <property>& t q& b3 [: ^7 O9 A% l
<!-- ZooKeeper 集群的地址 -->; a1 @) Y; x) [6 x
<name>yarn.resourcemanager.zk-address</name>
- D* L5 }5 L l1 b4 ]# q$ x. U) Q# r <value>hadoop001:2181,hadoop002:2181,hadoop003:2181</value>
4 v* ?1 |# f5 t2 Z5 S$ W$ j: y8 O. E </property>
8 \# p& ? s: X* F9 f5 y$ D <property>- e; ^5 n8 x/ h6 E
<!-- 启用自动恢复 -->
3 C0 A3 H$ H( b/ ? <name>yarn.resourcemanager.recovery.enabled</name>
0 H' E4 w8 n o* z4 K- |2 I: [ <value>true</value>
5 H3 U; d3 @' h4 C" f </property>
0 t2 G; u W9 C3 i9 l7 r2 x <property>; v* |' s6 v! E k+ r& w0 s
<!-- 用于进行持久化存储的类 -->( k" c3 F/ r2 g* u4 z5 j
<name>yarn.resourcemanager.store.class</name>1 ^% P& y7 Z* l, L$ T
<value>org.apache.hadoop.yarn.server.resourcemanager.recovery.ZKRMStateStore</value>6 F% q7 L; ?) v. V* h% \
</property>
6 h4 v3 ~8 l& p# Y: X</configuration>) O2 Z* q! e) z# L
5. mapred-site.xml
p u9 L. _: h<configuration>6 h& X! }- }1 n* r8 |8 t$ I0 ~
<property>+ T- H$ Z/ w" J7 _' i. Y( e/ b
<!--指定 mapreduce 作业运行在 yarn 上-->3 _6 t1 g) i) K" K7 q2 G
<name>mapreduce.framework.name</name>$ l& M1 U, ]# U! d9 I
<value>yarn</value>* D9 \. G2 }6 B; J9 A A0 S
</property>
9 \1 U L; s* L- j2 D</configuration>) E( [# _5 x* g4 T
5. slaves
6 `: I& G. {8 D* @( e2 a; S: h配置所有从属节点的主机名或 IP 地址,每行一个。所有从属节点上的 DataNode 服务和 NodeManager 服务都会被启动。3 Z7 e! P4 `; y
4 ?6 f; t" ~+ ~, v8 g' Z8 v
hadoop001
2 w) L# q/ ]! Mhadoop0024 A3 `5 i$ K% z! {
hadoop003; M1 x2 `' K, f% ? }: c
4.4 分发程序
) E' I9 H2 A" m: E) {6 E$ Z2 e将 Hadoop 安装包分发到其他两台服务器,分发后建议在这两台服务器上也配置一下 Hadoop 的环境变量。
8 b% M, m' j" {( x Q5 R. n
1 K6 N: p# [; e4 r# U: _ @8 p9 x# 将安装包分发到hadoop002
( s: a4 e( X% Y& jscp -r /usr/app/hadoop-2.6.0-cdh5.15.2/ hadoop002:/usr/app/
4 E: U7 t2 {8 ^- S. D& ^# 将安装包分发到hadoop003% q. s) b L! ?* f$ ?- r6 O/ S
scp -r /usr/app/hadoop-2.6.0-cdh5.15.2/ hadoop003:/usr/app/
. ]. ]( U4 n7 i7 Z; M% T* T" ]五、启动集群
, u8 u5 V0 \* Z1 `8 d% F1 l7 L5.1 启动ZooKeeper
0 `( n- I+ Z% A4 D" ?$ R分别到三台服务器上启动 ZooKeeper 服务:/ A" N1 W9 \, v8 b% ]6 G a- Y
/ d0 c) T, E/ n8 W6 h0 J zkServer.sh start A6 @: d3 S4 Y: q& z( U
5.2 启动Journalnode
. R2 f1 r) K9 z% G分别到三台服务器的的 ${HADOOP_HOME}/sbin 目录下,启动 journalnode 进程:
7 R0 @% |" S. T* _) e! T: ?3 I7 H6 Z- h6 e; d
hadoop-daemon.sh start journalnode$ q. i- n/ W: }- `1 r0 s; h
5.3 初始化NameNode
4 P7 N, L- o+ G; g1 E在 hadop001 上执行 NameNode 初始化命令:
5 T/ R' N$ P% u7 t" L6 [
2 J) w" t) _* c& S7 a, D/ thdfs namenode -format9 e8 J% Y5 h, g" P h3 L5 J# m
执行初始化命令后,需要将 NameNode 元数据目录的内容,复制到其他未格式化的 NameNode 上。元数据存储目录就是我们在 hdfs-site.xml 中使用 dfs.namenode.name.dir 属性指定的目录。这里我们需要将其复制到 hadoop002 上:
' K) K3 o4 x: i, X' Q8 W
; _+ w4 P2 V* C$ S( O scp -r /home/hadoop/namenode/data hadoop002:/home/hadoop/namenode/
! C: m3 h, p% }' |4 @" J( G. M5.4 初始化HA状态, D4 N7 P2 X" Y: j& i7 c
在任意一台 NameNode 上使用以下命令来初始化 ZooKeeper 中的 HA 状态:4 e3 c: |* ~) p( K3 H# N
; c7 Y$ L/ L) Z7 a+ v* s3 Jhdfs zkfc -formatZK
. s# r" j# A% L5.5 启动HDFS
( O& D4 P- g" P2 g' R: V进入到 hadoop001 的 ${HADOOP_HOME}/sbin 目录下,启动 HDFS。此时 hadoop001 和 hadoop002 上的 NameNode 服务,和三台服务器上的 DataNode 服务都会被启动:, }7 B! \( c. j) ?6 p8 y
7 _% W# y& r& [+ V, w' Cstart-dfs.sh/ }- |3 `% Z! G* W
5.6 启动YARN
3 |/ p1 V8 b" l" f* F# ~. S( [进入到 hadoop002 的 ${HADOOP_HOME}/sbin 目录下,启动 YARN。此时 hadoop002 上的 ResourceManager 服务,和三台服务器上的 NodeManager 服务都会被启动:
* k% W" r4 }0 s6 p- y7 ~& L' M5 [. D
start-yarn.sh
) s; r7 a7 q8 ]4 K# w, W. b需要注意的是,这个时候 hadoop003 上的 ResourceManager 服务通常是没有启动的,需要手动启动:
) Y+ m K& z- {9 c* e- U
8 N- ]% T8 v4 syarn-daemon.sh start resourcemanager
! a4 ~* ~; y9 M- H/ u- Z六、查看集群
0 I! [9 R9 u' H: w! D1 L' o# N9 m6.1 查看进程4 ~( h5 M) c) i3 Q0 [( q+ d
成功启动后,每台服务器上的进程应该如下:9 V) s& Y; c6 S) y
! p8 g0 V! u5 Y- |# l[root@hadoop001 sbin]# jps
: {4 Q$ P. j$ E4512 DFSZKFailoverController4 R2 {6 }4 r; f# S/ W/ x; Z2 L; \
3714 JournalNode1 S- @1 o# h Y8 b, Z" }2 d
4114 NameNode6 |) ?- v7 z& S8 ~
3668 QuorumPeerMain
% x. t# ?8 }% W, D: @# n6 p+ B. t0 g5012 DataNode$ B+ N- [ ]; j- g0 D
4639 NodeManager
4 Z: R5 E7 r/ Q) I i2 q6 L- M
[3 V0 K/ W% W1 M% m- C. c# j( W- ^+ [' s
[root@hadoop002 sbin]# jps
9 @$ O* a; k: J# K& ?1 q4499 ResourceManager4 L9 G I' ]) h6 X
4595 NodeManager
% c5 W' f0 z6 w! j! v' D/ j4 u3465 QuorumPeerMain* z$ z0 R# a% L5 ~8 T8 x
3705 NameNode
* K) j- s1 b( g* X1 }2 I3915 DFSZKFailoverController
0 L1 Q1 J' U! n' U6 w+ h! C3 q5211 DataNode
; h- x! t6 R8 [3533 JournalNode% y2 R9 A3 q8 e' j9 P
F3 G5 t+ Y2 s0 |8 a3 f
: S3 ^7 O6 |4 e) ]/ T& Y[root@hadoop003 sbin]# jps- Y i- _" _* e- L% _0 A O% i
3491 JournalNode
0 a! K0 |0 n# m3942 NodeManager
/ D$ L @; X! q9 s. Y) i* c; _# h4102 ResourceManager
+ ~% H9 S6 e8 i# O1 }9 y4201 DataNode
4 b4 T5 k3 D4 r' A. \! `3435 QuorumPeerMain( y' _8 U7 ~% P
6.2 查看Web UI
+ R# k5 g& x! L3 P2 Y, rHDFS 和 YARN 的端口号分别为 50070 和 8080,界面应该如下:! F2 q6 J% L4 ]) s9 d
$ ^% Z/ z q) x1 X此时 hadoop001 上的 NameNode 处于可用状态:
& }: @+ `* N* Y ?8 c- W) T6 o/ o& f
8 G% Q) M8 T+ s! ?7 Y0 l) G
- ]% v. `) D, n; n K" d; O! j& @" Y而 hadoop002 上的 `NameNode` 则处于备用状态:
( p$ o& f+ x- n/ j. m9 e6 }$ `' ]! t' O
2 y& x0 |4 h; G) P) S+ k
hadoop002 上的 ResourceManager 处于可用状态:0 v, X% o Y3 o) L8 J, ]' s
# o8 A+ V/ x5 O" ?5 P
9 l- ]% {+ w& F. I9 a3 x) z
5 n6 ^" j Y5 {0 |3 P2 q* K% v S/ G
hadoop003 上的 ResourceManager 则处于备用状态:1 Q0 ] R _$ P+ F* e' S' V3 ^
1 T/ x- K' d( ~2 `9 k" o0 `
U" f5 k+ ^( p7 N: g4 |
+ T& F* K3 G" Y4 O: B2 \9 L# q6 h# r
同时界面上也有 Journal Manager 的相关信息:
6 `, N7 D0 o% P8 t, C) i7 y/ g- y, c- _2 l
6 b4 O) W& Q" w2 I
8 R5 W K" N3 V o## 七、集群的二次启动0 D' @. p6 V9 _+ Z9 V: T
上面的集群初次启动涉及到一些必要初始化操作,所以过程略显繁琐。但是集群一旦搭建好后,想要再次启用它是比较方便的,步骤如下(首选需要确保 ZooKeeper 集群已经启动):
8 @" M' b0 }/ }% Q" W9 g( P& _$ D' |8 A
在 hadoop001 启动 HDFS,此时会启动所有与 HDFS 高可用相关的服务,包括 NameNode,DataNode 和 JournalNode:
6 i* ]; y! x! a6 R& B ^ c. v3 M) D
start-dfs.sh
9 T& U' [! I: q5 Z. m# B& ^在 hadoop002 启动 YARN:$ q7 ]; N% F$ b) h1 U: q
# H4 W! h7 T3 {/ N8 a& C
start-yarn.sh; p3 p( Y. ~2 d: d, W
这个时候 hadoop003 上的 ResourceManager 服务通常还是没有启动的,需要手动启动:
: a. l" I5 a3 I' }% H$ o# D0 i' j- Y2 U
yarn-daemon.sh start resourcemanager' N1 D' y/ Y; U5 H2 w0 |! Y- e3 z6 S
3 }2 n* b/ c6 V% s# _$ P( D7 G$ N
|
|