大数据集群运维:调优、排错与 CDH 接入

环境信息

使用的 hadoop 完全分布式集群

1
2
3
192.168.2.241 hadoop01
192.168.2.242 hadoop02
192.168.2.243 hadoop03

Yarn 资源调度

Yarn 中有三种资源调度器可供选择

  1. FIFO Scheduler : 按照时间先后顺序进行服务, 一般不用。 hadoop1.x 默认使用
  2. Capacity Scheduler : 容量调度器, 多用户,多队列。 hadoop2.x, hadoop3.x, 默认使用
  3. Fair Scheduler : 公平调度器, 支持多用户、多分组管理.

Capacity Scheduler

容量资源调度器,支持多队列,但默认情况下只有 root.default 这一个队列

让任务运行在指定的队列

  1. 直接指定队列名
  2. 通过用户名、用户组和队列名进行对应

Fair Scheduler

Fair Scheduler 将整个 Yarn 的可用资源划分成多个队列资源池,每个队列中可以配置最小和最大的可用资源(内存和 CPU)、最大可同时运行 Application 数量、权重,以及可以提交和管理 Application 的用户等。

启用 Fair Scheduler

/etc/hadoop/conf/yarn-site.xml 添加

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
<!-- 设置为公平调度  -->
<property>
<name>yarn.resourcemanager.scheduler.class</name>
<value>org.apache.hadoop.yarn.server.resourcemanager.scheduler.fair.FairScheduler</value>
</property>

<!-- 公平调度配置路径 -->
<property>
<name>yarn.scheduler.fair.allocation.file</name>
<value>/etc/hadoop/conf/fair-scheduler.xml</value>
</property>

<!-- 未指定队列名时,将以用户名作为队列名。
注意:下面 fair-scheduler.xml 里一旦写了 <queuePlacementPolicy>,这个属性就被忽略,
实际生效的是那组 rule。 -->
<property>
<name>yarn.scheduler.fair.user-as-default-queue</name>
<value>true</value>
<description>default is True</description>
</property>

<!-- 开启抢占模式 允许调度器杀掉占用超过其应占资源份额队列的 containers -->
<property>
<name>yarn.scheduler.fair.preemption</name>
<value>true</value>
</property>

/etc/hadoop/conf/fair-scheduler.xml

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
<?xml version="1.0"?>
<allocations>
<!-- users max running apps -->
<userMaxAppsDefault>10</userMaxAppsDefault>
<queue name="root">
<aclSubmitApps> </aclSubmitApps>
<aclAdministerApps> </aclAdministerApps>
<queue name="default">
<minResources>12000mb,5vcores</minResources>
<maxResources>100000mb,50vcores</maxResources>
<maxRunningApps>22</maxRunningApps>
<schedulingMode>fair</schedulingMode>
<weight>1</weight>
<aclSubmitApps>*</aclSubmitApps>
</queue>

<queue name="dev_group">
<minResources>115000mb,50vcores</minResources>
<maxResources>500000mb,150vcores</maxResources>
<maxRunningApps>181</maxRunningApps>
<schedulingMode>fair</schedulingMode>
<weight>5</weight>
<aclSubmitApps> dev_group</aclSubmitApps>
<aclAdministerApps>hadoop dev_group</aclAdministerApps>
</queue>


<queue name="test_group">
<minResources>23000mb,10vcores</minResources>
<maxResources>300000mb,100vcores</maxResources>
<maxRunningApps>22</maxRunningApps>
<schedulingMode>fair</schedulingMode>
<weight>4</weight>
<aclSubmitApps> test_group</aclSubmitApps>
<aclAdministerApps>hadoop test_group</aclAdministerApps>
</queue>

</queue>
<!-- 注意 create="false" 的含义是"仅当同名队列已经存在时才用用户名队列",
而不是"按用户名建队列"。要自动建队列得写 create="true"。 -->
<queuePlacementPolicy>
<rule name="user" create="false" />
<rule name="primaryGroup" create="false" />
<rule name="secondaryGroupExistingQueue" create="false" />
<rule name="default" queue="default" />
</queuePlacementPolicy>

