web-dev-qa-db-ja.com

インストールする最も簡単な方法Python依存関係Spark executorノード?

Python Sparkプログラムで依存関係として個々のファイルを送信できることを理解しています。しかし、本格的なライブラリ(numpyなど)はどうですか?

Sparkには、提供されたパッケージマネージャー(pipなど)を使用してライブラリの依存関係をインストールする方法がありますか?または、Sparkプログラムの前に手動で行う必要があります。処刑?

答えが手動の場合、多数の分散ノードでライブラリ(インストールパス、バージョンなど)を同期するための「ベストプラクティス」アプローチは何ですか?

22
trianta2

実際に実際に試してみたところ、コメントとして投稿したリンクは、依存関係で望んでいることを正確に実行していないと思います。あなたがかなり合理的に求めているのは、Sparkに依存関係のインストールに関してsetuptoolsとpipをうまく機能させる方法です。これはSparkではサポートされないのではないかと私は思います。サードパーティの依存関係の問題は、汎用のPythonで大部分解決されていますが、Sparkでは、手動の依存関係管理などに戻ることが前提となっているようです。

私は virtualenv に基づいて不完全ではあるが機能的なパイプラインを使用しています。基本的な考え方は

  1. Sparkノード専用のvirtualenvを作成する
  2. Sparkジョブを実行するたびに、社内のすべてのPythonライブラリの新しいpip installを実行します。これらをsetuptoolsで設定している場合は、依存関係がインストールされます
  3. Virtualenvのサイトパッケージディレクトリを圧縮します。これには、ワーカーノードに必要なライブラリとその依存関係が含まれますが、すでに持っている標準のPythonライブラリは含まれません。
  4. ライブラリとその依存関係を含む単一の.Zipファイルを--py-filesへの引数として渡します

もちろん、このプロセスを管理するためにいくつかのヘルパースクリプトをコーディングする必要があります。以下は、私が使用しているものから適応させたヘルパースクリプトです。

#!/usr/bin/env bash
# helper script to fulfil Spark's python packaging requirements.
# Installs everything in a designated virtualenv, then zips up the virtualenv for using as an the value of
# supplied to --py-files argument of `pyspark` or `spark-submit`
# First argument should be the top-level virtualenv
# Second argument is the zipfile which will be created, and
#   which you can subsequently supply as the --py-files argument to 
#   spark-submit
# Subsequent arguments are all the private packages you wish to install
# If these are set up with setuptools, their dependencies will be installed

VENV=$1; shift
ZIPFILE=$1; shift
PACKAGES=$*

. $VENV/bin/activate
for pkg in $PACKAGES; do
  pip install --upgrade $pkg
done
TMPZIP="$TMPDIR/$RANDOM.Zip" # abs path. Use random number to avoid clashes with other processes
( cd "$VENV/lib/python2.7/site-packages" && Zip -q -r $TMPZIP . )
mv $TMPZIP $ZIPFILE

sparkジョブを送信するために実行する他の単純なラッパースクリプトのコレクションがあります。最初にこのスクリプトをそのプロセスの一部として呼び出し、spark-submitを実行するときに2番目の引数(Zipファイルの名前)が--py-files引数として渡されることを確認します(コメントに記載されています) )。私は常にこれらのスクリプトを実行するので、誤って古いコードを実行してしまうことはありません。 Sparkオーバーヘッドと比較して、小規模プロジェクトの場合、パッケージ化オーバーヘッドは最小限です。

可能な改善はたくさんあります。たとえば、新しいZipファイルをいつ作成するかを賢く考えたり、2つのZipファイルに分割したりします。1つは頻繁に変更されるプライベートパッケージを含み、もう1つはほとんど変更しない依存関係を含みます。頻繁に再構築されます。 Zipを再構築する前に、ファイルの変更を確認する方が賢明です。また、引数の有効性をチェックすることは良い考えです。しかし、今のところ、私の目的にはこれで十分です。

私が思いついたソリューションは、特にNumPyのような大規模な依存関係用には設計されていません(ただし、それらには有効です)。また、Cベースの拡張機能を構築していて、ドライバーノードのアーキテクチャーがクラスターノードとは異なる場合も機能しません。

すでにNumPy(および 他の多くのパッケージ )が含まれているため、すべてのノードで Anaconda のようなPythonディストリビューションを実行するための推奨事項を他の場所で確認しました。これは、NumPyだけでなく他のCベースの拡張機能を実行するためのより良い方法かもしれません。いずれにしても、Anacondaに必要なPyPIパッケージが適切なバージョンであると常に期待できるわけではありません。さらに、Spark環境を制御してAnacondaを配置できない可能性があるため、このvirtualenvベースのアプローチはまだ役に立ちます。

20
Andy MacKinlay