TT Lab
开始
学习 学习路径 课程

Apache Hadoop — 在一个 Pod 里搭起并运维 HDFS 与 YARN

按 2Gi 的 Pod 设定容器大小并划分队列

在 TT Lab 中继续学习

目标

通过 ResourceManager 的 REST API 确认这个集群能提供的资源,并观察请求比它更大的容器的作业会如何结束。在 Capacity Scheduler 中创建 etl 和 adhoc 队列并提交作业,同时涉及不存在的队列被拒绝,以及把已结束作业的日志聚合起来阅读的方法。

为什么重要

YARN 是以容器为单位分配集群内存和核数的资源管理器。NodeManager 会报告自己能提供的份额(yarn.nodemanager.resource.memory-mb),ResourceManager 的调度器则把请求提升到最小分配单位来占用,大于最大分配就拒绝。无论是 MapReduce 还是 Spark,凡是运行在 YARN 之上的,都遵循这些规则。 在生产环境中,“作业停在 ACCEPTED 不动”和“作业马上就死了”,大多是这些数字的问题。容器大小比节点份额大,就永远排不上位置;比最大分配大,就会立刻被拒绝。这个 Pod 内存只有 2Gi,所以把节点份额设成了 1024MB——数字小,规则反而更容易看清。 队列是多个团队共用一个集群的办法。Capacity Scheduler 为每个队列设置保证份额(capacity)和可借用的上限(maximum-capacity)。同一个父队列下,保证份额之和必须是 100,修改配置文件后用 refreshQueues 重新读取。已结束容器的日志由 NodeManager 聚合保存到 HDFS(日志聚合),所以即使 Pod 消失了,也能用 yarn logs 读取。

步骤

  1. 用 lab-hadoop start yarn 启动 YARN,并把 curl -s http://localhost:8088/ws/v1/cluster/metrics 的响应保存到 /root/hdp/yarn/metrics.json。
  2. 用 -D mapreduce.map.memory.mb=2048 运行示例 jar 中的 pi,让作业结束,然后把该应用的 yarn application -status <애플리케이션 ID> 的输出保存到 /root/hdp/yarn/toobig.txt(占位符为应用 ID)。
  3. 修改 /opt/hadoop/etc/hadoop/capacity-scheduler.xml,把 root 之下的队列设为 default,etl,adhoc,保证份额设为 20、50、30,adhoc 的上限设为 50,执行 yarn rmadmin -refreshQueues 之后,把 yarn queue -status etl 的输出保存到 /root/hdp/yarn/etl.txt。
  4. 把 /data/books/book-1.txt 上传到 HDFS 的 /user/root/yarn/in/,并用 -D mapreduce.job.queuename=etl 运行 wordcount,输出到 /user/root/yarn/wc-etl。
  5. 把同样的 wordcount 提交到不存在的队列 nope(输出 /user/root/yarn/wc-nope),并把错误输出保存到 /root/hdp/yarn/badqueue.txt。
  6. 把 curl -s http://localhost:8088/ws/v1/cluster/scheduler 的响应保存到 /root/hdp/yarn/scheduler.json。
  7. 用 yarn logs -applicationId <애플리케이션 ID> 聚合第 4 步作业的应用日志,保存到 /root/hdp/yarn/etl-logs.txt(占位符为应用 ID)。
  8. 在 /root/hdp/yarn/report.md 中写出 ## 컨테이너 크기、## 대기열、## 로그 三个小节。第一节写入第 1 步的 totalMB 和第 2 步中请求的 2048。

参考

集群能提供什么

用 lab-hadoop start yarn 启动 YARN,并把 curl -s http://localhost:8088/ws/v1/cluster/metrics 的响应 JSON 保存到 /root/hdp/yarn/metrics.json。

clusterMetrics 中的 totalMB、totalVirtualCores、activeNodes 就是 NodeManager 报告的份额。请想一想:Pod 是 2Gi,totalMB 为什么比它小得多——HDFS 和 YARN 的四个守护进程以及客户端 JVM 会先占去位置。

比最大分配更大的容器

运行 yarn jar /opt/hadoop/share/hadoop/mapreduce/hadoop-mapreduce-examples-3.5.0.jar pi -D mapreduce.map.memory.mb=2048 1 10,让作业结束,然后把该应用的 yarn application -status application_<…> 的输出保存到 /root/hdp/yarn/toobig.txt。

一个 Map 要 2048MB,而最大分配是 1024MB。AM 在请求 Map 容器之前,就把作业以 KILLED 结束了。应用 ID 就是作业 ID 的数字,在历史文件夹中找名称为 QuasiMonteCarlo 的 KILLED 作业即可。诊断(Diagnostics)行会说明原因。

创建三个队列

在 /opt/hadoop/etc/hadoop/capacity-scheduler.xml 中,把 yarn.scheduler.capacity.root.queues 设为 default,etl,adhoc,把 root.default.capacity、root.etl.capacity、root.adhoc.capacity 设为 20、50、30,把 root.adhoc.maximum-capacity 设为 50。用 yarn rmadmin -refreshQueues 重新读取之后,把 yarn queue -status etl 的输出保存到 /root/hdp/yarn/etl.txt。

同一个父队列下,保证份额(capacity)之和必须是 100,refreshQueues 才会接受。上限(maximum-capacity)是能借用剩余资源的界限。光修改配置文件什么都不会发生——必须重新读取。

向 etl 队列提交作业

把 /data/books/book-1.txt 上传到 HDFS 的 /user/root/yarn/in/,并用 yarn jar <예제 jar> wordcount -D mapreduce.job.queuename=etl /user/root/yarn/in /user/root/yarn/wc-etl 运行(占位符为示例 jar)。

队列只写名字(不带 root.)。请看作业历史文件名中的队列一栏是否出现了 root.etl。评分器会检查这一栏和输出中的 _SUCCESS。

不存在的队列在提交时被拒绝

用 -D mapreduce.job.queuename=nope 把同样的 wordcount 提交到 /user/root/yarn/wc-nope,并把错误输出(包括标准错误)保存到 /root/hdp/yarn/badqueue.txt。

调度器在接收应用的那一刻就会拒绝不存在的队列。作业根本没有开始,所以历史中也不会留下记录——因此这个错误只存在于提交一方的输出中。

调度器看到的队列

把 curl -s http://localhost:8088/ws/v1/cluster/scheduler 的响应 JSON 保存到 /root/hdp/yarn/scheduler.json。

响应的 scheduler.schedulerInfo.queues.queue 中,每个队列都有 capacity、maxCapacity、usedCapacity。评分器会检查这些值是否与你修改过的配置文件一致——相当于确认 refreshQueues 是否真的生效了。

读取已结束作业的聚合日志

用第 4 步作业的应用 ID(application_<…>)执行 yarn logs -applicationId <ID>,把输出保存到 /root/hdp/yarn/etl-logs.txt。

容器结束后,NodeManager 会把它的日志聚合到 HDFS 的 /tmp/logs/<사용자>/ 之下(日志聚合)(占位符为用户名)。所以即使节点消失了,日志也还在。应用结束后聚合需要几秒钟,所以马上调用可能会得到空输出。输出中,每个容器依次出现 Container: 头部,以及 LogType:syslog、stdout、stderr。

记录资源数字

在 /root/hdp/yarn/report.md 中写出 ## 컨테이너 크기、## 대기열、## 로그 三个小节。第一节以数字写入第 1 步的 totalMB 和第 2 步中请求的 2048。

请写出:节点份额、最小分配、最大分配和 AM 大小是如何相互咬合的;队列的保证份额和上限意味着什么;日志聚合到了哪里。