<fairSharePreemptionTimeout>60</fairSharePreemptionTimeout>
<defaultFairSharePreemptionTimeout>60</defaultFairSharePreemptionTimeout>
</allocations>

容量调度器与公平调度器的区别

容量调度器的调度策略是,先选择资源利用率低的队列,然后在队列中同时考虑 FIFO 和内存因素;而公平调度器仅考虑公平,而公平是通过任务缺额体现的,调度器每次选择缺额最大的任务(队列的资源量,任务的优先级等仅用于计算任务缺额)

HDFS 存储权限

刚开始

1
2
3
4
5
6
7
8
9
10
[hadoop@hadoop01 sbin]$ hadoop fs -ls /demo
Found 1 items
-rw-r--r-- 2 hadoop supergroup 105 2022-05-16 23:36 /demo/demo.txt
[hadoop@hadoop01 sbin]$ hadoop fs -getfacl /demo/demo.txt
# file: /demo/demo.txt
# owner: hadoop
# group: supergroup
user::rw-
group::r--
other::r--

修改 /etc/hadoop/conf/hdfs-site.xml

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
<property>
<name>fs.permissions.umask-mode</name>
<value>026</value>
</property>


<!-- 开启 HDFS 的权限控制机制 -->
<property>
<name>dfs.permissions.enabled</name>
<value>true</value>
</property>
<!-- 开启 ACL 精细化控制 -->
<property>
<name>dfs.namenode.acls.enabled</name>
<value>true</value>
</property>

修改完后 重启 dfs

默认情况下新文件的权限默认是 666 与 umask 的交集,新目录的权限是 777 与 umask 的交集,如果 umask 为 026,那么新文件的权限就是 640,新目录的权限就是 751

测试

1
2
3
4
5
6
7
8
9
[hadoop@hadoop01 sbin]$ hadoop fs -put /tmp/demo_acl_test.txt /demo
[hadoop@hadoop01 sbin]$ hadoop fs -ls /demo
Found 2 items
-rw-r--r-- 2 hadoop supergroup 105 2022-05-16 23:36 /demo/demo.txt
-rw-r----- 2 hadoop supergroup 105 2022-05-25 04:20 /demo/demo_acl_test.txt
[hadoop@hadoop01 sbin]$ hadoop fs -mkdir /acl_test
[hadoop@hadoop01 sbin]$ hadoop fs -ls /
Found 10 items
drwxr-x--x - hadoop supergroup 0 2022-05-25 04:22 /acl_test

通过 ACL 机制,可以实现 HDFS 文件系统更精细化的权限控制

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
[hadoop@hadoop01 sbin]$ hdfs dfs -setfacl -m user:hive:rw- /demo/demo.txt
[hadoop@hadoop01 sbin]$ hadoop fs -getfacl /demo/demo_acl_test.txt
# file: /demo/demo_acl_test.txt
# owner: hadoop
# group: supergroup
user::rw-
group::r--
other::---

[hadoop@hadoop01 sbin]$ hadoop fs -getfacl /demo/demo.txt
# file: /demo/demo.txt
# owner: hadoop
# group: supergroup
user::rw-
user:hive:rw-
group::r--
mask::rw-
other::r--

权限相关的两个参数性质完全不同

顺带说清一个容易误配的地方:fs.permissions.umask-modedfs.permissions.enabled 虽然都带”权限”,但一个是客户端行为、一个是服务端强制,作用完全不同。

fs.permissions.umask-mode(默认 022)决定的是新建文件/目录时由客户端算出的初始权限。它写在客户端的配置里、由客户端计算后随请求发给 NameNode——所以:

  • 重启 NameNode 并不是它生效的前提,改客户端配置即时生效;
  • 一个自带配置文件的远端客户端(比如别人机器上的 hadoop fs、或者程序里 conf.set())可以直接绕过你在集群侧设的 umask;
  • 想统一,只能靠分发一致的客户端配置,或者干脆不依赖它,改用目录上的 default ACL 来兜底。

