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 真实执行验证,命令回显均实测通过。

Apache ToreeApache Toree2026/10/15

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 特有的源修复。

  1. 具有 root 或 sudo 权限的 CentOS 8 系统。
  2. 可访问阿里云 vault 归档镜像(mirrors.aliyun.com/centos-vault/)与清华 PyPI 镜像。
  3. 可访问 Spark 发行包镜像(本文使用华为云镜像)与 Maven 中央仓库 %AddJar/%AddDeps 下载依赖时用。
  4. 至少 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 ToreeScala/SQLJVM 原生内核,经 spark-submit 启动sc/spark 变量直接可用,%AddJar/%AddDeps 动态加载,%%SQL 内置以 Scala 为主的交互式 Spark 开发
sparkmagicPython/PySpark通过 Livy REST 代理远端 Spark需额外部署 Livy;%%spark magic 远程执行团队共享远端集群、Python 技术栈
almondScala基于 coursier 的纯 Scala 内核不绑定 Spark;接 Spark 需自行装配 launcher纯 Scala 数据探索、轻量 notebook
pyspark 内核Pythonipykernel 包装 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 makecacheMetadata cache created.403/404 → 4.2 节源修复,确认 $releasever 已替换
java -version1.8.0_312版本不对 → alternatives --config java
pip3 --version21.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.0Kernel 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.jsonjupyter 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 已无官方源可恢复。

九、参考链接

  1. CentOS Vault 归档镜像(阿里云):https://mirrors.aliyun.com/centos-vault/
  2. Apache Toree 官方 Installation 文档:https://toree.apache.org/docs/current/user/installation
  3. PyPI apache-toree 包页:https://pypi.org/project/apache-toree/
  4. Spark 3.0.3 下载与 sha512:https://archive.apache.org/dist/spark/spark-3.0.3/
  5. Spark 华为云镜像:https://mirrors.huaweicloud.com/apache/spark/
  6. Toree 0.5.0-incubating 官方 bin 包(archive):https://archive.apache.org/dist/incubator/toree/0.5.0-incubating/toree/