Pyspark python package的测试
PySpark - Python Package Management
PySpark提供了一种将python环境剥离到镜像之外的一种方式,众所周知,在docker的优化方案中,减小镜像的体积能够节省资源、提高效率,这是一种“极大程度上”能够优化镜像的方式。
在这篇博文中,我主要使用conda打包python的方式测了一下在k8s集群上的client/cluster模式提交任务
环境准备
- k8s 集群
- NFS - PVC(需要结合k8s配置nfs pvc)
- 一个可提交spark任务的镜像
启动容器
- 用能够提交spark任务的镜像启动一个容器
- 进入容器,Do Something(可以在容器中提前用conda打包所需的python)
1. conda打包环境
- 安装conda
- 用conda安装所需python环境
# python=XXX, XXX代表指定python版本
conda create -y -n pyspark_conda_env -c conda-forge pyarrow pandas conda-pack python=XXX
conda activate pyspark_conda_env
conda pack -f -o pyspark_conda_env.tar.gz
2. 测试使用的代码:app.py
import pandas as pd
from pyspark.sql.functions import pandas_udf
from pyspark.sql import SparkSession
def main(spark):
df = spark.createDataFrame(
[(1, 1.0), (1, 2.0), (2, 3.0), (2, 5.0), (2, 10.0)],
("id", "v"))
@pandas_udf("double")
def mean_udf(v: pd.Series) -> float:
return v.mean()
print(df.groupby("id").agg(mean_udf(df['v'])).collect())
if __name__ == "__main__":
main(SparkSession.builder.getOrCreate())
client mode
运行命令
在client模式下,PYSPARK_DRIVER_PYTHON
和 PYSPARK_PYTHON
都要设置
PYSPARK_PYTHON
: 通过--archives
上传的pyspark_conda_env.tar.gz
在pod中解压之后的python路径PYSPARK_DRIVER_PYTHON
:pyspark_conda_env.tar.gz
在容器中解压之后的python路径- 由于
client
模式下,PYSPARK_DRIVER_PYTHON
指定的python路径只被driver
端使用,所以只需挂载到当前启动的容器中就行,不需要在其他节点也存在。
# 解压!
# root@icx-1:/ppml/trusted-big-data-ml# tar -zxvf pyspark_conda_env.tar.gz -C pyspark_conda_env
export PYSPARK_DRIVER_PYTHON=/ppml/trusted-big-data-ml/pyspark_conda_env/bin/python # Do not set in cluster modes.
export PYSPARK_PYTHON=./pyspark_conda_env/bin/python
# 提交Spark命令
${SPARK_HOME}/bin/spark-submit \
--conf spark.kubernetes.authenticate.driver.serviceAccountName=${RUNTIME_K8S_SERVICE_ACCOUNT} \
--deploy-mode client \
--conf spark.driver.host=${LOCAL_HOST} \
--master ${RUNTIME_SPARK_MASTER} \
--conf spark.kubernetes.executor.podTemplateFile=/ppml/trusted-big-data-ml/spark-executor-template.yaml \
--conf spark.kubernetes.container.image=${RUNTIME_K8S_SPARK_IMAGE} \
--conf spark.kubernetes.executor.deleteOnTermination=false \
--archives ./pyspark_conda_env.tar.gz#pyspark_conda_env \
local:///ppml/trusted-big-data-ml/app.py
执行分析
# hello
cluster mode
运行命令
在cluster模式下,只需要设置PYSPARK_PYTHON
PYSPARK_PYTHON
:pyspark_conda_env.tar.gz
解压到pod中的python路径- 通过conda打包的
pyspark_conda_env.tar.gz
,通过spark.kubernetes.file.upload.path
指定的共享文件系统传入到Driver
中
export PYSPARK_PYTHON=./pyspark_conda_env/bin/python
# 提交Spark命令
${SPARK_HOME}/bin/spark-submit \
--conf spark.kubernetes.authenticate.driver.serviceAccountName=${RUNTIME_K8S_SERVICE_ACCOUNT} \
--deploy-mode cluster \
--master ${RUNTIME_SPARK_MASTER} \
--conf spark.kubernetes.executor.podTemplateFile=/ppml/trusted-big-data-ml/spark-executor-template.yaml \
--conf spark.kubernetes.driver.podTemplateFile=/ppml/trusted-big-data-ml/spark-driver-template.yaml \
--conf spark.kubernetes.container.image=${RUNTIME_K8S_SPARK_IMAGE} \
--conf spark.kubernetes.executor.deleteOnTermination=false \
--conf spark.kubernetes.file.upload.path=/ppml/trusted-big-data-ml/work/data/shaojie \
--archives ./pyspark_conda_env.tar.gz#pyspark_conda_env \
local:///ppml/trusted-big-data-ml/work/data/shaojie/app.py
通过跑cluster
模式的任务,趁机来看一下spark.kubernetes.file.upload.path
的作用。在这里,--archives
意为通过指定逗号分割的tar
,jar
,zip
等一系列依赖包,将会被解压到executor
中
执行分析
22-07-29 02:05:58 INFO SparkContext:57 - Added archive file:/ppml/trusted-big-data-ml/work/data/shaojie/spark-upload-06550aaa-76f6-4f6e-a123-d34c71dbce5c/pyspark_conda_env.tar.gz#pyspark_conda_env at spark://app-py-36a4238247b3d72e-driver-svc.default.svc:7078/files/pyspark_conda_env.tar.gz with timestamp 1659060357319
22-07-29 02:05:58 INFO Utils:57 - Copying /ppml/trusted-big-data-ml/work/data/shaojie/spark-upload-06550aaa-76f6-4f6e-a123-d34c71dbce5c/pyspark_conda_env.tar.gz to /tmp/spark-6c702f67-0531-49f8-9656-48d4e110eea1/pyspark_conda_env.tar.gz
INFO fork chmod is forbidden !!!/tmp/spark-6c702f67-0531-49f8-9656-48d4e110eea1/pyspark_conda_env.tar.gz
22-07-29 02:05:58 INFO SparkContext:57 - Unpacking an archive file:/ppml/trusted-big-data-ml/work/data/shaojie/spark-upload-06550aaa-76f6-4f6e-a123-d34c71dbce5c/pyspark_conda_env.tar.gz#pyspark_conda_env from /tmp/spark-6c702f67-0531-49f8-9656-48d4e110eea1/pyspark_conda_env.tar.gz to /var/data/spark-3024b9ad-8e4d-4b2a-b51a-aee8f54d5a46/spark-8acb95d2-599d-4e2f-8203-c1f3455c4c7f/userFiles-994a18bf-12cd-4d98-b3e9-1035f741fe67/pyspark_conda_en
SparkContext
先索取spark.kubernetes.file.upload.path
路径中所有被上传的archives
包,添加到driver
中。[spark.kubernetes.file.upload.path
所指定的路径一定要是可被共享访问的文件系统: HDFS, NFS等]- 拷贝共享路径中的包到Driver中的路径
- 解压Driver中拷贝过来的
archives
包到指定位置
questions
- client去提交
archives
的时候,不需要指定spark.kubernetes.file.upload.path
的嘛? - cluster提交的
archives
主要是给启动的driver
使用? spark.kubernetes.file.upload.path
文档上认为这个配置的值应该是一个远程存储