dfs.permissions.enabled 才是服务端的开关:关掉之后 NameNode 完全不做权限检查(属主、rwx 位、ACL 全部无效),任何人都能删任何目录。它常在测试环境被顺手关掉,然后忘了打开——这属于严重的安全配置错误,因为 HDFS 的用户身份本来就只是一个字符串(不开 Kerberos 时随便就能伪装),权限检查是唯一那道门。

ACL 那边有两个显示细节值得知道:

1
2
3
4
5
6
7
8
9
$ hdfs dfs -setfacl -m user:alice:rwx /data
$ hdfs dfs -ls /data
drwxrwx---+ - hadoop supergroup ... # 注意末尾多出来的 + 号,表示这个路径有扩展 ACL
$ hdfs dfs -getfacl /data
user::rwx
user:alice:rwx # effective:rwx
group::r-x
mask::rwx # ← 这一行是关键
other::---

mask 是所有命名用户和组条目的权限上限:某个条目的实际生效权限等于它自己的权限与 mask 求交集。所以 chmod 一个带 ACL 的目录时,改动的其实是 mask 而不是 group::——这就解释了一个常见现象:明明给 alice 授了 rwxgetfacl 里却显示 effective:r-x,原因是有人 chmod 750 把 mask 压下去了。

内存与 CPU 调优

Yarn 的内存和 CPU 调优

在 Yarn 集群中,平衡内存、CPU、磁盘这三者的资源分配是很重要的,最基本的经验就是: 每两个 Container 使用一块磁盘、一个 CPU 核,这种配置,可以使集群的资源得到一个比较好的平衡利用

Yarn 的内存优化主要涉及 ResourceManager、NodeManager 相关进程以及 Yarn 的一些配置参数

  1. ResourceManager: 通常建议将 ResourceManager 独立运行在一台服务器上,所以只考虑操作系统对内存的占用即可
    比如 8G 内存的服务器,单独部署 ResourceManager

/etc/hadoop/conf/yarn-env.sh

1
2
3
4
# 8GB 内存的机器不要把堆开成 8192:那是物理内存的 100%,
# 元空间、线程栈、堆外和操作系统全都没有余量,实际会 swap 或者直接起不来。留 4~5GB 给堆。
export YARN_RESOURCEMANAGER_HEAPSIZE=4096
export YARN_RESOURCEMANAGER_OPTS="-server -Xms${YARN_RESOURCEMANAGER_HEAPSIZE}m -Xmx${YARN_RESOURCEMANAGER_HEAPSIZE}m"
  1. NodeManager 充当 shuffle 任务的 server 端时,内存应该调大
    /etc/hadoop/conf/yarn-env.sh
1
2
export YARN_NODEMANAGER_HEAPSIZE=4096
export YARN_NODEMANAGER_OPTS="-Xms${YARN_NODEMANAGER_HEAPSIZE}m -Xmx${YARN_NODEMANAGER_HEAPSIZE}m"
  1. 参数优化
    /etc/hadoop/conf/yarn-site.xml
    /etc/hadoop/conf/mapred-site.xml

需要根据任务内存,cpu 等进行综合考虑

RM 的内存资源配置
NM 的内存资源配置
AM 内存配置相关参数

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
RM1:yarn.scheduler.minimum-allocation-mb,表示单个容器可以申请的最小内存,默认 1024MB。

RM2:yarn.scheduler.maximum-allocation-mb,表示单个容器可以申请的最大内存,默认 8192MB。

APP1:yarn.app.mapreduce.am.resource.mb,MR 运行于 Yarn 上时,为 AM 分配多少内存。

APP2:yarn.app.mapreduce.am.command-opts,运行 MRAppMaster 时的 jvm 参数,可设置 -Xmx、-Xms 等选项。

NM 的内存资源配置

NM1:yarn.nodemanager.resource.memory-mb,表示节点可用的最大内存。

