1

好吧,这很奇怪。我有一些我想在集群启动时运行的初始化脚本

集群有 init 脚本,它在一个文件中(在 dbfs 中)

基本上这个

dbfs:/databricks/init-scripts/custom-cert.sh

现在,当我像这样制作初始化脚本时,它可以工作(我的端点没有 ssl 错误。此外,集群的事件日志显示初始化脚本的持续时间为 1 秒

dbutils.fs.put("/databricks/init-scripts/custom-cert.sh", """#!/bin/bash
cp /dbfs/orgcertificates/orgcerts.crt /usr/local/share/ca-certificates/
sudo update-ca-certificates
echo "export REQUESTS_CA_BUNDLE=/etc/ssl/certs/ca-certificates.crt" >> /databricks/spark/conf/spark-env.sh
""")

但是,如果我只是将 init 脚本放在 bash 脚本中并通过管道将其上传到 DBFS,那么 init 脚本不会做任何事情。它根据事件日志执行,但执行持续时间为 0 秒。

我在一个名为的文件中有 sh 脚本

custom-cert.sh

内容同上,即

#!/bin/bash
cp /dbfs/orgcertificates/orgcerts.crt /usr/local/share/ca-certificates/
sudo update-ca-certificates
echo "export REQUESTS_CA_BUNDLE=/etc/ssl/certs/ca-certificates.crt"

但是当我检查 /usr/local/share/ca-certificates/ 时,它不包含 /dbfs/orgcertificates/orgcerts.crt,即使集群初始化脚本已经运行。

另外,我在两种情况下都比较了初始化脚本的内容,至少肉眼比较,我不知道有什么区别

IE

%sh
cat /dbfs/databricks/init-scripts/custom-cert.sh

在两个场景中显示相同的内容。第二种情况有什么问题?

编辑:我阅读了更多关于初始化脚本的内容,发现初始化脚本的日志写在这里

%sh
ls /databricks/init_scripts/

查看该位置的 err 文件,似乎有错误

sudo: update-ca-certificates
: command not found

为什么在第一种情况下会发现 update-ca-certificates 但当我将相同的脚本放在 sh 脚本中并将其上传到 dbfs 时(而不是在笔记本中执行 dbutils.fs.put)?

编辑2:响应第一个答案。运行命令后

dbutils.fs.put("/databricks/init-scripts/custom-cert.sh", """#!/bin/bash
cp /dbfs/orgcertificates/orgcerts.crt /usr/local/share/ca-certificates/
sudo update-ca-certificates
echo "export REQUESTS_CA_BUNDLE=/etc/ssl/certs/ca-certificates.crt" >> /databricks/spark/conf/spark-env.sh
""")

输出是文件 custom-cert.sh,然后我使用初始化脚本位置作为 dbfs:/databricks/init-scripts/custom-cert.sh 重新启动集群,然后它就可以工作了。因此,它本质上与 init 脚本正在读取的内容相同(即生成的 sh 脚本)。如果我不使用 dbfs put 而是将内容放入 bash 文件并在 CI/CD 过程中上传,为什么它无法读取?

4

2 回答 2

1

我们知道,init 脚本是一个 shell 脚本,它在 Apache Spark 驱动程序或工作 JVM 启动之前在每个集群节点启动期间运行。case-2当您使用%sh魔术命令运行 bash 命令时,意味着您正在尝试在本地驱动程序节点中执行此命令。这样worker节点就无法访问了。但是基于 case-1,通过使用魔法命令,您正在尝试从 root%fs运行复制命令 ( )。dbutils.fs.put这样除了驱动节点,其他工作节点也可以访问路径。

参考:https ://docs.databricks.com/data/databricks-file-system.html#summary-table-and-diagram

于 2021-09-28T01:24:10.050 回答
0

看来我在问题的评论部分所做的观察是要走的路。

我现在使用我在 Azure DevOps 的 CI/CD 管道期间运行的数据块作业创建初始化脚本。

笔记本有命令

dbutils.fs.rm("/databricks/init-scripts/custom-cert.sh")
dbutils.fs.put("/databricks/init-scripts/custom-cert.sh", """#!/bin/bash
cp /dbfs/internal-certificates/certs.crt /usr/local/share/ca-certificates/
sudo update-ca-certificates
echo "export REQUESTS_CA_BUNDLE=/etc/ssl/certs/ca-certificates.crt" >> /databricks/spark/conf/spark-env.sh
""")

然后我创建了一个 Databricks 作业(指向这个笔记本),该集群是一个临时的作业集群。当然,在我的情况下,即使是这个作业创建也是使用 powershell 脚本自动完成的。

然后,我再次使用 Powershell 脚本在发布管道中调用此 Databricks 作业。

这将创建文件

/databricks/init-scripts/custom-cert.sh

然后,我在访问我的组织端点的任何其他集群中使用此文件(没有证书错误)。

我不知道(或仍然理解),为什么同一个脚本文件不能只是回购的一部分并在发布过程中上传(而不是这个 Databricks 作业调用笔记本)。我很想知道原因。正如您所看到的,关于这个问题的另一个答案并不成立,集群脚本是由作业集群创建的,然后作为其初始化脚本的一部分从另一个集群访问。

它简单地归结为如何创建初始化脚本。

但我完成了我的工作。只要它也可以帮助某人完成工作。我提出了一个支持案例以了解原因。

于 2021-09-29T14:16:25.450 回答