简介:《华为云大数据实验报告hhu》面向高校大数据课程学习者与云计算实践入门者,围绕在华为云上搭建和管理大数据平台的关键环节展开,适合作为课程实验、课程设计或平台部署练习的参考材料。资源包共1个docx文档,压缩后约4.36MB,内容以图文实验记录和过程说明为主,便于按实验模块查阅与整理。已有2607人学习,说明其在华为云大数据实验场景中具有一定参考价值。报告覆盖云主机实现大数据、云服务实现大数据、BigData Pro综合实验以及大数据交互式查询四个部分,涉及ECS与OBS配置、Hadoop集群搭建、节点通信测试、Spark集群部署、SQL查询分析等实践内容,可帮助读者梳理实验流程、理解云服务协同方式,并对照完成环境配置、集群验证与结果分析,积累云端大数据平台的部署与排错经验。
1. 从四台云主机到能跑的集群:这套大数据实验环境的真实门槛
大数据实验这四个字,写到操作里就是四台云主机、一个对象存储桶、一份 hosts、一次 SSH 互信、四个 Hadoop XML,外加一次绝对不能再来的 NameNode 格式化。云主机实现大数据这条链路之所以被反复抄进实验报告,是因为它把 Hadoop 集群搭建、Spark 集群搭建、对象存储互联这三件事串成了一条线;反过来,只要有一个环节没对齐,后面全是运气——hosts 少写一行,节点互信就成了主要障碍;副本数写 4 却只买了 4 台、其中一台还兼着 NameNode,YARN 一启动就报资源不满。
这篇记录面向想在自己账号下把整套环境复现一遍的人:不追最新版本,只求一次装通、装坏能救。从买机器、建桶、配互信,到格式化、启动、提交第一个任务,每一步都给能抄的命令和能对照的参数。
2. 环境规划:四台 ECS、一个 OBS 桶、一份 hosts 先定死
集群装不起来,多数时候不是命令敲错,是资源买错。我见过最常见的返工是买了四台机器却发现不在同一个子网,内网地址互相 ping 不通,只能退订重买;也见过把桶建在另一个区域,结果 ECS 访问对象存储走的是公网,跑一个 distcp 慢得像在等下载。所以动手前先把三张表定下来:节点角色与规格、桶和密钥、名字与地址的映射。
2.1 四台节点的规格与镜像:2 核 4G 是底线不是推荐
弹性云服务器按角色分,不要四台一个模子买。NameNode 和 ResourceManager 都压在 node1 上,它还要跑 Spark Master,内存吃紧最先出问题的就是它。
| 节点 | 承担角色 | 建议规格 | 磁盘 |
|---|---|---|---|
| node1 | NameNode、ResourceManager、SecondaryNameNode、Spark Master | 2 核 4G(4 核 8G 更稳) | 系统盘 40G + 数据盘 100G |
| node2 | DataNode、NodeManager、Spark Worker | 2 核 4G | 系统盘 40G |
| node3 | DataNode、NodeManager、Spark Worker | 2 核 4G | 系统盘 40G |
| node4 | DataNode、NodeManager、Spark Worker | 2 核 4G | 系统盘 40G |
镜像选 CentOS 7.9 或 Ubuntu 20.04 这一档,别一上来就选最新的发行版。新版系统自带的 OpenJDK 往往是 11 或 17,Hadoop 3.3.x 在 Java 8 上最稳,Java 11 要额外改一堆启动参数,Java 17 直接不认。省事的做法是装完系统后手动装 JDK 8,把系统自带的卸掉或者不设成默认。
买的时候还有四个勾必须打对:同一个区域、同一个可用区、同一个 VPC 和子网、加入同一个安全组。公网 IP 只给 node1 绑一个用来登录,其余三台不买带宽,集群内部全走内网地址。这样既省钱,也避免有人图省事在配置文件里写公网 IP,结果节点间通信绕出去再绕回来,延迟翻好几倍。
提示:安全组是第二层防火墙。node1 对办公网只放通 22 端口,9000(HDFS)、9870(NameNode Web)、8088(YARN Web)、7077(Spark Master)、8080(Spark Worker)这些一律只对内网网段放通,不要图方便开成 0.0.0.0/0。
2.2 OBS 桶怎么建:区域对齐比桶名重要
对象存储在这一套里干两件事:存实验原始数据,以及给 HDFS 当外部落地的中转站。建桶的流程不长,但有几个点决定后面能不能通。
桶名全局唯一,区域必须和 ECS 一致,这是第一位的。如果后面打算把桶当文件系统直接挂给计算引擎用(比如让 Spark 的 warehouse 目录落在桶上),创建时选并行文件系统类型,普通对象桶在 rename 和追加写上会明显拖慢任务。
创建完成之后,控制台上会给出桶的访问地址(Endpoint)和区域代码,把这两个记下来。接着去创建访问密钥,下载下来的 credentials.csv 里是三列:User Name、Access Key Id、Secret Access Key。
| 项 | 用途 | 注意 |
|---|---|---|
| Access Key Id(AK) | 标识调用者身份 | 可重新下载,泄露风险相对低 |
| Secret Access Key(SK) | 请求签名密钥 | 只在创建时给一次,关掉页面就再也看不到 |
| Endpoint | 服务访问地址 | 必须和桶同区域,写错就是连不上 |
SK 只给一次这件事,是这套环境里最容易被忽略的后悔药问题。很多人的做法是下载完 csv 直接扔进项目目录,顺手提交到代码仓库,过两天发现桶里多了不认识的文件。正确姿势是拿到就写进配置文件、把 csv 删掉,或者至少放进 .gitignore 覆盖不到的路径。
密钥最终要落进 Hadoop 的 core-site.xml,形如:
<!-- core-site.xml 中与对象存储相关的三个属性,值从 credentials.csv 和控制台取 --> <property> <name>fs.obs.access.key</name> <value>你的AccessKeyId</value> </property> <property> <name>fs.obs.secret.key</name> <value>你的SecretAccessKey</value> </property> <property> <name>fs.obs.endpoint</name> <value>控制台 Endpoint 一栏给出的地址</value> </property>这三个属性的作用是让 Hadoop 的 OBS 文件系统实现拿到签名凭据。前两个填错的表现是 403,第三个填错的表现是连接超时或者域名解析失败,两种报错指向的原因完全不同,排查时先看报错类型再看内容。
2.3 内网 IP 与 hosts:四个名字必须先对上号
云主机默认的主机名通常是一串带实例 ID 的名字,跟配置文件里写的 node1、node2 对不上,后面 ssh 和集群内通信全靠碰运气。所以开机第一件事是改主机名,再写 hosts。
在四台机器上分别执行:
# 以 node1 为例,node2~node4 改成对应名字 hostnamectl set-hostname node1 # 四台机器都追加同样的四行,IP 换成你自己的内网地址 cat >> /etc/hosts <<'EOF' 192.168.0.10 node1 192.168.0.53 node2 192.168.0.169 node3 192.168.0.77 node4 EOF这里有两个细节。一是 IP 必须用内网地址,不是绑在 node1 上的公网地址;二是主机名不要带下划线和特殊字符,Hadoop 在解析时对这类字符处理得不干净,日志里会出现莫名其妙的主机名解析失败。
改完之后用hostname和ping -c 2 node2各验一次。四台机器上 hosts 内容必须完全一致,任何一台少一行,后面分布式启动就会卡在那台机器上,而且报错信息通常只写「连接被拒绝」,不会告诉你是 hosts 的问题。
3. 系统层准备:OpenJDK、防火墙、SSH 互信
这一层是三件事,做完了才有资格谈 Hadoop。顺序不能乱:先 JDK,再关防火墙,最后配互信。互信放最后是因为它依赖主机名已经定好,hosts 没写对就去配免密,配完还是要输密码。
3.1 OpenJDK 安装与 JAVA_HOME 落位
按发行版选命令,四台机器都要装。
# CentOS 7 系 yum install -y java-1.8.0-openjdk java-1.8.0-openjdk-devel # Ubuntu 20.04 系 apt-get update && apt-get install -y openjdk-8-jdk只装 JRE 是不够的。Hadoop 编译本地库、Spark 提交任务时都要用到 JDK 里的编译工具,缺了会在运行任务时报 NoClassDefFoundError 或者 tools.jar 找不到,而这个错跟业务代码毫无关系,排查起来很绕。
装完先确认路径:
readlink -f $(which java) # 输出类似 /usr/lib/jvm/java-1.8.0-openjdk-1.8.0.392.b08-2.el7_9.x86_64/jre/bin/java把末尾的/jre/bin/java去掉,就是 JAVA_HOME。然后统一写进 /etc/profile.d 下,不要直接改 /etc/profile,改坏了不好回滚:
cat > /etc/profile.d/bigdata.sh <<'EOF' export JAVA_HOME=/usr/lib/jvm/java-1.8.0-openjdk-1.8.0.392.b08-2.el7_9.x86_64 export PATH=$JAVA_HOME/bin:$PATH EOF source /etc/profile.d/bigdata.sh java -version版本取舍上,Hadoop 3.3.x 配 Java 8 是踩坑最少的组合;如果团队统一要求 Java 11,需要额外在 hadoop-env.sh 和 yarn-site.xml 里补 openssh 相关参数,属于能跑但要多调半天的那类。四台机器上的 JAVA_HOME 路径要完全一致,否则远程启动进程时会因为找不到 Java 直接退出。
3.2 关闭防火墙与 SELinux:集群通信的前提
云上其实有两层防火墙,安全组和系统自带的 firewalld。安全组放通了,系统里没关,端口照样不通。
# 四台都执行 systemctl stop firewalld systemctl disable firewalld setenforce 0 sed -i 's/^SELINUX=.*/SELINUX=disabled/' /etc/selinux/config前两行处理 firewalld,后两行处理 SELinux。setenforce 0只对当前生效,改配置文件是为了重启后依然关闭。如果只做前一步,机器一重启集群又连不上,这种问题最费时间,因为你会默认怀疑配置写错了。
验证方式很简单,在 node1 上随便挑一个端口试:
# 在 node2 上起个临时监听 python3 -m http.server 9000 # 在 node1 上访问 curl -I http://node2:9000能返回 200 就说明系统层没拦。这一步过了,后面 Hadoop 起不来就基本可以排除网络因素。
3.3 四节点 SSH 免密:从 ssh-keygen 到 authorized_keys
Hadoop 和 Spark 的启动脚本本质是在本地循环 ssh 到各节点执行命令,免密没配好,start-dfs.sh会中途停下来等密码,然后超时退出。
第一步,四台机器各自生成密钥对,一路回车不要设密码:
ssh-keygen -t rsa -b 2048 -N '' -f /root/.ssh/id_rsa第二步,把四台的公钥都取出来:
cat /root/.ssh/id_rsa.pub第三步,在 node1 上把四段公钥拼进同一个 authorized_keys 文件。公钥整行照抄,最后一段注释会显示root@node1这类信息,能帮你确认有没有漏:
cat >> /root/.ssh/authorized_keys <<'EOF' ssh-rsa AAAAB3Nza...第一台公钥... root@node1 ssh-rsa AAAAB3Nza...第二台公钥... root@node2 ssh-rsa AAAAB3Nza...第三台公钥... root@node3 ssh-rsa AAAAB3Nza...第四台公钥... root@node4 EOF chmod 700 /root/.ssh chmod 600 /root/.ssh/authorized_keys第四步,把这份合并后的文件分发到其余三台,第一次分发需要输密码:
for h in node2 node3 node4; do scp /root/.ssh/authorized_keys $h:/root/.ssh/authorized_keys done分发完再统一改一次权限,scp 过去的文件权限会跟着源文件走,但养成习惯没坏处。
验证不要用ssh node2手动敲,那样看不出问题。用批量模式跑一圈:
for h in node1 node2 node3 node4; do ssh -o BatchMode=yes -o ConnectTimeout=5 $h hostname doneBatchMode=yes的含义是禁止交互式输入密码,能返回四个主机名就说明真的通了;如果某台卡住,说明那台的 authorized_keys 没同步或者权限不对。这个循环我每次都跑,比一个个试快得多。
还有一个高频坑:root 家目录的权限。有些镜像把 /root 设成 777,sshd 会因为权限过宽拒绝使用 authorized_keys,日志里写的是「Authentication refused: bad ownership or modes」。改回 700 就好,跟密钥本身没关系。
4. Hadoop 与 Spark 集群搭建:四个 XML、一次格式化、一次提交
配置文件的思路是先在一台机器上改好,再整体分发,不要四台各改一遍——总有一台会漏掉一个属性,而集群启动时不会告诉你哪台漏了。
4.1 解包、环境变量与 workers
cd /opt # 从 Apache 官方归档站下载,版本按团队统一的来,这里以 3.3.x 为例 wget https://archive.apache.org/dist/hadoop/common/hadoop-3.3.6/hadoop-3.3.6.tar.gz tar -zxvf hadoop-3.3.6.tar.gz mv hadoop-3.3.6 /opt/hadoop解包之后配环境变量,仍然写进 /etc/profile.d,四台保持一致:
cat >> /etc/profile.d/bigdata.sh <<'EOF' export HADOOP_HOME=/opt/hadoop export HADOOP_CONF_DIR=$HADOOP_HOME/etc/hadoop export PATH=$HADOOP_HOME/bin:$HADOOP_HOME/sbin:$PATH EOF source /etc/profile.d/bigdata.shHADOOP_CONF_DIR 这个变量必须显式设。有些教程只设 HADOOP_HOME,本地跑没问题,但 Spark 读取 HDFS 配置时找不到 core-site.xml,会报「No FileSystem for scheme: hdfs」,看着像 Jar 包缺失,其实是配置目录没告诉它。
workers 文件决定 DataNode 起在哪几台:
cat > $HADOOP_CONF_DIR/workers <<'EOF' node2 node3 node4 EOF注意 Hadoop 3.x 里这个文件叫 workers,2.x 叫 slaves,照旧教程抄会找不到文件。node1 不写进去,它只做 NameNode 和 ResourceManager;如果想让 node1 也存数据,加一行就行,但 2 核 4G 的机器同时干四件事,跑大任务容易 OOM。
4.2 core-site.xml:默认文件系统与 OBS 接入点
这是四个文件里第一个要改的,决定客户端默认连哪个 HDFS。
<configuration> <!-- 默认文件系统指向 node1 的 9000 端口 --> <property> <name>fs.defaultFS</name> <value>hdfs://node1:9000</value> </property> <!-- 临时目录必须改,默认 /tmp 重启即丢 --> <property> <name>hadoop.tmp.dir</name> <value>/data/hadoop/tmp</value> </property> <!-- 对象存储凭据,见 2.2 节 --> <property> <name>fs.obs.access.key</name> <value>你的AccessKeyId</value> </property> <property> <name>fs.obs.secret.key</name> <value>你的SecretAccessKey</value> </property> <property> <name>fs.obs.endpoint</name> <value>控制台 Endpoint 一栏给出的地址</value> </property> </configuration>hadoop.tmp.dir这一项值得单独说。默认值是 /tmp/hadoop-${user},云主机重启、系统清理临时文件都会把它删掉,NameNode 的元数据和 DataNode 的块文件一旦落在这里,重启后集群直接变成空壳,而且报错信息只是「找不到块」,不会告诉你目录被清了。改成数据盘路径,一次省掉半天排查。
4.3 hdfs-site.xml、yarn-site.xml 与 mapred-site.xml
三个文件的属性各有侧重:hdfs 管副本和存储路径,yarn 管资源上限,mapred 管任务运行时环境。
<!-- hdfs-site.xml --> <configuration> <!-- 副本数不超过 DataNode 台数,三台就写 3 --> <property> <name>dfs.replication</name> <value>3</value> </property> <property> <name>dfs.namenode.name.dir</name> <value>file:///data/hadoop/name</value> </property> <property> <name>dfs.datanode.data.dir</name> <value>file:///data/hadoop/data</value> </property> </configuration>副本数是最容易照抄错的一项。教程里写 3,你只有两台 DataNode,上传文件时就会一直报「could only be replicated to 0 nodes」,看着像权限问题,实际是凑不够副本数。按实际 DataNode 数量填,宁可写 2。
<!-- 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> <!-- 2 核 4G 的机器给到 3072 已经接近顶格 --> <property> <name>yarn.nodemanager.resource.memory-mb</name> <value>3072</value> </property> <property> <name>yarn.scheduler.maximum-allocation-mb</name> <value>3072</value> </property> </configuration>这两个内存参数必须一起改。只改 nodemanager 那项、不改 scheduler 上限,提交任务时会报「Invalid resource request, requested memory < 0, or requested memory > max configured」,因为调度器认为单容器最多只能要 8192(默认值),而节点实际只有 3072,两边对不上。
<!-- mapred-site.xml --> <configuration> <property> <name>mapreduce.framework.name</name> <value>yarn</value> </property> <!-- 3.x 必填,漏了任务跑一半会 NoClassDefFoundError --> <property> <name>yarn.app.mapreduce.am.env</name> <value>HADOOP_MAPRED_HOME=/opt/hadoop</value> </property> <property> <name>mapreduce.map.env</name> <value>HADOOP_MAPRED_HOME=/opt/hadoop</value> </property> <property> <name>mapreduce.reduce.env</name> <value>HADOOP_MAPRED_HOME=/opt/hadoop</value> </property> </configuration>后面这三个 env 是 Hadoop 3.x 相对 2.x 的新增要求,很多老教程没有。漏掉的典型现象是任务卡在 ACCEPTED 或者刚跑起来就失败,日志里翻半天只能看到类找不到,跟容器环境变量其实是一个事。
最后别忘了 hadoop-env.sh 里的 JAVA_HOME,这是独立于 /etc/profile 的:
echo 'export JAVA_HOME=/usr/lib/jvm/java-1.8.0-openjdk-1.8.0.392.b08-2.el7_9.x86_64' >> $HADOOP_CONF_DIR/hadoop-env.sh配好之后整体分发,别一台台改:
for h in node2 node3 node4; do scp -r $HADOOP_CONF_DIR/* $h:$HADOOP_CONF_DIR/ done4.4 格式化 NameNode 与启动集群
格式化只做一次,做之前确认三件事:hadoop.tmp.dir 和 dfs.namenode.name.dir 指向的目录是空的、四台配置已同步、workers 文件里写的是 node2 到 node4。
hdfs namenode -format看到Storage directory /data/hadoop/name has been successfully formatted才算成功。这一步失败通常是目录权限或者磁盘空间,跟配置无关。
启动分两步,先 HDFS 后 YARN:
start-dfs.sh start-yarn.sh然后在 node1 上jps看进程,应该有 NameNode、ResourceManager、SecondaryNameNode;node2 到 node4 上应该有 DataNode 和 NodeManager。少哪个就去对应机器的日志里找,日志在$HADOOP_HOME/logs下,按日期命名。
确认 DataNode 都注册上了:
hdfs dfsadmin -report输出里Live datanodes (3)这一行是关键。如果显示 0,说明 DataNode 没连上 NameNode,八成是 hosts 或者防火墙的问题,回头查第 2、3 章。
4.5 Spark 解包与 spark-env.sh:指向 Hadoop 的那几个变量
Spark 包一定要选带 hadoop3 后缀的二进制版,纯 bin 包不带 HDFS 客户端依赖,读 HDFS 会直接报类找不到。
cd /opt wget https://archive.apache.org/dist/spark/spark-3.3.2/spark-3.3.2-bin-hadoop3.tgz tar -zxvf spark-3.3.2-bin-hadoop3.tgz mv spark-3.3.2-bin-hadoop3 /opt/sparkspark-env.sh 从模板复制后追加,重点是 HADOOP_CONF_DIR:
cp /opt/spark/conf/spark-env.sh.template /opt/spark/conf/spark-env.sh cat >> /opt/spark/conf/spark-env.sh <<'EOF' export JAVA_HOME=/usr/lib/jvm/java-1.8.0-openjdk-1.8.0.392.b08-2.el7_9.x86_64 export HADOOP_CONF_DIR=/opt/hadoop/etc/hadoop export SPARK_MASTER_HOST=node1 export SPARK_WORKER_MEMORY=2g export SPARK_WORKER_CORES=2 EOFSPARK_WORKER_MEMORY 给 2g 是因为机器总共 4G,还要留给系统和 NodeManager。给 3g 以上,Worker 起得来但一跑任务就被系统 OOM Killer 干掉,现象是 Worker 进程莫名消失,日志里什么都没有。
workers 文件同样只写计算节点:
cp /opt/spark/conf/workers.template /opt/spark/conf/workers cat > /opt/spark/conf/workers <<'EOF' node2 node3 node4 EOF把整个 Spark 目录分发到三台计算节点,路径保持一致:
for h in node2 node3 node4; do scp -r /opt/spark $h:/opt/ done启动时用绝对路径,因为 Hadoop 也有个 start-all.sh,环境变量顺序不同会调到错的:
/opt/spark/sbin/start-all.sh访问 node1 的 8080 端口能看到 Worker 列表,三个 ALIVE 就对了。
4.6 提交第一个任务:wordcount 与 distcp 到 OBS
先用 Hadoop 自带的例子验证 HDFS 和 YARN 这条链路:
# 造一份小数据 hdfs dfs -mkdir -p /input printf 'hello bigdata\nhello spark\nhello hdfs\n' > /tmp/wc.txt hdfs dfs -put /tmp/wc.txt /input/ # 跑自带 wordcount hadoop jar $HADOOP_HOME/share/hadoop/mapreduce/hadoop-mapreduce-examples-3.3.6.jar \ wordcount /input /output hdfs dfs -cat /output/part-r-00000能打印出三行带词频的结果,说明 HDFS 读写、YARN 调度、MapReduce 运行时环境三样都通了。
再验证对象存储,用 distcp 把结果推过去:
hadoop distcp hdfs://node1:9000/output obs://你的桶名/outputdistcp 是最省事的联调手段,一条命令同时检验 AK/SK、Endpoint、桶权限和网络连通性四件事。能跑完不报错,第 2.2 节配的那三个属性就是对的;报 403 查密钥,报连接超时查 Endpoint 和区域。
5. 常见问题排查:这套集群装崩的五个现场
装这套环境的经验,一半来自配置文档,一半来自这些报错。下面五条是我遇到过频率最高的,每条都按现象、原因、解决写,遇到问题时对着找比从头读日志快。
5.1 免密配完了 ssh 还要密码
现象:authorized_keys 里四段公钥都在,ssh node2仍然提示输入密码,但输完密码能进去。
原因:九成是权限问题。sshd 对 .ssh 目录和 authorized_keys 的权限有硬性要求,目录必须是 700,文件必须是 600,家目录不能是 777 或者属主不对。另一种可能是公钥粘贴时被换行截断,中间缺了一段。
解决:先看 sshd 日志/var/log/secure,如果出现Authentication refused: bad ownership or modes,直接chmod 700 /root/.ssh && chmod 600 /root/.ssh/authorized_keys。日志没这条,就把公钥整行重新复制一遍,确认开头是 ssh-rsa、结尾是 root@主机名,中间没有断行。最后用ssh -o BatchMode=yes node2 hostname验证,这个参数会禁止密码回退,能过才是真的免密。
5.2 格式化之后 DataNode 一个都没起来
现象:hdfs dfsadmin -report显示Live datanodes (0),node2 到 node4 的 DataNode 进程起不来或者起来就退出。
原因:集群 ID 不一致。NameNode 格式化时会生成一个 clusterID 写进 VERSION 文件,DataNode 首次启动时也会生成自己的。如果之前格式化过一次、DataNode 上残留了旧目录,两边的 ID 对不上,DataNode 会拒绝加入。
解决:先停掉所有进程,把四台机器上 dfs.datanode.data.dir 和 dfs.namenode.name.dir 指向的目录整个清空,再重新格式化一次 NameNode,然后启动。注意格式化只能做一次这个说法是有前提的——集群里没有有效数据时可以重来,有数据时清目录等于删数据。所以这套环境里我习惯在格式化之前先确认所有节点目录都是空的。
5.3 YARN 任务一直卡在 ACCEPTED
现象:任务提交成功,状态一直是 ACCEPTED,进度条不动,过很久变成 FAILED。
原因:两个方向。一是 NodeManager 没注册上,ResourceManager 手里没有可用资源;二是资源参数配得比节点实际能力还大,调度器分不出容器。
解决:先开 8088 端口看 Nodes 页面,如果节点数是 0,说明 NodeManager 没连上,查 hosts 和防火墙;节点数正常但内存 Available 是 0,回头改 yarn-site.xml 里的yarn.nodemanager.resource.memory-mb和yarn.scheduler.maximum-allocation-mb,两个值要一致且不能超过物理内存的 80%。2 核 4G 的机器写 3072 是合理上限,写 4096 会连系统和 NodeManager 自己都跑不动。
5.4 distcp 报 No FileSystem for scheme "obs"
现象:本地 HDFS 操作一切正常,一执行 distcp 到对象存储就报找不到 obs 文件系统。
原因:缺少对象存储的 SDK 依赖,或者类路径里没有对应的 jar。Hadoop 原生只带 hdfs、file、s3a 这几种实现,obs 协议的实现需要额外的 jar 包放进$HADOOP_HOME/share/hadoop/common/lib下。另一种原因是 core-site.xml 里的配置没分发到执行节点,客户端拿不到 Endpoint。
解决:把对应版本的存储 SDK jar 复制到 Hadoop 的 common/lib 目录,四台机器都放,然后重启相关进程。配置问题就检查$HADOOP_CONF_DIR/core-site.xml在各节点上是否内容一致,用 md5sum 对比最快。改完不用重启整个集群,重新提交任务即可。
注意:jar 包的版本要和 Hadoop 大版本匹配。3.3.x 配错 SDK 版本有时不报错,只是在写大文件时随机失败,比直接报错更难查。
5.5 spark-sql 起不来或者连不上 HDFS
现象:spark-sql启动后报找不到 HDFS 上的路径,或者提交任务时报No FileSystem for scheme: hdfs。
原因:spark-env.sh 里没设 HADOOP_CONF_DIR,Spark 拿不到 core-site.xml,默认认为文件系统是本地。另一种是 SPARK_MASTER_HOST 没设,Master 绑到了 127.0.0.1,Worker 连不上。
解决:确认 spark-env.sh 里三行都在——JAVA_HOME、HADOOP_CONF_DIR、SPARK_MASTER_HOST。改完分发到所有计算节点并重启/opt/spark/sbin/stop-all.sh再start-all.sh。验证方式是在 spark-shell 里执行spark.read.text("hdfs://node1:9000/input/wc.txt").count(),能返回数字说明配置已经生效。
6. 验收:跑通 spark-sql 查 OBS 上的数据才算装完
集群起来、进程都在,只能算装了一半。真正能交差的验收标准是:从对象存储读数据,用 SQL 查出来。
先确认前面几步的产物都在:
| 检查项 | 命令 | 期望结果 |
|---|---|---|
| HDFS 存活节点 | hdfs dfsadmin -report | Live datanodes 数量等于 workers 行数 |
| YARN 节点 | 浏览器打开 node1:8088 | Nodes 数量与 DataNode 一致 |
| Spark Worker | 浏览器打开 node1:8080 | 三个 Worker 状态 ALIVE |
| OBS 连通 | hadoop distcp hdfs://node1:9000/output obs://桶名/output | 无报错退出 |
| wordcount 结果 | hdfs dfs -cat /output/part-r-00000 | 三行词频 |
四项里任何一项不达标,先回对应章节补,不要往下走。
然后用 spark-sql 直接查桶里的数据。这一步把 Spark、Hadoop 配置、OBS 凭据三样绑在一起验证:
/opt/spark/bin/spark-sql --master spark://node1:7077 \ --conf spark.hadoop.fs.obs.access.key=你的AccessKeyId \ --conf spark.hadoop.fs.obs.secret.key=你的SecretAccessKey \ --conf spark.hadoop.fs.obs.endpoint=控制台Endpoint进去之后建外部表指向桶里的目录,注意分隔符要和 distcp 推上去的文件一致:
-- 外部表不搬数据,只登记路径,删表不会删桶里的文件 CREATE EXTERNAL TABLE wc_result (word STRING, cnt INT) ROW FORMAT DELIMITED FIELDS TERMINATED BY '\t' LOCATION 'obs://你的桶名/output'; SELECT * FROM wc_result ORDER BY cnt DESC LIMIT 5;能查出结果,这套环境就算真正跑通了:Spark 认得 Hadoop 的配置,Hadoop 认得 OBS 的凭据,桶里的数据和 HDFS 里的数据能被同一套 SQL 引擎读到。
最后补一个容易漏的点。上面这条命令用的是集群模式,如果换成--master local[*]本地跑,凭据要写在 spark-defaults.conf 里而不是命令行,否则 driver 和 executor 拿到的配置不一致,会出现「本地能查、提交到集群就 403」的玄学现象。我一般两种模式都跑一遍,确认行为一致再算验收完成。
从那以后我每次重装这套环境,都会严格按这个顺序走:先跑一遍 BatchMode 的 ssh 循环,再确认四个节点的 hosts 完全一致,然后才hdfs namenode -format,
本文还有配套的精品资源,点击获取