NM2:yarn.nodemanager.vmem-pmem-ratio,表示虚拟内存率,默认 2.1。

map / reduce 任务容器的内存配置相关参数
(真正的 ApplicationMaster 内存是上面的 APP1 / APP2,别和这一组搞混)

AM1:mapreduce.map.memory.mb,分配给 map Container 的内存大小。

AM2:mapreduce.map.java.opts,运行 map 任务的 jvm 参数,可设置 -Xmx、-Xms 等选项。

AM3:mapreduce.reduce.memory.mb,分配给 reduce Container 的内存大小。

AM4:mapreduce.reduce.java.opts,运行 reduce 任务的 jvm 参数,可设置 -Xmx、-Xms 等选项。

需要注意

RM1、RM2 的值均不能大于 NM1 的值

AM1 和 AM3 的值应该在 RM1 和 RM2 这两个值之间

AM3 的值最好为 AM1 的两倍

AM2 要配合 AM1、AM4 要配合 AM3,各自成对,java.opts 和另一边的容器大小之间没有任何约束关系:
-Xmx 取所属容器的 8 折左右(AM2 ≈ AM1 × 0.8,AM4 ≈ AM3 × 0.8),余下的留给线程栈、元空间和 native 内存。

千万别按"AM2 落在 AM1 和 AM3 之间"来配:假如 map 容器 1024、reduce 容器 2048,
照那个说法把 map 的 -Xmx 设成 1800m,堆就超过了 map 容器的上限,
NodeManager 会以 running beyond physical memory limits 把它杀掉。
  1. cpu 优化
1
2
3
4
5
yarn.nodemanager.resource.cpu-vcores 表示该节点服务器上 Yarn 可使用的虚拟 CPU 个数,默认为 8。由于需要给操作系统、datanode、nodemanager 进程预留一定量的 CPU,所以一般将系统 CPU 的 90% 留给此参数即可,例如集群节点有 32 个 core,那么分配 28 个 core 给 yarn。

yarn.scheduler.minimum-allocation-vcores 表示单个任务可申请的最小虚拟核数,默认为 1。

yarn.scheduler.maximum-allocation-vcores 表示单个任务可申请的最大虚拟核数,默认为 4。

HDFS 的内存和 CPU 调优

HDFS 性能参数配置

1
2
3
4
5
dfs.replication  副本数,一般设置为 3
dfs.block.size 数据块大小,一般为 128 或 128 的整数,据块设置太小,会增加 NameNode 的压力;数据块设置过大,会增加定位数据的时间
dfs.datanode.data.dir HDFS 数据块的存储路径,最好为独立磁盘的路径

dfs.datanode.max.transfer.threads datanode 可 同时处理的最大文件数量 ,建议将这个值尽量调大,最大值可以配置为 65535

HDFS 内存资源调优

主要是配置 Namenode 的堆内存。Namenode 堆内存配置过小,会导致频繁产生 Full GC,进而导致 namenode 宕机;而 namenode 只处理元数据——客户端从它那里拿到块位置之后,数据流是直连 DataNode 的,不经过 namenode。所以它的堆需求由命名空间对象的数量决定(文件数加块数,经验值大约每百万个块 1GB),跟读写的数据量没有关系。一般将 Namenode 放在单独的服务器上

NameNode 的堆按命名空间规模估,专用机上给到物理内存的一半左右是常见做法。
注意 HADOOP_HEAPSIZE_MAX所有 Hadoop 守护进程和客户端命令的默认堆,不是 NameNode 专属,
要单独配 NameNode 应该用 HDFS_NAMENODE_OPTS
/etc/hadoop/conf/hadoop-env.sh

1
export HDFS_NAMENODE_OPTS="-Xms30g -Xmx30g -XX:+UseG1GC"

DataNode 是另一回事:它不持有命名空间,堆常态 4~8GB 就够,
剩下的物理内存要留给 page cache(读性能靠它),不要照 NameNode 那样往上堆。
/etc/hadoop/conf/hadoop-env.sh

