خوانندگان عزیز، ظهر بخیر. امروز کمی در مورد آپاچی اسپارک و چشم انداز توسعه آن صحبت خواهیم کرد.
در دنیای مدرن بیگ دیتا، آپاچی اسپارک استاندارد واقعی برای توسعه وظایف پردازش دسته ای داده است. علاوه بر این، از آن برای ایجاد برنامههای پخش جریانی استفاده میشود که در مفهوم میکرو دستهای، پردازش و ارسال دادهها در بخشهای کوچک (جریانسازی ساختار یافته جرقه) کار میکنند. و به طور سنتی بخشی از پشته کلی Hadoop بوده و از YARN (یا در برخی موارد Apache Mesos) به عنوان مدیر منابع استفاده میکند. تا سال 2020، استفاده از آن به شکل سنتی آن برای اکثر شرکت ها به دلیل عدم توزیع مناسب Hadoop زیر سوال می رود - توسعه HDP و CDH متوقف شده است، CDH به خوبی توسعه نیافته و هزینه بالایی دارد، و بقیه تامین کنندگان Hadoop یا دیگر وجود ندارد یا آینده ای مبهم خواهد داشت. بنابراین، راهاندازی آپاچی اسپارک با استفاده از Kubernetes مورد توجه جامعه و شرکتهای بزرگ است - تبدیل شدن به استانداردی در ارکستراسیون کانتینر و مدیریت منابع در ابرهای خصوصی و عمومی، مشکل زمانبندی منابع نامناسب وظایف Spark در YARN را حل میکند و ارائه میکند. یک پلت فرم به طور پیوسته در حال توسعه با بسیاری از توزیع های تجاری و باز برای شرکت ها در هر اندازه و راه راه. علاوه بر این، در پی محبوبیت، بسیاری از آنها قبلاً موفق شده اند چندین نصب را از خود به دست آورند و تخصص خود را در استفاده از آن افزایش داده اند، که این حرکت را ساده می کند.
با شروع نسخه 2.3.0، Apache Spark پشتیبانی رسمی برای اجرای وظایف در یک خوشه Kubernetes به دست آورد و امروز، ما در مورد بلوغ فعلی این رویکرد، گزینه های مختلف برای استفاده از آن و مشکلاتی که در حین پیاده سازی با آن مواجه می شوند صحبت خواهیم کرد.
اول از همه، بیایید به روند توسعه وظایف و برنامه های کاربردی بر اساس Apache Spark نگاهی بیندازیم و موارد معمولی را که در آن شما نیاز به اجرای یک کار در یک کلاستر Kubernetes دارید را برجسته کنید. در تهیه این پست از OpenShift به عنوان توزیع استفاده می شود و دستورات مربوط به ابزار خط فرمان (oc) آن داده می شود. برای سایر توزیعهای Kubernetes، میتوان از دستورات مربوطه از ابزار خط فرمان استاندارد Kubernetes (kubectl) یا آنالوگهای آنها (مثلاً برای oc adm policy) استفاده کرد.
اولین مورد استفاده - spark-submit
در طول توسعه وظایف و برنامه های کاربردی، توسعه دهنده نیاز به اجرای وظایف برای اشکال زدایی تبدیل داده ها دارد. از نظر تئوری، خردهها را میتوان برای این اهداف استفاده کرد، اما توسعه با مشارکت نمونههای واقعی (البته آزمایشی) سیستمهای نهایی ثابت کرده است که در این دسته از وظایف سریعتر و بهتر است. در موردی که ما در نمونه های واقعی سیستم های پایانی اشکال زدایی می کنیم، دو سناریو ممکن است:
توسعه دهنده یک وظیفه Spark را به صورت محلی در حالت مستقل اجرا می کند.
یک توسعه دهنده یک کار Spark را در یک خوشه Kubernetes در یک حلقه آزمایشی اجرا می کند.
گزینه اول حق وجود دارد، اما دارای تعدادی معایب است:
هر توسعه دهنده باید از محل کار به تمام نمونه های سیستم های نهایی مورد نیاز خود دسترسی داشته باشد.
برای اجرای وظیفه در حال توسعه به مقدار کافی منابع روی ماشین کار مورد نیاز است.
گزینه دوم این معایب را ندارد، زیرا استفاده از یک خوشه Kubernetes به شما این امکان را می دهد که منابع لازم را برای وظایف در حال اجرا اختصاص دهید و دسترسی لازم به نمونه های سیستم نهایی را برای آن فراهم کنید، و با استفاده از مدل نقش Kubernetes به طور انعطاف پذیر دسترسی به آن را فراهم کنید. همه اعضای تیم توسعه بیایید آن را به عنوان اولین مورد استفاده برجسته کنیم - راه اندازی وظایف Spark از یک ماشین توسعه دهنده محلی در یک خوشه Kubernetes در یک حلقه آزمایشی.
بیایید در مورد فرآیند راه اندازی Spark برای اجرای محلی بیشتر صحبت کنیم. برای شروع استفاده از Spark باید آن را نصب کنید:
mkdir /opt/spark
cd /opt/spark
wget http://mirror.linux-ia64.org/apache/spark/spark-2.4.5/spark-2.4.5.tgz
tar zxvf spark-2.4.5.tgz
rm -f spark-2.4.5.tgz
ما بسته های لازم برای کار با Kubernetes را جمع آوری می کنیم:
cd spark-2.4.5/
./build/mvn -Pkubernetes -DskipTests clean package
یک ساخت کامل زمان زیادی می برد و برای ایجاد تصاویر Docker و اجرای آنها در یک خوشه Kubernetes، شما واقعاً فقط به فایل های jar از دایرکتوری "assembly/" نیاز دارید، بنابراین فقط می توانید این زیر پروژه را بسازید:
برای اجرای Spark Jobs در Kubernetes، باید یک تصویر Docker ایجاد کنید تا از آن به عنوان تصویر پایه استفاده کنید. در اینجا 2 رویکرد ممکن وجود دارد:
تصویر Docker تولید شده شامل کد اجرایی Spark وظیفه است.
تصویر ایجاد شده فقط شامل Spark و وابستگی های لازم است، کد اجرایی از راه دور میزبانی می شود (مثلاً در HDFS).
ابتدا بیایید یک تصویر Docker بسازیم که شامل یک نمونه آزمایشی از یک کار Spark است. برای ایجاد تصاویر Docker، Spark ابزاری به نام "docker-image-tool" دارد. بیایید کمک در مورد آن را مطالعه کنیم:
./bin/docker-image-tool.sh --help
با کمک آن می توانید تصاویر Docker ایجاد کرده و آنها را در رجیستری های راه دور آپلود کنید، اما به طور پیش فرض دارای تعدادی معایب است:
بدون شکست، 3 تصویر Docker را به طور همزمان ایجاد می کند - برای Spark، PySpark و R.
به شما اجازه نمی دهد نام تصویر را مشخص کنید.
بنابراین، ما از نسخه اصلاح شده این ابزار استفاده خواهیم کرد که در زیر آمده است:
vi bin/docker-image-tool-upd.sh
#!/usr/bin/env bash
function error {
echo "$@" 1>&2
exit 1
}
if [ -z "${SPARK_HOME}" ]; then
SPARK_HOME="$(cd "`dirname "$0"`"/..; pwd)"
fi
. "${SPARK_HOME}/bin/load-spark-env.sh"
function image_ref {
local image="$1"
local add_repo="${2:-1}"
if [ $add_repo = 1 ] && [ -n "$REPO" ]; then
image="$REPO/$image"
fi
if [ -n "$TAG" ]; then
image="$image:$TAG"
fi
echo "$image"
}
function build {
local BUILD_ARGS
local IMG_PATH
if [ ! -f "$SPARK_HOME/RELEASE" ]; then
IMG_PATH=$BASEDOCKERFILE
BUILD_ARGS=(
${BUILD_PARAMS}
--build-arg
img_path=$IMG_PATH
--build-arg
datagram_jars=datagram/runtimelibs
--build-arg
spark_jars=assembly/target/scala-$SPARK_SCALA_VERSION/jars
)
else
IMG_PATH="kubernetes/dockerfiles"
BUILD_ARGS=(${BUILD_PARAMS})
fi
if [ -z "$IMG_PATH" ]; then
error "Cannot find docker image. This script must be run from a runnable distribution of Apache Spark."
fi
if [ -z "$IMAGE_REF" ]; then
error "Cannot find docker image reference. Please add -i arg."
fi
local BINDING_BUILD_ARGS=(
${BUILD_PARAMS}
--build-arg
base_img=$(image_ref $IMAGE_REF)
)
local BASEDOCKERFILE=${BASEDOCKERFILE:-"$IMG_PATH/spark/docker/Dockerfile"}
docker build $NOCACHEARG "${BUILD_ARGS[@]}"
-t $(image_ref $IMAGE_REF)
-f "$BASEDOCKERFILE" .
}
function push {
docker push "$(image_ref $IMAGE_REF)"
}
function usage {
cat <<EOF
Usage: $0 [options] [command]
Builds or pushes the built-in Spark Docker image.
Commands:
build Build image. Requires a repository address to be provided if the image will be
pushed to a different registry.
push Push a pre-built image to a registry. Requires a repository address to be provided.
Options:
-f file Dockerfile to build for JVM based Jobs. By default builds the Dockerfile shipped with Spark.
-p file Dockerfile to build for PySpark Jobs. Builds Python dependencies and ships with Spark.
-R file Dockerfile to build for SparkR Jobs. Builds R dependencies and ships with Spark.
-r repo Repository address.
-i name Image name to apply to the built image, or to identify the image to be pushed.
-t tag Tag to apply to the built image, or to identify the image to be pushed.
-m Use minikube's Docker daemon.
-n Build docker image with --no-cache
-b arg Build arg to build or push the image. For multiple build args, this option needs to
be used separately for each build arg.
Using minikube when building images will do so directly into minikube's Docker daemon.
There is no need to push the images into minikube in that case, they'll be automatically
available when running applications inside the minikube cluster.
Check the following documentation for more information on using the minikube Docker daemon:
https://kubernetes.io/docs/getting-started-guides/minikube/#reusing-the-docker-daemon
Examples:
- Build image in minikube with tag "testing"
$0 -m -t testing build
- Build and push image with tag "v2.3.0" to docker.io/myrepo
$0 -r docker.io/myrepo -t v2.3.0 build
$0 -r docker.io/myrepo -t v2.3.0 push
EOF
}
if [[ "$@" = *--help ]] || [[ "$@" = *-h ]]; then
usage
exit 0
fi
REPO=
TAG=
BASEDOCKERFILE=
NOCACHEARG=
BUILD_PARAMS=
IMAGE_REF=
while getopts f:mr:t:nb:i: option
do
case "${option}"
in
f) BASEDOCKERFILE=${OPTARG};;
r) REPO=${OPTARG};;
t) TAG=${OPTARG};;
n) NOCACHEARG="--no-cache";;
i) IMAGE_REF=${OPTARG};;
b) BUILD_PARAMS=${BUILD_PARAMS}" --build-arg "${OPTARG};;
esac
done
case "${@: -1}" in
build)
build
;;
push)
if [ -z "$REPO" ]; then
usage
exit 1
fi
push
;;
*)
usage
exit 1
;;
esac
با کمک آن، ما یک تصویر اولیه Spark حاوی یک کار آزمایشی برای محاسبه Pi با استفاده از Spark جمع آوری می کنیم (در اینجا {docker-registry-url} URL رجیستری تصویر Docker شما است، {repo} نام مخزن داخل رجیستری است، که با پروژه در OpenShift مطابقت دارد، {image-name} - نام تصویر (اگر از جداسازی سه سطحی تصاویر استفاده شود، برای مثال، مانند رجیستری یکپارچه تصاویر Red Hat OpenShift)، {tag} - برچسب این نسخه تصویر):
بیایید بررسی کنیم که تصویر مونتاژ شده در OKD موجود است. برای انجام این کار، URL را در مرورگر با لیستی از تصاویر پروژه مربوطه باز کنید (در اینجا {project} نام پروژه در داخل خوشه OpenShift است، {OKD-WEBUI-URL} نشانی اینترنتی کنسول وب OpenShift است. ) - https://{OKD-WEBUI-URL}/console /project/{project}/browse/images/{image-name}.
برای اجرای وظایف، باید یک حساب سرویس با امتیازات اجرای پادها به صورت روت ایجاد شود (این نکته را بعداً مورد بحث قرار خواهیم داد):
- نام - نام وظیفه ای که در شکل گیری نام غلاف های Kubernetes شرکت می کند.
—class — کلاس فایل اجرایی که هنگام شروع کار فراخوانی می شود.
—conf — پارامترهای پیکربندی Spark.
spark.executor.instances - تعداد اجراکنندگان Spark برای راهاندازی.
spark.kubernetes.authenticate.driver.serviceAccountName - نام حساب سرویس Kubernetes که هنگام راهاندازی پادها استفاده میشود (برای تعریف زمینه و قابلیتهای امنیتی هنگام تعامل با Kubernetes API).
spark.kubernetes.namespace - فضای نام Kubernetes که در آن پادهای درایور و اجرا کننده راه اندازی می شوند.
spark.submit.deployMode - روش راهاندازی Spark (برای Spark-submit استاندارد از "cluster" استفاده میشود، برای Spark Operator و نسخههای بعدی Spark "client").
spark.kubernetes.container.image - تصویر داکر که برای راه اندازی غلاف ها استفاده می شود.
spark.master — URL API Kubernetes (خارجی مشخص شده است تا دسترسی از دستگاه محلی انجام شود).
local:// مسیری است که به Spark قابل اجرا در داخل تصویر داکر می رسد.
ما به پروژه OKD مربوطه می رویم و پادهای ایجاد شده را مطالعه می کنیم - https://{OKD-WEBUI-URL}/console/project/{project}/browse/pods.
برای سادهتر کردن فرآیند توسعه، میتوان از گزینه دیگری استفاده کرد که در آن یک تصویر پایه مشترک از Spark ایجاد میشود که توسط همه وظایف برای اجرا استفاده میشود و عکسهای فوری فایلهای اجرایی در حافظه خارجی (مثلا Hadoop) منتشر میشوند و هنگام فراخوانی مشخص میشوند. spark-submit به عنوان لینک. در این حالت، میتوانید نسخههای مختلف وظایف Spark را بدون بازسازی تصاویر Docker اجرا کنید، مثلاً از WebHDFS برای انتشار تصاویر استفاده کنید. ما درخواستی برای ایجاد فایل ارسال می کنیم (در اینجا {host} میزبان سرویس WebHDFS است، {port} پورت سرویس WebHDFS است، {path-to-file-on-hdfs} مسیر مورد نظر برای فایل است. در HDFS):
curl -i -X PUT "http://{host}:{port}/webhdfs/v1/{path-to-file-on-hdfs}?op=CREATE
شما پاسخی مانند این دریافت خواهید کرد (در اینجا {location} آدرس اینترنتی است که باید برای دانلود فایل استفاده شود):
فایل اجرایی Spark را در HDFS بارگیری کنید (در اینجا {path-to-local-file} مسیر فایل اجرایی Spark در میزبان فعلی است):
curl -i -X PUT -T {path-to-local-file} "{location}"
پس از این، میتوانیم spark-submit را با استفاده از فایل Spark آپلود شده در HDFS انجام دهیم (در اینجا {class-name} نام کلاسی است که برای تکمیل کار باید راهاندازی شود):
لازم به ذکر است که برای دسترسی به HDFS و اطمینان از کارکرد کار، ممکن است لازم باشد Dockerfile و اسکریپت enterpoint.sh را تغییر دهید - یک دستورالعمل به Dockerfile اضافه کنید تا کتابخانه های وابسته را در پوشه /opt/spark/jars کپی کنید. فایل پیکربندی HDFS را در SPARK_CLASSPATH در نقطه ورودی قرار دهید.
مورد استفاده دوم - آپاچی لیوی
علاوه بر این، هنگامی که یک کار توسعه می یابد و نتیجه نیاز به آزمایش دارد، این سوال مطرح می شود که آن را به عنوان بخشی از فرآیند CI/CD راه اندازی کنید و وضعیت اجرای آن را ردیابی کنید. البته، میتوانید آن را با استفاده از یک تماس محلی spark-submit اجرا کنید، اما این زیرساخت CI/CD را پیچیده میکند، زیرا نیاز به نصب و پیکربندی Spark روی عوامل/رانرهای سرور CI و راهاندازی دسترسی به Kubernetes API دارد. برای این مورد، پیادهسازی هدف استفاده از Apache Livy را بهعنوان یک API REST برای اجرای وظایف Spark که در داخل یک خوشه Kubernetes میزبانی میشوند، انتخاب کرده است. با کمک آن میتوانید وظایف Spark را روی یک خوشه Kubernetes با استفاده از درخواستهای cURL معمولی اجرا کنید که به راحتی بر اساس هر راهحل CI پیادهسازی میشود و قرار دادن آن در داخل خوشه Kubernetes مشکل احراز هویت را هنگام تعامل با Kubernetes API حل میکند.
بیایید آن را به عنوان مورد دوم برجسته کنیم - اجرای وظایف Spark به عنوان بخشی از فرآیند CI/CD در یک خوشه Kubernetes در یک حلقه آزمایشی.
کمی در مورد Apache Livy - به عنوان یک سرور HTTP کار می کند که یک رابط وب و یک API RESTful ارائه می دهد که به شما امکان می دهد با عبور پارامترهای لازم، Spark-submit را از راه دور راه اندازی کنید. بهطور سنتی بهعنوان بخشی از توزیع HDP ارسال میشود، اما همچنین میتواند با استفاده از مانیفست مناسب و مجموعهای از تصاویر Docker، مانند این، در OKD یا هر نصب دیگر Kubernetes مستقر شود. github.com/ttauveron/k8s-big-data-experiments/tree/master/livy-spark-2.3. برای مورد ما، یک تصویر Docker مشابه، از جمله Spark نسخه 2.4.5 از Dockerfile زیر ساخته شد:
تصویر تولید شده را می توان ساخت و در مخزن Docker موجود شما، مانند مخزن داخلی OKD، آپلود کرد. برای استقرار آن، از مانیفست زیر استفاده کنید ({registry-url} - URL رجیستری تصویر Docker, {image-name} - Docker image name, {tag} - Docker image tag, {livy-url} - URL دلخواه که در آن سرور قابل دسترسی Livy خواهد بود؛ اگر Red Hat OpenShift به عنوان توزیع Kubernetes استفاده شود، از مانیفست "Route" استفاده می شود، در غیر این صورت از مانیفست Ingress یا Service مربوطه از نوع NodePort استفاده می شود:
پس از اعمال آن و راه اندازی موفقیت آمیز پاد، رابط گرافیکی Livy در پیوند موجود است: http://{livy-url}/ui. با Livy، میتوانیم وظیفه Spark خود را با استفاده از یک درخواست REST از مثلاً Postman منتشر کنیم. نمونه ای از یک مجموعه با درخواست در زیر ارائه شده است (آگومان های پیکربندی با متغیرهای لازم برای عملکرد کار راه اندازی شده را می توان در آرایه "args" ارسال کرد):
بیایید اولین درخواست از مجموعه را اجرا کنیم، به رابط OKD برویم و بررسی کنیم که کار با موفقیت راه اندازی شده است - https://{OKD-WEBUI-URL}/console/project/{project}/browse/pods. در همان زمان، یک جلسه در رابط Livy ظاهر می شود (http://{livy-url}/ui) که در آن، با استفاده از Livy API یا رابط گرافیکی، می توانید پیشرفت کار را پیگیری کرده و جلسه را مطالعه کنید. سیاهههای مربوط
حالا بیایید نشان دهیم لیوی چگونه کار می کند. برای انجام این کار، اجازه دهید سیاهههای مربوط به کانتینر Livy را در داخل غلاف با سرور Livy بررسی کنیم - https://{OKD-WEBUI-URL}/console/project/{project}/browse/pods/{livy-pod-name }?tab=logs. از آنها میتوانیم ببینیم که هنگام فراخوانی Livy REST API در ظرفی به نام «livy»، یک spark-submit اجرا میشود، مشابه آنچه در بالا استفاده کردیم (در اینجا {livy-pod-name} نام پاد ایجاد شده است. با سرور Livy). این مجموعه همچنین یک پرسش دوم را معرفی می کند که به شما امکان می دهد وظایفی را اجرا کنید که از راه دور یک فایل اجرایی Spark را با استفاده از سرور Livy میزبانی می کنند.
مورد استفاده سوم - اپراتور اسپارک
اکنون که این کار آزمایش شده است، سؤال اجرای منظم آن مطرح می شود. راه اصلی برای اجرای منظم وظایف در یک خوشه Kubernetes موجودیت CronJob است و می توانید از آن استفاده کنید، اما در حال حاضر استفاده از اپراتورها برای مدیریت برنامه ها در Kubernetes بسیار محبوب است و برای Spark یک اپراتور نسبتا بالغ وجود دارد که همچنین در راه حل های سطح سازمانی (به عنوان مثال، Lightbend FastData Platform) استفاده می شود. ما استفاده از آن را توصیه می کنیم - نسخه پایدار فعلی Spark (2.4.5) گزینه های پیکربندی نسبتاً محدودی برای اجرای وظایف Spark در Kubernetes دارد، در حالی که نسخه اصلی بعدی (3.0.0) پشتیبانی کامل از Kubernetes را اعلام می کند، اما تاریخ انتشار آن ناشناخته باقی مانده است. . Spark Operator با افزودن گزینه های پیکربندی مهم (به عنوان مثال، نصب ConfigMap با پیکربندی دسترسی Hadoop به Spark pod) و توانایی اجرای یک کار برنامه ریزی شده منظم، این نقص را جبران می کند.
بیایید آن را به عنوان یک مورد استفاده سوم برجسته کنیم - به طور منظم وظایف Spark را در یک خوشه Kubernetes در یک حلقه تولید اجرا می کنیم.
استفاده از مانیفست از مخزن رسمی (https://github.com/GoogleCloudPlatform/spark-on-k8s-operator/tree/master/manifest). شایان ذکر است که در Cloudflow یک اپراتور با API نسخه v1beta1 وجود دارد. اگر از این نوع نصب استفاده می شود، توضیحات مانیفست برنامه Spark باید بر اساس تگ های نمونه در Git با نسخه API مناسب، به عنوان مثال، "v1beta1-0.9.0-2.4.0" باشد. نسخه اپراتور را می توان در توضیحات CRD موجود در اپراتور در فرهنگ لغت "نسخه ها" یافت:
oc get crd sparkapplications.sparkoperator.k8s.io -o yaml
اگر اپراتور به درستی نصب شده باشد، یک pod فعال با عملگر Spark در پروژه مربوطه ظاهر می شود (به عنوان مثال، cloudflow-fdp-sparkoperator در فضای Cloudflow برای نصب Cloudflow) و یک نوع منبع Kubernetes مربوطه با نام "sparkapplications" ظاهر می شود. . با دستور زیر می توانید برنامه های Spark موجود را کاوش کنید:
oc get sparkapplications -n {project}
برای اجرای وظایف با استفاده از Spark Operator باید 3 کار را انجام دهید:
یک تصویر Docker ایجاد کنید که شامل تمام کتابخانه های لازم و همچنین پیکربندی و فایل های اجرایی باشد. در تصویر هدف، این تصویری است که در مرحله CI/CD ایجاد شده و روی یک خوشه آزمایشی آزمایش شده است.
انتشار یک تصویر Docker در یک رجیستری قابل دسترسی از خوشه Kubernetes.
این مانیفست یک حساب سرویس را مشخص میکند که قبل از انتشار مانیفست، باید نقشبندیهای لازم را ایجاد کنید که حقوق دسترسی لازم را برای برنامه Spark برای تعامل با Kubernetes API (در صورت لزوم) فراهم میکند. در مورد ما، برنامه برای ایجاد Pods به حقوق نیاز دارد. بیایید پیوند نقش لازم را ایجاد کنیم:
همچنین شایان ذکر است که این مشخصات مانیفست ممکن است شامل یک پارامتر "hadoopConfigMap" باشد که به شما امکان می دهد یک ConfigMap با پیکربندی Hadoop بدون نیاز به قرار دادن فایل مربوطه در تصویر Docker مشخص کنید. همچنین برای اجرای منظم وظایف مناسب است - با استفاده از پارامتر "زمان بندی"، می توان برنامه ای برای اجرای یک کار معین مشخص کرد.
پس از آن، ما مانیفست خود را در فایل spark-pi.yaml ذخیره می کنیم و آن را در خوشه Kubernetes اعمال می کنیم:
oc apply -f spark-pi.yaml
این یک شی از نوع "sparkapplications" ایجاد می کند:
oc get sparkapplications -n {project}
> NAME AGE
> spark-pi 22h
در این حالت، یک pod با یک برنامه ایجاد می شود که وضعیت آن در "sparkapplications" ایجاد شده نمایش داده می شود. با دستور زیر می توانید آن را مشاهده کنید:
oc get sparkapplications spark-pi -o yaml -n {project}
پس از اتمام کار، POD به وضعیت "تکمیل" منتقل می شود، که در "sparkapplications" نیز به روز می شود. گزارش های برنامه را می توان در مرورگر یا با استفاده از دستور زیر مشاهده کرد (در اینجا {sparkapplications-pod-name} نام پاد وظیفه در حال اجرا است):
oc logs {sparkapplications-pod-name} -n {project}
وظایف Spark را نیز می توان با استفاده از ابزار تخصصی sparkctl مدیریت کرد. برای نصب آن، مخزن را با کد منبع آن کلون کنید، Go را نصب کنید و این ابزار را بسازید:
git clone https://github.com/GoogleCloudPlatform/spark-on-k8s-operator.git
cd spark-on-k8s-operator/
wget https://dl.google.com/go/go1.13.3.linux-amd64.tar.gz
tar -xzf go1.13.3.linux-amd64.tar.gz
sudo mv go /usr/local
mkdir $HOME/Projects
export GOROOT=/usr/local/go
export GOPATH=$HOME/Projects
export PATH=$GOPATH/bin:$GOROOT/bin:$PATH
go -version
cd sparkctl
go build -o sparkctl
sudo mv sparkctl /usr/local/bin
بیایید لیستی از وظایف در حال اجرا Spark را بررسی کنیم:
بیایید وظیفه توصیف شده را با استفاده از sparkctl اجرا کنیم:
sparkctl create spark-app.yaml -n {project}
بیایید لیستی از وظایف در حال اجرا Spark را بررسی کنیم:
sparkctl list -n {project}
بیایید لیست رویدادهای یک وظیفه Spark راه اندازی شده را بررسی کنیم:
sparkctl event spark-pi -n {project} -f
بیایید وضعیت عملکرد Spark در حال اجرا را بررسی کنیم:
sparkctl status spark-pi -n {project}
در پایان، من می خواهم معایب کشف شده استفاده از نسخه پایدار فعلی Spark (2.4.5) در Kubernetes را در نظر بگیرم:
اولین و شاید اصلیترین نقطه ضعف، عدم وجود دادههای محلی است. با وجود تمام کاستیهای YARN، استفاده از آن مزایایی نیز داشت، به عنوان مثال، اصل ارائه کد به داده (به جای داده به کد). به لطف آن، وظایف Spark بر روی گره هایی که داده های درگیر در محاسبات در آن قرار داشتند، اجرا شد و زمان تحویل داده ها از طریق شبکه به میزان قابل توجهی کاهش یافت. هنگام استفاده از Kubernetes، ما با نیاز به انتقال داده های مربوط به یک کار در سراسر شبکه مواجه هستیم. اگر آنها به اندازه کافی بزرگ باشند، زمان اجرای کار می تواند به طور قابل توجهی افزایش یابد، و همچنین نیاز به فضای نسبتا زیادی از دیسک اختصاص داده شده به نمونه های وظیفه Spark برای ذخیره سازی موقت آنها دارد. این نقطه ضعف را می توان با استفاده از نرم افزارهای تخصصی که محلی بودن داده ها را در Kubernetes تضمین می کند (به عنوان مثال Alluxio) کاهش داد، اما این در واقع به معنای نیاز به ذخیره یک کپی کامل از داده ها در گره های خوشه Kubernetes است.
دومین نقطه ضعف مهم امنیت است. به طور پیشفرض، ویژگیهای مرتبط با امنیت در مورد اجرای وظایف Spark غیرفعال هستند، استفاده از Kerberos در اسناد رسمی پوشش داده نمیشود (اگرچه گزینههای مربوطه در نسخه 3.0.0 معرفی شدهاند، که نیاز به کار اضافی دارد)، و اسناد امنیتی برای با استفاده از Spark (https://spark.apache.org/docs/2.4.5/security.html) فقط YARN، Mesos و Standalone Cluster به عنوان فروشگاه کلید ظاهر می شوند. در عین حال، کاربری که وظایف Spark تحت آن راه اندازی می شود را نمی توان مستقیماً مشخص کرد - ما فقط حساب سرویسی را که تحت آن کار می کند مشخص می کنیم و کاربر بر اساس سیاست های امنیتی پیکربندی شده انتخاب می شود. در این رابطه، یا از کاربر ریشه استفاده می شود که در یک محیط تولیدی ایمن نیست، یا یک کاربر با یک UID تصادفی، که هنگام توزیع حقوق دسترسی به داده ها ناخوشایند است (این را می توان با ایجاد PodSecurityPolicies و پیوند دادن آنها به حساب های خدمات مربوطه). در حال حاضر، راه حل این است که یا تمام فایل های لازم را مستقیماً در تصویر داکر قرار دهید، یا اسکریپت راه اندازی Spark را برای استفاده از مکانیسم ذخیره و بازیابی اسرار مورد استفاده در سازمان خود تغییر دهید.
اجرای کارهای Spark با استفاده از Kubernetes به طور رسمی هنوز در حالت آزمایشی است و ممکن است در آینده تغییرات قابل توجهی در مصنوعات مورد استفاده (فایل های پیکربندی، تصاویر پایه Docker و اسکریپت های راه اندازی) ایجاد شود. و در واقع، هنگام تهیه مواد، نسخه های 2.3.0 و 2.4.5 آزمایش شدند، رفتار به طور قابل توجهی متفاوت بود.
بیایید منتظر به روزرسانی ها باشیم - اخیراً نسخه جدیدی از Spark (3.0.0) منتشر شد که تغییرات قابل توجهی در کار Spark در Kubernetes ایجاد کرد ، اما وضعیت آزمایشی پشتیبانی را برای این مدیر منابع حفظ کرد. شاید بهروزرسانیهای بعدی واقعاً این امکان را به شما بدهد که به طور کامل از YARN و اجرای وظایف Spark در Kubernetes بدون ترس از امنیت سیستم خود و بدون نیاز به تغییر مستقل اجزای عملکردی استفاده کنید.