简介:本资源是一份完整的华为云大数据实验教学报告,面向高校大数据、云计算相关专业学生及初入云平台实践的开发者,聚焦在华为云环境中动手构建与管理Hadoop/Spark集群的核心能力。报告系统覆盖四大实验模块:基于ECS云主机的手动部署大数据环境、调用华为云原生服务(OBS、ECS、数据库等)实现数据存储与分析、使用BigData Pro一站式方案完成Hadoop+Spark双集群搭建与OBS互联验证,以及通过Spark SQL开展交互式大数据查询。资源为1个4.36MB的docx文档,内容结构清晰,含详细操作命令、密钥配置示例、节点SSH连接日志、集群通信测试记录及目录导航,便于边学边练、复现排错。目前已有2443人学习下载,是理解华为云大数据技术栈落地路径、掌握云上分布式系统部署关键步骤的实用型实践材料。
1. 华为云大数据实验报告:不是模板套用,而是真实跑通 Hadoop+Spark+OBS 的四阶段闭环
这不是一份交差用的 PDF 报告,而是一份从零开始、在华为云上亲手把 Hadoop 集群搭起来、让 WordCount 跑出结果、再把 Spark 任务连上 OBS 桶读写数据、最后用 SQL 查出实时统计的完整实操记录。我见过太多人卡在「node1 ssh node2 提示 permission denied」、「hdfs namenode -format 后 jps 看不到 NameNode」、「spark-shell 连不上 hdfs://node1:9000」这三道坎上,反复重装系统三次以上。这份报告里所有命令、IP 映射、密钥配置、hosts 文件内容、甚至 SSH 公钥粘贴时多了一个空格导致互信失败的血泪经验,都原样保留。它适合两类人:一是高校课程设计刚拿到“华为云大数据实验”题目的学生,需要可复现、能截图、能答辩的路径;二是企业内训或自学转岗者,想绕过抽象概念,直接在真实云环境里摸清 Hadoop 分布式启动逻辑、OBS 与 HDFS 的协议桥接机制、以及 Spark on YARN 的资源申请链路。它不讲 MapReduce 原理,但告诉你core-site.xml里fs.defaultFS必须写成hdfs://node1:9000而不是hdfs://192.168.0.10:9000——后者在跨节点通信时会因 DNS 解析失败静默退出。
2. 云主机实现大数据:ECS 四节点集群搭建与 Hadoop 环境初始化
2.1 为什么必须用四节点?单机伪分布式根本练不出真问题
Hadoop 生产级部署从来不是“一台机器配好所有角色”就能模拟的。NameNode、DataNode、ResourceManager、NodeManager 分离部署,才能暴露网络策略、时间同步、SSH 互信、端口冲突等真实约束。本实验采用明确角色划分:
- node1(192.168.0.10):NameNode + ResourceManager + SecondaryNameNode + Spark Master
- node2(192.168.0.53):DataNode + NodeManager + Spark Worker
- node3(192.168.0.169):DataNode + NodeManager + Spark Worker
- node4(192.168.0.77):DataNode + NodeManager + Spark Worker
提示:华为云 ECS 默认安全组只开放 22/3389/80/443,Hadoop 所需端口(如 9000、8020、8088、50070、50075)必须手动添加入方向规则,否则
hdfs dfs -ls /永远超时。
2.2 OpenJDK 安装与环境变量固化:别信java -version显示就完事
华为云新购 ECS 镜像(如 CentOS 7.9)默认无 Java,且yum install java-1.8.0-openjdk-devel安装路径不统一,易导致 Hadoop 启动脚本找不到JAVA_HOME。必须显式安装并硬编码路径:
# 所有节点执行(注意:必须 root 权限) curl -O https://github.com/AdoptOpenJDK/openjdk8-binaries/releases/download/jdk8u362-b09/OpenJDK8U-jdk_x64_linux_hotspot_8u362b09.tar.gz tar -zxvf OpenJDK8U-jdk_x64_linux_hotspot_8u362b09.tar.gz -C /opt/ ln -sf /opt/jdk8u362-b09 /opt/java echo 'export JAVA_HOME=/opt/java' >> /etc/profile echo 'export PATH=$JAVA_HOME/bin:$PATH' >> /etc/profile source /etc/profile验证方式不是java -version,而是which java输出/opt/java/bin/java,且ls -l /opt/java/bin/java指向真实二进制文件。曾有学员因yum install后未清理旧版 Java,update-alternatives --config java切换错误,导致hadoop version报UnsupportedClassVersionError—— JDK 版本错配是 Hadoop 启动失败第一大玄学原因。
2.3 /etc/hosts 静态映射:DNS 不可靠,IP+主机名才是铁律
华为云 ECS 实例名(如ecs-ca89-0001)与内网 IP 绑定,但默认/etc/hosts为空。Hadoop 依赖主机名解析,若仅靠 DHCP 分配的127.0.0.1 localhost,start-dfs.sh会尝试连接localhost:9000而非node1:9000,NameNode 启动后立即退出。必须在所有节点执行:
# 编辑 hosts(注意:四行必须完全一致,不能漏空格) cat >> /etc/hosts << 'EOF' 192.168.0.10 node1 ecs-ca89-0001 192.168.0.53 node2 ecs-ca89-0002 192.168.0.169 node3 ecs-ca89-0003 192.168.0.77 node4 ecs-ca89-0004 EOF验证命令:ping -c 1 node2必须返回64 bytes from ecs-ca89-0002 (192.168.0.53)。若返回Unknown host,说明 hosts 未生效或格式错误(常见坑:行尾多空格、IP 与主机名间非 Tab 或空格、中文符号混入)。
2.4 SSH 免密登录:不是配一次,而是配四组双向通道
Hadoop 启动脚本(如start-dfs.sh)内部调用ssh node2启动 DataNode,若 node1 无法免密登录 node2,脚本卡死在交互式密码提示。但仅配node1 → node2不够,YARN 的start-yarn.sh需要 ResourceManager(node1)向所有 NodeManager(node2~node4)下发命令,且 Spark Worker 启动也需 master 向 worker 免密推送。因此必须建立全连接矩阵:
# 在 node1 上执行(生成密钥对) ssh-keygen -t rsa -P '' -f ~/.ssh/id_rsa # 将公钥分发到所有节点(含自己!) ssh-copy-id -i ~/.ssh/id_rsa.pub root@node1 ssh-copy-id -i ~/.ssh/id_rsa.pub root@node2 ssh-copy-id -i ~/.ssh/id_rsa.pub root@node3 ssh-copy-id -i ~/.ssh/id_rsa.pub root@node4 # 验证:以下四条命令均应无密码输出 ls 结果 ssh node1 'ls /root/.ssh/authorized_keys' ssh node2 'ls /root/.ssh/authorized_keys' ssh node3 'ls /root/.ssh/authorized_keys' ssh node4 'ls /root/.ssh/authorized_keys'关键参数说明:
-P ''表示空密码,避免交互;ssh-copy-id自动追加公钥到authorized_keys并修复权限(.ssh700,authorized_keys600),比手动cat >>更可靠;- 必须包含
ssh-copy-id root@node1,否则start-dfs.sh在本地启动 NameNode 时仍会提示输入密码。
2.5 Hadoop 配置文件精简落地:只改 4 个 XML,删掉所有注释
Hadoop 配置文件(core-site.xml,hdfs-site.xml,yarn-site.xml,mapred-site.xml)官方模板含数百行注释,新手易误改注释块内参数。本实验采用最小化配置,仅保留必需项(已剔除全部注释和冗余 property):
<!-- core-site.xml --> <configuration> <property> <name>fs.defaultFS</name> <value>hdfs://node1:9000</value> </property> </configuration><!-- hdfs-site.xml --> <configuration> <property> <name>dfs.namenode.name.dir</name> <value>/opt/hadoop/data/namenode</value> </property> <property> <name>dfs.datanode.data.dir</name> <value>/opt/hadoop/data/datanode</value> </property> <property> <name>dfs.replication</name> <value>3</value> </property> </configuration><!-- yarn-site.xml --> <configuration> <property> <name>yarn.resourcemanager.hostname</name> <value>node1</value> </property> <property> <name>yarn.nodemanager.aux-services</name> <value>mapreduce_shuffle</value> </property> </configuration><!-- mapred-site.xml --> <configuration> <property> <name>mapreduce.framework.name</name> <value>yarn</value> </property> </configuration>注意:
dfs.namenode.name.dir和dfs.datanode.data.dir对应目录必须提前创建并赋权:mkdir -p /opt/hadoop/data/{namenode,datanode}chown -R root:root /opt/hadoop/data
若目录不存在或权限不足,hdfs namenode -format会报Cannot create directory并静默失败。
3. Hadoop 集群启动与 OBS 互联验证:从格式化到跨云存储读写
3.1 格式化 NameNode 与启动 DFS/YARN:顺序不可逆,日志是唯一真相
Hadoop 启动有严格依赖链:必须先hdfs namenode -format初始化元数据,再start-dfs.sh启动 HDFS,最后start-yarn.sh启动 YARN。任何一步失败,必须查日志而非重试:
# 在 node1 执行(仅一次!重复 format 会清空所有数据) hdfs namenode -format # 启动 HDFS(自动在 node1 启 NameNode,node2~node4 启 DataNode) start-dfs.sh # 启动 YARN(自动在 node1 启 ResourceManager,node2~node4 启 NodeManager) start-yarn.sh验证是否成功,不看 jps,看日志和端口:
tail -n 20 /opt/hadoop/logs/hadoop-root-namenode-node1.log应含Startup completed;netstat -tnlp | grep :9000应显示java进程监听;hdfs dfsadmin -report应列出 3 个 Live Datanodes(node2~node4);yarn node -list应显示 3 个 ACTIVE 节点。
若jps显示进程但hdfs dfs -ls /报Connection refused,大概率是core-site.xml中fs.defaultFS写成hdfs://192.168.0.10:9000,Hadoop 内部用主机名node1解析,而192.168.0.10未映射到node1,导致连接localhost失败。
3.2 WordCount 实验:用真实数据验证集群可用性
下载经典input.txt(含 "hello world hello hadoop" 等文本),上传至 HDFS 并运行 MapReduce:
# 在 node1 创建测试目录并上传 hdfs dfs -mkdir -p /input hdfs dfs -put /root/input.txt /input/ # 运行官方 WordCount(Hadoop 自带) hadoop jar /opt/hadoop/share/hadoop/mapreduce/hadoop-mapreduce-examples-*.jar wordcount /input /output # 查看结果 hdfs dfs -cat /output/part-r-00000预期输出:
hadoop 1 hello 2 world 1若报File does not exist: /input,检查hdfs dfs -ls /是否可见/input;若报Application application_... failed 2 times due to AM Container for ... exited with exitCode: -1000,大概率是 YARN NodeManager 内存不足(华为云默认 ECS 内存 2GB,需在yarn-site.xml中添加yarn.nodemanager.resource.memory-mb设为 1536)。
3.3 OBS 服务接入:不是挂载,而是通过 hadoop-aws 模块桥接
华为云 OBS 是对象存储,HDFS 是分布式文件系统,二者协议不兼容。必须启用 Hadoop 的hadoop-aws模块,并配置 OBS Endpoint。本实验使用obs.cn-north-4.myhuaweicloud.com(华北-北京四区):
<!-- core-site.xml 新增 OBS 相关配置 --> <property> <name>fs.obs.impl</name> <value>org.apache.hadoop.fs.obs.OBSFileSystem</value> </property> <property> <name>fs.AbstractFileSystem.obs.impl</name> <value>org.apache.hadoop.fs.obs.OBS</value> </property> <property> <name>fs.obs.access.key</name> <value>S8RSFKYBTOSPA9YX92XB</value> </property> <property> <name>fs.obs.secret.key</name> <value>jpU0nHcXWVjftBFo7lAdgbq6JjCOPENZylB1fOTk</value> </property> <property> <name>fs.obs.endpoint</name> <value>obs.cn-north-4.myhuaweicloud.com</value> </property>关键点:
fs.obs.access.key和fs.obs.secret.key必须与 OBS 控制台下载的credentials.csv中完全一致(区分大小写,末尾无空格)。曾有学员复制时带入隐藏的 Unicode 字符(如U+200B零宽空格),导致hadoop fs -ls obs://mybucket/报403 Forbidden。
3.4 测试 OBS 互联:用 HDFS 命令直读 OBS 桶
创建 OBS 桶mybucket(公开读写),上传测试文件test.txt,然后在 Hadoop CLI 中访问:
# 列出 OBS 桶内容(需确保 hadoop-aws-*.jar 及其依赖已放入 /opt/hadoop/share/hadoop/common/lib/) hadoop fs -ls obs://mybucket/ # 从 OBS 下载文件到本地 hadoop fs -get obs://mybucket/test.txt /root/ # 将本地文件上传到 OBS hadoop fs -put /root/input.txt obs://mybucket/input/若hadoop fs -ls obs://mybucket/报No FileSystem for scheme: obs,说明hadoop-aws.jar未正确加载(需确认版本匹配 Hadoop 3.x,且aws-java-sdk-bundle-*.jar已一并放入 lib 目录);若报Unable to load AWS credentials from any provider in the chain,检查core-site.xml中 key 名是否拼错(如fs.obs.access.key写成fs.obs.access_key)。
4. Spark 集群搭建与 OBS 数据直读:绕过 HDFS 中转的高效路径
4.1 Spark on YARN 模式选型:为什么不用 Standalone?
本实验采用--master yarn模式,而非 Spark 自带的 Standalone 集群。原因有三:
- 资源复用:YARN 已管理 node2~node4 的 CPU/内存,Spark 直接向 YARN 申请容器,避免独立调度器冲突;
- OBS 兼容性:Spark 3.x 原生支持
obs://URI,但需通过 Hadoop 配置传递 AK/SK,YARN 模式可继承core-site.xml; - 运维简化:无需单独维护 Spark Master/Worker 进程,
spark-submit即可提交任务。
4.2 Spark 配置文件注入 Hadoop 环境:让 Spark “看见” OBS
Spark 本身不解析core-site.xml,需在spark-defaults.conf中显式声明 Hadoop 配置路径,并确保 OBS 相关属性被加载:
# spark-defaults.conf spark.hadoop.fs.obs.impl org.apache.hadoop.fs.obs.OBSFileSystem spark.hadoop.fs.AbstractFileSystem.obs.impl org.apache.hadoop.fs.obs.OBS spark.hadoop.fs.obs.access.key S8RSFKYBTOSPA9YX92XB spark.hadoop.fs.obs.secret.key jpU0nHcXWVjftBFo7lAdgbq6JjCOPENZylB1fOTk spark.hadoop.fs.obs.endpoint obs.cn-north-4.myhuaweicloud.com spark.yarn.jars /opt/spark/jars/*,/opt/hadoop/share/hadoop/common/lib/*注意:
spark.yarn.jars必须包含 Hadoop 的common/lib路径,否则 Spark Driver 无法加载 OBSFileSystem 类,报ClassNotFoundException: org.apache.hadoop.fs.obs.OBSFileSystem。
4.3 Spark Shell 直连 OBS:一行命令验证端到端链路
启动 Spark Shell 并读取 OBS 中的 CSV 文件(假设obs://mybucket/data/user.csv存在):
# 在 node1 启动(自动连接 YARN) spark-shell --master yarn --deploy-mode client # 在 Scala 交互式环境中执行: val df = spark.read.option("header","true").csv("obs://mybucket/data/user.csv") df.show(5)若报java.lang.NoClassDefFoundError: com/amazonaws/auth/AWSCredentialsProvider,说明aws-java-sdk-bundle-*.jar未放入 Spark jars 目录;若报AccessDeniedException: Access Denied,检查spark.hadoop.fs.obs.access.key值是否与credentials.csv一致(尤其注意 Secret Key 是否被截断)。
4.4 Spark SQL 查询 OBS 表:把对象存储当数据库用
创建临时视图并执行 SQL,验证交互式查询能力:
// 注册为临时表 spark.read.option("header","true").csv("obs://mybucket/data/sales.csv") .createOrReplaceTempView("sales") // 执行聚合查询 spark.sql("SELECT region, SUM(amount) FROM sales GROUP BY region").show()此步骤证明:无需将 OBS 数据迁入 Hive 或 HDFS,Spark SQL 可直接扫描对象存储,实现“存算分离”架构下的即席分析。这是华为云 BigData Pro 方案的核心价值之一——降低数据移动成本。
5. 避坑指南:Hadoop+Spark+OBS 联调中 5 个高频翻车现场
5.1 现象:start-dfs.sh后jps显示 NameNode,但hdfs dfsadmin -report无 DataNode
原因:DataNode 进程启动失败,但脚本未报错。常见于/etc/hosts中 node2~node4 的主机名未正确映射到内网 IP,导致 DataNode 尝试连接node1:9000时 DNS 解析超时,自动退出。
解决:在 node2 执行tail -n 50 /opt/hadoop/logs/hadoop-root-datanode-*.log,搜索Connection refused或UnknownHostException;修正/etc/hosts后,先hadoop-daemon.sh stop datanode,再hadoop-daemon.sh start datanode。
5.2 现象:hadoop fs -ls obs://mybucket/返回空列表,但 OBS 控制台可见文件
原因:OBS 桶策略限制了匿名访问,且fs.obs.access.key使用的是 IAM 用户密钥,但该用户未被授予ObjectReader权限。
解决:登录华为云 IAM 控制台,找到用户roy_yuki,为其绑定预设策略OBS ObjectReader;或在桶策略中显式添加"Principal": {"AWS": ["arn:aws:iam::123456789012:user/roy_yuki"]}。
5.3 现象:Spark Shell 中df.show()报java.lang.OutOfMemoryError: GC overhead limit exceeded
原因:Spark Driver 内存默认 1G,读取大文件时元数据解析耗尽堆内存。
解决:启动时指定 Driver 内存:
spark-shell --master yarn --driver-memory 2g --deploy-mode client5.4 现象:spark-submit提交任务后,YARN Web UI 显示 Application 状态为ACCEPTED但长期不变成RUNNING
原因:YARN 资源不足,NodeManager 未上报心跳,或yarn.nodemanager.resource.memory-mb设置过小(如 512MB),而 Spark ApplicationMaster 申请 1024MB 内存失败。
解决:检查yarn node -list是否所有节点状态为RUNNING;增大yarn.nodemanager.resource.memory-mb至 1536,重启 NodeManager:
yarn-daemon.sh stop nodemanager yarn-daemon.sh start nodemanager5.5 现象:hdfs namenode -format成功,但start-dfs.sh后hdfs dfs -ls /报Safe mode is ON
原因:NameNode 启动后进入安全模式(Safe Mode),等待足够多 DataNode 心跳注册(默认需 99.9% DataNode 上线)。若仅启动部分 DataNode(如只启 node2),则永远卡在安全模式。
解决:确认hdfs dfsadmin -report显示所有 DataNode 为Live;若确认已全启,强制退出安全模式:
hdfs dfsadmin -safemode leave6. 进阶技巧:用 Spark Structured Streaming 实现实时 OBS 日志消费
6.1 为什么 Structured Streaming 比传统 Flume+Kafka 更轻量?
在华为云场景下,OBS 天然支持事件通知(Event Notification),当新文件写入桶时,可触发函数工作流(FunctionGraph)或直接被 Spark Streaming 监听。相比部署 Kafka 集群,OBS+Spark Streaming 架构更简洁:
- 数据源:OBS 桶
obs://mybucket/logs/持续追加app-20240501-001.log; - 计算引擎:Spark Structured Streaming 监听目录,按文件事件触发微批处理;
- 结果存储:写回 OBS 或直推至华为云 DWS 数据仓库。
6.2 实现代码:监听 OBS 目录并解析 Nginx 日志
以下 Scala 代码在 Spark Shell 中可直接运行(需提前上传nginx-log-parser.jar到集群):
import org.apache.spark.sql.functions._ val logStream = spark .readStream .format("csv") .option("sep", " ") // Nginx 日志以空格分隔 .option("inferSchema", "false") // 避免 schema 推断开销 .schema("ip STRING, time STRING, method STRING, url STRING, status STRING, size STRING") .load("obs://mybucket/logs/") val parsedLog = logStream .withColumn("timestamp", to_timestamp(col("time"), "[dd/MM/yyyy:HH:mm:ss Z]")) .filter(col("status") === "200") .groupBy(window(col("timestamp"), "10 minutes"), col("url")) .count() val query = parsedLog .writeStream .format("console") .outputMode("Append") .trigger(Trigger.ProcessingTime("30 seconds")) .start() query.awaitTermination()参数说明:
.trigger(Trigger.ProcessingTime("30 seconds"))表示每 30 秒检查一次 OBS 目录新增文件;window(..., "10 minutes")滚动窗口聚合,避免状态无限增长;outputMode("Append")仅输出新增结果,适合监控场景。
6.3 性能调优:OBS 列式扫描加速与小文件合并
OBS 本质是对象存储,频繁读取小文件(如每秒 100 个 1KB 日志)会导致大量 HTTP 请求,拖慢 Streaming 吞吐。解决方案:
- 合并小文件:用华为云 DLI(Data Lake Insight)服务定时执行
INSERT INTO TABLE merged_logs SELECT * FROM obs://mybucket/logs/ WHERE dt='20240501',将当日所有小文件合并为 Parquet 列式文件; - 启用 OBS Select:对 CSV/JSON 文件,用
obs://bucket/prefix/?select-type=1&select-sql=SELECT%20*%20FROM%20S3Object%20WHERE%20s.status%3D200直接下推过滤,减少网络传输量。
从那以后我每次部署 Hadoop 集群,都强制走一遍ping node2 && ssh node2 'hostname' && hdfs dfsadmin -report三连检;每次配 OBS,必用hadoop fs -ls obs://bucket/验证后再写 Spark 代码;每次提交 Streaming 任务,先用--master local[2]本地模式跑通逻辑,再切到 YARN。这些看似繁琐的步骤,省下的不是时间,而是凌晨三点排查NoSuchMethodError的崩溃感。希望帮到你。
本文还有配套的精品资源,点击获取