1
2
export HDFS_DATANODE_HEAPSIZE=4096
export HDFS_DATANODE_OPTS="-Xms${HDFS_DATANODE_HEAPSIZE}m -Xmx${HDFS_DATANODE_HEAPSIZE}m"

Kafka 性能调优

Kafka 是一个高吞吐量分布式消息系统,并且提供了持久化存储功能,其高性能有两个重要特征:

  1. 磁盘连续读写性能远远高于随机读写的特点
  2. 通过将一个 topic 拆分多个 partition,可提供并发和吞吐量

内存调优,修改 系统文件

1
2
vm.dirty_background_ratio /proc/sys/vm/dirty_background_ratio  5%
vm.dirty_ratio /proc/sys/vm/dirty_ratio 10%

/opt/bigdata/kafka/current/config/server.properties

topic 的拆分

将不同的 partition 分布在不同在磁盘上,可以将磁盘的多个目录配置到 broker 的 log.dirs

1
log.dirs=/disk1/logs,/disk2/logs,/disk3/logs

配置参数优化

1
2
3
4
5
6
7
8
9
log.retention.hours=72
log.segment.bytes=1073741824

# 这两项默认是不启用的,一般也别开:
# interval.messages 是单个 partition 累积的消息数(不是 producer 写入的总条数);
# 而主动 fsync(尤其 1 秒一次)正好抵消掉上面说的 page cache 批量顺序写的收益。
# Kafka 官方的建议是交给操作系统刷盘,持久性靠副本(replication.factor + min.insync.replicas)来保证。
#log.flush.interval.messages=10000
#log.flush.interval.ms=1000

日志保留3 天,段文件 1G,每当 producer 写入 10000 条消息或 1s 刷数据到磁盘

常见问题排查

下线一个 datanode 节点

/etc/hadoop/conf/hdfs-site.xml 添加

1
2
3
4
5

<property>
<name>dfs.hosts.exclude</name>
<value>/etc/hadoop/conf/hosts-exclude</value>
</property>

/etc/hadoop/conf/hosts-exclude 添加待下线的节点

1
hadoop03

刷新hadoop 配置

1
hdfs dfsadmin -refreshNodes

查看退役进度

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
[hadoop@hadoop01 ~]$ hdfs dfsadmin -report
Configured Capacity: 72955723776 (67.95 GB)
Present Capacity: 33702436598 (31.39 GB)
DFS Remaining: 32456507392 (30.23 GB)
DFS Used: 1245929206 (1.16 GB)
DFS Used%: 3.70%
Replicated Blocks:
Under replicated blocks: 412
Blocks with corrupt replicas: 0
Missing blocks: 0
Missing blocks (with replication factor 1): 0
Low redundancy blocks with highest priority to recover: 412
Pending deletion blocks: 0
Erasure Coded Block Groups:
Low redundancy block groups: 0
Block groups with corrupt internal blocks: 0
Missing block groups: 0
Low redundancy blocks with highest priority to recover: 0
Pending deletion blocks: 0

-------------------------------------------------
Live datanodes (2):

Name: 192.168.2.241:9866 (hadoop01)
Hostname: hadoop01
Decommission Status : Normal
Configured Capacity: 36477861888 (33.97 GB)
DFS Used: 657819584 (627.35 MB)
Non DFS Used: 22519461952 (20.97 GB)
DFS Remaining: 13300580352 (12.39 GB)
DFS Used%: 1.80%
DFS Remaining%: 36.46%
Configured Cache Capacity: 0 (0 B)
Cache Used: 0 (0 B)
Cache Remaining: 0 (0 B)
Cache Used%: 100.00%
Cache Remaining%: 0.00%
Xceivers: 0
Last contact: Wed May 25 05:03:23 EDT 2022
Last Block Report: Wed May 25 04:20:17 EDT 2022
Num of Blocks: 871


