CentOS 8 安装 Apache Toree 指南
在 CentOS 8 上从零安装 Apache Toree 0.5.0-incubating,覆盖 EOL 后 vault 镜像源修复、pip 升级、el8 显式 JAVA_HOME 实测、JDK 8 与 Spark 3.0.3 配对、内核注册与 notebook 真实执行验证,命令回显均实测通过。
CentOS 8 安装 Apache Toree 指南
目标:在 CentOS 8 上从零搭建 Apache Toree 0.5.0-incubating 的 Jupyter 内核环境(JDK 8 + Spark 3.0.3 + Jupyter),解决 EOL 软件源失效、pip 版本过老、el8 下 JAVA_HOME 缺省为空三个高频问题,并完成内核注册与 notebook 真实执行验证。本文全部命令与回显均已在 CentOS 8 实测通过。
CentOS 8 已于 2021 年底停止维护,官方 mirror.centos.org 源已下线(返回 403/404),安装 Toree 之前必须先把 yum 源切到 vault 归档镜像;同时 CentOS 8 自带的 Python 3.6 与 pip 9.0.3 过老,无法直接解析 Jupyter 新依赖,需要先升级 pip。本文按「修源 → 装 JDK/pip → 装 Spark → 注册内核 → 执行验证」的顺序给出全流程。
一、环境信息
本节先固定可复现的基线环境,后续所有命令均在此环境执行。
- 操作系统:CentOS Linux 8(镜像版本 8.4.2105,软件源切换到 8.5.2111 vault)
- 架构:x86_64
- Python:3.6.8(系统自带 python3,pip 升级到 21.3.1)
- JDK:OpenJDK 1.8.0_312(yum 包
java-1.8.0-openjdk-devel) - Spark:spark-3.0.3-bin-hadoop2.7(安装到
/usr/local/spark) - Jupyter:jupyter_core 4.9.2、notebook 6.4.10、nbconvert 6.0.7(pip 自动解析的 Python 3.6 兼容版本)
- 组件版本:apache-toree 0.5.0(内核 jar 为 toree-assembly-0.5.0-incubating.jar)
- 验证用工作目录:
/root/toree-test
系统与组件确认(实时回显):
head -2 /etc/os-release && uname -m && python3 --version
NAME="CentOS Linux"
VERSION="8"
x86_64
Python 3.6.8
💡 说明:与 Ubuntu 22.04 上的同版本安装(第 1 篇)相比,CentOS 8 的差异集中在三处:yum 源、pip 版本、JAVA_HOME。Toree 内核侧(0.5.0 + Spark 3.0.3 + JDK 8)的行为完全一致。
二、前置条件
本节说明安装前必须满足的条件,以及 CentOS 8 特有的源修复。
- 具有 root 或 sudo 权限的 CentOS 8 系统。
- 可访问阿里云 vault 归档镜像(
mirrors.aliyun.com/centos-vault/)与清华 PyPI 镜像。 - 可访问 Spark 发行包镜像(本文使用华为云镜像)与 Maven 中央仓库
%AddJar/%AddDeps下载依赖时用。 - 至少 4 GB 可用磁盘空间。
先验证官方源已失效、vault 镜像可用(实时回显):
curl -sI --max-time 15 http://mirror.centos.org/centos/8/BaseOS/x86_64/os/repodata/repomd.xml | head -1
curl -sI --max-time 15 http://mirrors.aliyun.com/centos-vault/8.5.2111/BaseOS/x86_64/os/repodata/repomd.xml | head -1
HTTP ERROR 403
HTTP/1.1 200 OK
验证点:mirror.centos.org 返回 403(EOL 已下线),阿里云 centos-vault 返回 200。vault 按「具体小版本目录」组织,本文镜像对应的 8.4.2105 与相邻的 8.5.2111 均可用,统一用 8.5.2111。
三、版本选型说明
本节给出 Toree 0.5.0 在 CentOS 8 上的三个配套选择结论,均经实测:
JDK 选 8:与 Ubuntu 侧结论一致(第 1 篇第三章),Toree 0.5.0 + Spark 3.0.3 在 JDK 17 下报 InaccessibleObjectException: ... does not "opens java.nio",在 Spark 2.4.x(Scala 2.11 构建)下报 NoSuchMethodError: 'void scala.App.$init$(scala.App)';JDK 8 全链路可用。CentOS 8 的 AppStream 仓库提供 java-1.8.0-openjdk-devel,直接 yum 安装。
Spark 选 3.0.3(Scala 2.12 构建):Toree 0.5.0 官方集成测试基线(仓库 v0.5.0 标签镜像使用 Spark 3.0.3 + OpenJDK 8)。下载后核对 jars/spark-core_2.12-3.0.3.jar 存在。
pip 必须先升级:CentOS 8 自带 pip 9.0.3,解析 jupyter 依赖时大量 wheel 无法匹配,升级到 21.3.1(Python 3.6 支持的最后主线)后可正常安装,pip 自动解析出 Python 3.6 兼容的 Jupyter 组件组合(notebook 6.4.10 等)。
本文实际采用:apache-toree 0.5.0 + JDK 8(1.8.0_312)+ Spark 3.0.3 + pip 21.3.1。
💡 技术拓展:Jupyter 生态中「连接 Spark 的内核」不止 Apache Toree 一家,常见方案对比如下——
方案 语言 原理 特点 适用场景 Apache Toree Scala/SQL JVM 原生内核,经 spark-submit 启动 sc/spark变量直接可用,%AddJar/%AddDeps 动态加载,%%SQL 内置以 Scala 为主的交互式 Spark 开发 sparkmagic Python/PySpark 通过 Livy REST 代理远端 Spark 需额外部署 Livy;%%spark magic 远程执行 团队共享远端集群、Python 技术栈 almond Scala 基于 coursier 的纯 Scala 内核 不绑定 Spark;接 Spark 需自行装配 launcher 纯 Scala 数据探索、轻量 notebook pyspark 内核 Python ipykernel 包装 pyspark 启动器 无 magic 体系,靠 spark-submit 预配置 只用 PySpark 的简单场景 本文采用 Apache Toree,理由是 Scala + Spark 的开箱即用变量绑定与 SQL magic,且版本配对路径有官方测试基线可复现(Spark 3.0.3 + JDK 8)。
四、方案 A:pip 安装(推荐)
4.1 方案说明
方案 A 的链路是:修复 yum 源 → yum 安装 java-1.8.0-openjdk-devel 与 python3-pip → 升级 pip → pip3 install jupyter apache-toree → 下载解压 Spark 3.0.3 → jupyter toree install --spark_home=/usr/local/spark 注册内核 → nbconvert 执行验证。
4.2 修复 yum 源到 vault 归档镜像
CentOS 8 的 repo 文件使用 mirrorlist= 指向已下线的镜像服务,需要注释掉并改用 vault 的 baseurl。镜像内没有 8.4.2105 的别名,因此同时把 $releasever 固定为 8.5.2111:
sed -i -e 's|mirrorlist=|#mirrorlist=|g' \
-e 's|#baseurl=http://mirror.centos.org|baseurl=http://mirrors.aliyun.com/centos-vault|g' \
/etc/yum.repos.d/CentOS-Linux-*.repo
sed -i 's|\$releasever|8.5.2111|g' /etc/yum.repos.d/CentOS-Linux-*.repo
yum clean all && yum makecache
# 输出节选(实测末尾)
CentOS Linux 8.5.2111 - BaseOS 618 kB/s | 4.6 MB 00:07
CentOS Linux 8.5.2111 - Extras 27 kB/s | 10 kB 00:00
Metadata cache created.
验证点:yum makecache 能成功拉取 BaseOS/AppStream/Extras 三类元数据即源修复完成;若报 404,检查 sed 是否把 $releasever 全部替换(repo 文件里是字面 $releasever)。
4.3 安装 JDK 8 与 python3-pip
yum install -y java-1.8.0-openjdk-devel python3-pip which
# 输出节选(实测末尾)
xorg-x11-fonts-Type1-7.5-19.el8.noarch
Complete!
确认版本(实时回显):
java -version && pip3 --version && which java
openjdk version "1.8.0_312"
OpenJDK Runtime Environment (build 1.8.0_312-b07)
OpenJDK 64-Bit Server VM (build 25.312-b07, mixed mode)
pip 9.0.3 from /usr/lib/python3.6/site-packages (python 3.6)
/usr/bin/java
验证点:java -version 为 1.8.0_xxx;which java 返回 /usr/bin/java(由 alternatives 管理)。注意 JAVA_HOME 此时为空,这是 el8 的缺省状态,影响与处理见 4.7 节。
4.4 升级 pip
pip3 install --upgrade 'pip<22' -i https://pypi.tuna.tsinghua.edu.cn/simple
Installing collected packages: pip
Successfully installed pip-21.3.1
pip 21.3.1 from /usr/local/lib/python3.6/site-packages/pip (python 3.6)
说明:固定 pip<22 是因为 22.0 起官方不再支持 Python 3.6,清华源会自动匹配出 21.3.1。升级后 pip 位于 /usr/local/bin/pip3,优先于系统自带的 9.0.3。
4.5 安装 Jupyter 与 apache-toree
pip3 install jupyter apache-toree -i https://pypi.tuna.tsinghua.edu.cn/simple
# 输出节选(实测末尾)
Running setup.py install for apache-toree: finished with status 'done'
Successfully installed apache-toree-0.5.0 jupyter-1.1.1 jupyter-core-4.9.2 nbconvert-6.0.7 notebook-6.4.10 ...
确认安装结果:
pip3 show apache-toree | grep -E '^(Name|Version)'
jupyter --version | grep -E 'jupyter_core|notebook|nbconvert'
Name: apache-toree
Version: 0.5.0
jupyter_core : 4.9.2
nbconvert : 6.0.7
notebook : 6.4.10
验证点:pip 自动解析出 Python 3.6 兼容组合(notebook 6.4.10、nbconvert 6.0.7),版本比 Ubuntu 侧低但功能等价,nbconvert 执行与内核注册不受影响。
4.6 安装 Spark 3.0.3
cd /root && curl -sO --max-time 300 https://mirrors.huaweicloud.com/apache/spark/spark-3.0.3/spark-3.0.3-bin-hadoop2.7.tgz
echo "27082142c256feef390686e3bbd9a132b63e2b46681d2e2a7038c0b30c9c482ae46224c4a2c029ce0019e6c9b4ce1917018d2ff17b6723a9144595e73cef23df spark-3.0.3-bin-hadoop2.7.tgz" | sha512sum -c -
mkdir -p /usr/local/spark
tar xzf spark-3.0.3-bin-hadoop2.7.tgz -C /usr/local/spark --strip-components=1
ls /usr/local/spark/jars/ | grep -E 'spark-core|scala-library'
spark-3.0.3-bin-hadoop2.7.tgz: OK
scala-library-2.12.10.jar
spark-core_2.12-3.0.3.jar
验证点:sha512 与官方归档值一致;jars 下出现 spark-core_2.12-3.0.3.jar(Scala 2.12 构建)。
4.7 设置 JAVA_HOME(el8 关键差异)
CentOS 8 默认不导出 JAVA_HOME(实测 echo $JAVA_HOME 为空)。交互式会话中 spark-submit 能通过 PATH 里的 /usr/bin/java(alternatives 指向)找到 JDK,内核可以正常启动;但 systemd 服务、cron 等非登录环境下 PATH 通常不含 java,spark-submit 会因找不到 JDK 启动失败。el8 的稳妥做法是显式导出 JAVA_HOME,写入 /etc/profile.d/ 使所有会话生效:
echo $JAVA_HOME
cat > /etc/profile.d/jdk8.sh <<'EOF'
export JAVA_HOME=/usr/lib/jvm/java-1.8.0-openjdk
export PATH=$JAVA_HOME/bin:$PATH
EOF
source /etc/profile.d/jdk8.sh
echo "JAVA_HOME=$JAVA_HOME"
JAVA_HOME=/usr/lib/jvm/java-1.8.0-openjdk
用「剥离 PATH 中 java 后再显式指定 JAVA_HOME」的方式验证其必要性(模拟受限环境,实时回显):
env PATH=/usr/local/sbin:/usr/sbin:/sbin:/bin JAVA_HOME=/usr/lib/jvm/java-1.8.0-openjdk \
/usr/local/spark/bin/spark-submit --version 2>&1 | grep -m1 version
/___/ .__/\_,_/_/ /_/\_\ version 3.0.3
验证点:在无 java 的受限 PATH 下,显式 JAVA_HOME 后 spark-submit 正常输出版本 3.0.3;不设 JAVA_HOME 时同样的受限环境会因找不到 java 而失败。
4.8 注册 Toree 内核
jupyter toree install --spark_home=/usr/local/spark
jupyter kernelspec list
[ToreeInstall] Creating kernel Scala
[ToreeInstall] Installed kernelspec apache_toree_scala in /usr/local/share/jupyter/kernels/apache_toree_scala
Available kernels:
apache_toree_scala /usr/local/share/jupyter/kernels/apache_toree_scala
python3 /usr/local/share/jupyter/kernels/python3
生成的 kernel.json(内容与 Ubuntu 侧一致):
python3 -m json.tool /usr/local/share/jupyter/kernels/apache_toree_scala/kernel.json
{
"argv": [
"/usr/local/share/jupyter/kernels/apache_toree_scala/bin/run.sh",
"--profile",
"{connection_file}"
],
"env": {
"DEFAULT_INTERPRETER": "Scala",
"__TOREE_SPARK_OPTS__": "",
"__TOREE_OPTS__": "",
"SPARK_HOME": "/usr/local/spark"
},
"display_name": "Apache Toree - Scala",
"language": "scala",
"interrupt_mode": "signal",
"metadata": {}
}
4.9 执行验证
生成 notebook 并真实执行(一个 Scala 单元格 + 一个 Spark RDD 单元格):
mkdir -p /root/toree-test && cd /root/toree-test && python3 - <<'EOF'
import json
def code(src): return {'cell_type':'code','execution_count':None,'metadata':{},'outputs':[],'source':src.splitlines(True)}
nb={'cells':[code('val s = "CentOS 8 Toree OK"\nprintln(s)\n1 + 1'),
code('val rdd = sc.parallelize(1 to 100)\nprintln("sum=" + rdd.sum())')],
'metadata':{'kernelspec':{'display_name':'Apache Toree - Scala','language':'scala','name':'apache_toree_scala'},'language_info':{'name':'scala'}},'nbformat':4,'nbformat_minor':5}
open('centos-test.ipynb','w').write(json.dumps(nb, indent=1))
print('written')
EOF
timeout 300 jupyter nbconvert --to notebook --execute --ExecutePreprocessor.timeout=240 centos-test.ipynb --output centos-test-out.ipynb
written
[NbConvertApp] Writing 2292 bytes to centos-test-out.ipynb
提取执行结果:
python3 -c "
import json
nb=json.load(open('/root/toree-test/centos-test-out.ipynb'))
for c in nb['cells']:
for o in c.get('outputs',[]):
t=o.get('output_type')
if 'text' in o: print('['+t+']', ''.join(o['text']).rstrip())
elif 'data' in o: print('['+t+']', {k: ''.join(v).rstrip() for k,v in o['data'].items()})
"
[stream] CentOS 8 Toree OK
[display_data] {'text/plain': 's = CentOS 8 Toree OK'}
[execute_result] {'text/plain': '2'}
[stream] sum=5050.0
结果解读:第二个单元格 sc.parallelize(1 to 100).sum() 返回 5050.0,说明内核经 spark-submit 真实启动了 Spark 3.0.3 的本地 SparkContext 并完成 RDD 计算,JDK 8 + Spark 3.0.3 + Toree 0.5.0 在 CentOS 8 全链路可用。日志中的 WARN KernelOutputStream: Suppressing empty output: '' 属正常行为。
4.10 验证清单
| 检查项 | 预期(实测值) | 不符时排查 |
|---|---|---|
yum makecache | Metadata cache created. | 403/404 → 4.2 节源修复,确认 $releasever 已替换 |
java -version | 1.8.0_312 | 版本不对 → alternatives --config java |
pip3 --version | 21.3.1 ... (python 3.6) | 仍为 9.0.3 → 4.4 节升级,检查 /usr/local/bin 在 PATH 前列 |
| `ls /usr/local/spark/jars/ | grep spark-core` | spark-core_2.12-3.0.3.jar |
jupyter kernelspec list | 出现 apache_toree_scala | 缺失 → 重跑 4.8 节 |
| nbconvert 执行 | sum=5050.0 | Kernel died before replying to kernel_info → 核对 JDK/Spark 配对与 JAVA_HOME |
五、方案对比与选择建议
CentOS 8 上另可行的方式是官方 bin 包 + 手工注册 kernelspec(不依赖 pip 的 apache-toree,仅依赖 jupyter_core/jupyter_client),完整步骤与 kernel.json 模板见第 1 篇《Ubuntu 22.04 安装 Apache Toree 指南》第五章,两者在 CentOS 8 上同样适用——bin 包与 pip 包内是同一个 toree-assembly-0.5.0-incubating.jar(sha512 一致,实测比对)。差异对比:
| 维度 | 方案 A:pip 安装 | 方案 B:bin 包 + 手工注册 |
|---|---|---|
| 依赖 | pip(需升级到 21.3.1) | 仅 jupyter_core/jupyter_client |
| 内核 jar 来源 | pip 包内捆绑 | 官方 bin 包/Maven Central |
| kernel.json | jupyter toree install 自动生成 | 手工编写(照抄模板改路径) |
| 适用场景 | 常规联网服务器(推荐) | 离线机器、受限环境 |
选型建议:CentOS 8 的 pip 生态偏老,若已在维护 pip 环境(有 /usr/local 的可控升级权限)用方案 A 最省事;若机器 pip 被运维锁定,用方案 B 绕开 apache-toree 的 pip 安装。
六、基础配置
SPARK_HOME 与 Spark/Toree 参数:与 Ubuntu 一致,通过 --spark_home/--spark_opts/--toree_opts 在注册时写入 kernel.json 的 env,改配置用 --replace 重新注册(详见第 1 篇第七章与第 5 篇)。
JAVA_HOME:el8 特有重点。交互会话可依赖 /usr/bin/java,但注册内核并不读取 JAVA_HOME(它写在 kernel.json 的 SPARK_HOME 里),内核启动链 run.sh → spark-submit 在受限环境下才依赖它。生产上把 Jupyter 以 systemd 服务运行时,务必在 unit 文件或 /etc/profile.d/jdk8.sh(4.7 节)中固定:
export JAVA_HOME=/usr/lib/jvm/java-1.8.0-openjdk
Firewall 与端口:单机本地模式(--master=local[*])下内核不监听外部端口,无需开放防火墙;若接独立 Spark 集群,按集群要求开放 driver 回连端口。
七、常见问题(FAQ)
Q1:yum makecache 报 Failed to download metadata for repo 'appstream' / HTTP ERROR 403?
官方 mirror.centos.org 已随 CentOS 8 EOL 下线。按 4.2 节把 mirrorlist= 全部注释、baseurl 指到 mirrors.aliyun.com/centos-vault/8.5.2111/,并把 repo 文件中的 $releasever 替换为具体小版本(vault 没有版本别名目录)。
Q2:pip3 install jupyter 长时间无响应或装出奇怪的旧版本组合?
CentOS 8 自带 pip 9.0.3 依赖解析能力弱,很多带环境标记的 wheel 匹配不上。先按 4.4 节把 pip 升到 21.3.1 再装;Python 3.6 下最终解析到 notebook 6.4.10/nbconvert 6.0.7 属正常,功能完整。
Q3:内核启动报 Kernel died before replying to kernel_info?
与 Ubuntu 侧同因:JDK 17 或 Spark 2.4.x(Scala 2.11)配对错误。CentOS 8 上还要先确认 JAVA_HOME(或 PATH 中的 java)指向 1.8:java -version;受限环境按 4.7 节显式导出 JAVA_HOME。手动复现定位:$SPARK_HOME/bin/spark-submit --class org.apache.toree.Main /usr/local/share/jupyter/kernels/apache_toree_scala/lib/toree-assembly-0.5.0-incubating.jar --spark-context-initialization-mode none。
Q4:jupyter: command not found?
pip 升级后 jupyter 安装在 /usr/local/bin/,确认该目录在 PATH 中(echo $PATH | grep -o '/usr/local/bin');或用 python3 -m jupyter_core.jupyter 等价调用入口排查安装位置(pip3 show -f jupyter-core | grep bin)。
Q5:%AddJar 下载依赖报证书或超时错误?
确认能访问 repo1.maven.org;内网环境可换公司 Nexus 镜像地址,或把 jar 提前下载到本地后用 %AddJar file:///path/to/xxx.jar 方式加载。
八、卸载与清理
移除内核、卸载 pip 包:
jupyter kernelspec remove apache_toree_scala -y
pip3 uninstall -y apache-toree
Kernel specs to remove:
apache_toree_scala /usr/local/share/jupyter/kernels/apache_toree_scala
Removed 1 kernelspecs
Successfully uninstalled apache-toree-0.5.0
清理 Spark、发行包与验证目录:
rm -rf /usr/local/spark /root/spark-3.0.3-bin-hadoop2.7.tgz /root/toree-test
ls /usr/local/spark 2>&1
ls: cannot access '/usr/local/spark': No such file or directory
卸载 JDK(先 -s 预演确认再真删):
yum remove -s java-1.8.0-openjdk-devel | tail -3
# 输出节选(实测)
Package java-1.8.0-openjdk-devel-1:1.8.0_312.b07-2.el8_5.x86_64 to be removed
Operation skipped: remove test mode
恢复 yum 源(如需回到官方 repo 文件)只能从同小版本的 vault 手工取回 repo 模板重放,CentOS 8 已无官方源可恢复。
九、参考链接
- CentOS Vault 归档镜像(阿里云):https://mirrors.aliyun.com/centos-vault/
- Apache Toree 官方 Installation 文档:https://toree.apache.org/docs/current/user/installation
- PyPI apache-toree 包页:https://pypi.org/project/apache-toree/
- Spark 3.0.3 下载与 sha512:https://archive.apache.org/dist/spark/spark-3.0.3/
- Spark 华为云镜像:https://mirrors.huaweicloud.com/apache/spark/
- Toree 0.5.0-incubating 官方 bin 包(archive):https://archive.apache.org/dist/incubator/toree/0.5.0-incubating/toree/