Name: 192.168.2.242:9866 (hadoop02)
Hostname: hadoop02
Decommission Status : Normal
Configured Capacity: 36477861888 (33.97 GB)
DFS Used: 588109622 (560.87 MB)
Non DFS Used: 16733825226 (15.58 GB)
DFS Remaining: 19155927040 (17.84 GB)
DFS Used%: 1.61%
DFS Remaining%: 52.51%
Configured Cache Capacity: 0 (0 B)
Cache Used: 0 (0 B)
Cache Remaining: 0 (0 B)
Cache Used%: 100.00%
Cache Remaining%: 0.00%
Xceivers: 0
Last contact: Wed May 25 05:03:23 EDT 2022
Last Block Report: Wed May 25 04:20:17 EDT 2022
Num of Blocks: 599

这份输出说明退役其实还没完成:判据是待下线节点的 Decommission Status : Decommissioned 并且 under-replicated 归零,
而这里 Under replicated blocks: 412Live datanodes (2) 里两台的状态都还是 Normal

更要紧的是,3 个 DataNode、副本因子 3 的集群,排掉一台之后只剩 2 台,永远凑不出 3 份副本,
这个 decommission 不会结束。三节点想退役一台,得先把相关文件的副本数降到 ≤2(hdfs dfs -setrep 2 -R /path),
或者先加一个节点进来。

退役要满足的前置条件

上面那个”永远跑不完”的现场,正好可以把退役这件事的几个前置条件说全。

判据:什么叫退役完成。 两个条件同时满足——hdfs dfsadmin -report 里该节点显示 Decommission Status : Decommissioned(不是 Decommission in progress),并且 Under replicated blocks 归零。只看节点从列表里消失是不够的。

硬约束:副本数不能大于剩余节点数。 退役的本质是”把这个节点上的块在别处补够副本数,然后才允许它下线”。所以剩余可用节点数必须 ≥ 副本因子,否则永远补不齐、永远卡在 in progress。三节点集群退一台,就必须先把相关文件降到 2 副本:

1
hdfs dfs -setrep -w 2 -R /path       # -w 会等到实际达标才返回

速度:补副本有限流。 退役慢通常不是网络或磁盘的问题,而是被参数卡着。相关的两个是 NameNode 侧的:

1
2
3
4
<!-- 每个 DataNode 同时参与的复制流数量上限,默认 2,退役时可临时调大 -->
<property><name>dfs.namenode.replication.max-streams</name><value>20</value></property>
<!-- 硬上限,含最高优先级的恢复任务,默认 4 -->
<property><name>dfs.namenode.replication.max-streams-hard-limit</name><value>40</value></property>

改完 hdfs dfsadmin -refreshNodes 不会重读这两项(它们不在可动态刷新的列表里),需要重启 NameNode;急用的话可以先用 dfs.namenode.replication.work.multiplier.per.iteration 配合调度频率来提速。退役完记得调回去,否则日常的副本恢复会抢走过多带宽。

include 与 exclude 的判定优先级。 这一点是上面”上线”流程容易出错的根源:HDFS 先看 exclude,在 exclude 名单里就排除,跟它有没有出现在 include 里无关。两个文件都写着某节点时,它仍然按 decommission 处理。所以复役必须从 exclude 里删掉,只往 include 里加是没用的。

dfs.hosts(include) dfs.hosts.exclude 结果
正常服务
退役中/已退役
退役中/已退役
启用了 include 名单时被拒绝注册;未启用时正常服务

上线, 修改配置

1
2
3
4
<property>
<name>dfs.hosts</name>
<value>/etc/hadoop/conf/hosts</value>
</property>

写入 /etc/hadoop/conf/hosts

1
2
3
hadoop01
hadoop02
hadoop03

还要把 hadoop03 从 /etc/hadoop/conf/hosts-exclude删掉。HDFS 的判定是”在 exclude 名单里就排除”,
跟它有没有出现在 include 名单里无关;两个文件都写着的话仍然按 decommission 处理,节点不会真正复役。

另外注意:一旦启用了 dfs.hosts 白名单,任何不在这份文件里的 DataNode 都会被拒绝注册,加节点时别忘了同步它。

刷新hadoop 配置

1
hdfs dfsadmin -refreshNodes

hadoop03 手动启动 datanode

1
hdfs --daemon start datanode

某个 datanode 节点磁盘坏掉

  1. 在故障节点上查看 /etc/hadoop/conf/hdfs-site.xml 文件中对应的 dfs.datanode.data.dir 参数设置,去掉故障磁盘对应的目录挂载点;

  2. 在故障节点上查看 /etc/hadoop/conf/yarn-site.xml 文件中对应的 yarn.nodemanager.local-dirs 参数设置,去掉故障磁盘对应的目录挂载点;

  3. 重启该节点的 DataNode 服务和 NodeManager 服务即可。

Hadoop 进入安全模式

  1. Hadoop 的启动和验证都正常,那么只需等待一会儿,Hadoop 便将自动结束安全模式——前提是已上报的块达到了 dfs.namenode.safemode.threshold-pct(默认 0.999)并且过完 extension 时间。

先看差多少,再决定要不要动手:

1
2
hdfs dfsadmin -safemode get     # 当前状态
hdfs fsck / # 到底是缺块,还是 DataNode 没起全

确认只是在等上报,才用下面这条。它是强制跳过阈值检查,不是”等待的快捷方式”——
如果卡住的真实原因是 DataNode 没起全或者真有缺块,强制退出会让集群带着缺失块对外提供服务:

1
hdfs dfsadmin -safemode leave

krb 调试

KRB5_TRACE=/dev/stdout

正常返回

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
[root@test-152 keytabs]#  KRB5_TRACE=/dev/stdout kinit -kt test.keytab test
[3737241] 1731657026.743873: Getting initial credentials for [email protected]
[3737241] 1731657026.743874: Looked up etypes in keytab: aes256-cts, aes128-cts
[3737241] 1731657026.743876: Sending unauthenticated request
[3737241] 1731657026.743877: Sending request (175 bytes) to example.COM
[3737241] 1731657026.743878: Resolving hostname test-152
[3737241] 1731657026.743879: Sending initial UDP request to dgram 172.20.1.152:88
[3737241] 1731657026.743880: Received answer (692 bytes) from dgram 172.20.1.152:88
[3737241] 1731657026.743881: Sending DNS URI query for _kerberos.example.COM.
[3737241] 1731657026.743882: No URI records found
[3737241] 1731657026.743883: Sending DNS SRV query for _kerberos-master._udp.example.COM.
[3737241] 1731657026.743884: Sending DNS SRV query for _kerberos-master._tcp.example.COM.
[3737241] 1731657026.743885: No SRV records found
[3737241] 1731657026.743886: Response was not from master KDC
[3737241] 1731657026.743887: Processing preauth types: PA-ETYPE-INFO2 (19)
[3737241] 1731657026.743888: Selected etype info: etype aes256-cts, salt "example.COMtest", params ""
[3737241] 1731657026.743889: Produced preauth for next request: (empty)
[3737241] 1731657026.743890: Getting AS key, salt "example.COMtest", params ""
[3737241] 1731657026.743891: Retrieving [email protected] from FILE:test.keytab (vno 0, enctype aes256-cts) with result: 0/Success
[3737241] 1731657026.743892: AS key obtained from gak_fct: aes256-cts/C03C
[3737241] 1731657026.743893: Decrypted AS reply; session key is: aes256-cts/0610
[3737241] 1731657026.743894: FAST negotiation: available
[3737241] 1731657026.743895: Initializing FILE:/tmp/krb5cc_0 with default princ [email protected]
[3737241] 1731657026.743896: Storing [email protected] -> krbtgt/[email protected] in FILE:/tmp/krb5cc_0
[3737241] 1731657026.743897: Storing config in FILE:/tmp/krb5cc_0 for krbtgt/[email protected]: fast_avail: yes
[3737241] 1731657026.743898: Storing [email protected] -> krb5_ccache_conf_data/fast_avail/krbtgt\/example.COM\@example.COM@X-CACHECONF: in FILE:/tmp/krb5cc_0

[root@test-152 keytabs]# KRB5_TRACE=/dev/stdout klist
Ticket cache: FILE:/tmp/krb5cc_0
Default principal: [email protected]

Valid starting Expires Service principal
11/15/2024 15:50:26 11/16/2024 15:50:26 krbtgt/[email protected]
[root@test-152 keytabs]# KRB5_TRACE=/dev/stdout kdestroy
[3737246] 1731657059.396333: Destroying ccache FILE:/tmp/krb5cc_0
[root@test-152 keytabs]#

yarn 日志查看

1
2
3
4
5
6
7
8
yarn application -list # yarn app -list
yarn app -list -appStates ALL # yarn application -list -appStates FINISHED,FAILED,KILLED
yarn application -status <application_id>
yarn logs -applicationId <application_id>
yarn logs -applicationId <application_id> -containerId <container_id> > container_logs.txt


yarn queue -status default

CDH 客户端接入

CDH 安装在另外的服务器,可以从 CDH 管理界面下载配置文件

导入到本地服务器

下载 CDH-5.9.1-1.cdh5.9.1.p0.4-el7.parcel

1
2
3
4
5
6
7
8
mkdir -p /opt/cloudera/parcels
cd /opt/cloudera/parcels
# 上传刚才的的parcel包至/opt/cloudera/parcels目录

tar -zxvf CDH-5.9.1-1.cdh5.9.1.p0.4-el7.parcel
# 解包出来的目录名不带 -el7.parcel 后缀,软链要指向那个目录,
# 指向 parcel 包文件本身的话后面 CDH/lib/hive、CDH/bin 全都会 ENOTDIR
ln -s CDH-5.9.1-1.cdh5.9.1.p0.4 CDH

下载 hive-clientconfig.zip 和 hbase-clientconfig.zip 、hdfs-clientconfig.zip并解压到 /opt/cloudera/etc/

1
2
3
4
5
[root@k8s01 parcels]# mkdir -p /opt/cloudera/etc/
[root@k8s01 parcels]# ll /opt/cloudera/etc/
drwxr-xr-x 2 root root 154 6 25 10:31 hadoop-conf
drwxr-xr-x 2 root root 153 6 25 10:31 hbase-conf
drwxr-xr-x 2 root root 266 6 25 10:31 hive-conf

配置环境变量

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
cat > /etc/profile.d/cdh.sh <<-EOF
export JAVA_HOME=/usr/lib/jvm/java-1.7.0-openjdk-1.7.0.45.x86_64
export HADOOP_HOME=/opt/cloudera/parcels/CDH
export HIVE_HOME=/opt/cloudera/parcels/CDH/lib/hive
export HBASE_HOME=/opt/cloudera/parcels/CDH/lib/hbase
export HCAT_HOME=/opt/cloudera/parcels/CDH
export HADOOP_CONF_DIR=/opt/cloudera/etc/hadoop-conf
export HIVE_CONF=/opt/cloudera/etc/hive-conf/
export YARN_CONF_DIR=/opt/cloudera/etc/hadoop-conf
export CDH_MR2_HOME=\$HADOOP_HOME/lib/hadoop-mapreduce
export PATH=\${HADOOP_HOME}/bin:\${HADOOP_HOME}/sbin:\${HBASE_HOME}/bin:\${HIVE_HOME}/bin:\${HCAT_HOME}/bin:\${PATH}
EOF
# 两点说明:HDFS/YARN 客户端要读 hadoop-conf 那份,别指到 hive-conf(原来这么写的话解出来的 hadoop-conf 全程没被用上);
# PATH 里也不要放配置目录,PATH 只用于查找可执行文件,放 \$HADOOP_CONF_DIR 不起任何作用。

source /etc/profile

将服务器 ip 及 域名 加入 客户端 /etc/hosts

验证

1
2
3
hdfs dfs -ls /

hive