Të dashur lexues, ditë të mirë. Sot do të flasim pak për Apache Spark dhe perspektivat e tij të zhvillimit.

NĂ« botĂ«n moderne tĂ« Big Data, Apache Spark Ă«shtĂ« standardi de facto pĂ«r zhvillimin e zgjidhjeve tĂ« pĂ«rpunimit nĂ« grup. PĂ«rveç kĂ«saj, ai pĂ«rdoret gjithashtu pĂ«r tĂ« krijuar aplikacione pĂ«r transmetim nĂ« konceptin e mikro-grumbullit, duke pĂ«rpunuar dhe dĂ«rguar tĂ« dhĂ«na nĂ« sasi tĂ« vogla (Spark Structured Streaming). Tradicionalisht, ai ka qenĂ« pjesĂ« e stakut tĂ« pĂ«rgjithshĂ«m Hadoop, duke pĂ«rdorur YARN si menaxher tĂ« burimeve (ose, nĂ« disa raste, Apache Mesos). Deri nĂ« vitin 2020, pĂ«rdorimi i tij nĂ« formĂ«n tradicionale pĂ«r shumicĂ«n e kompanive ishte nĂ«n pyetje tĂ« madhe pĂ«r shkak tĂ« mungesĂ«s sĂ« distribucioneve tĂ« mira Hadoop - zhvillimi i HDP dhe CDH Ă«shtĂ« ndalur, CDH Ă«shtĂ« mjaft i papĂ«rfunduar dhe ka njĂ« kosto tĂ« lartĂ«, ndĂ«rsa ofruesit e tjerĂ« tĂ« Hadoop ose kanĂ« ndaluar sĂ« ekzistuari ose kanĂ« njĂ« tĂ« ardhme tĂ« paqartĂ«. Prandaj, interesi nĂ« rritje i komunitetit dhe kompanive tĂ« mĂ«dha po tĂ«rhiqet nga запŃŃĐș Apache Spark nĂ«pĂ«rmjet Kubernetes - duke u bĂ«rĂ« standard nĂ« orkestrimin e kontenierĂ«ve dhe menaxhimin e burimeve nĂ« re private dhe publike, ai zgjidh problemin me planifikimin e vĂ«shtirĂ« tĂ« burimeve tĂ« detyrave tĂ« Spark nĂ« YARN dhe ofron njĂ« platformĂ« qĂ« po zhvillohet qĂ«ndruar, me shumĂ« distribucione komerciale dhe tĂ« hapura pĂ«r kompani tĂ« tĂ« gjitha madhĂ«sive dhe llojeve. PĂ«r mĂ« tepĂ«r, nĂ« valĂ«n e popullaritetit, shumica e tyre tashmĂ« kanĂ« arritur tĂ« krijojnĂ« disa instalime dhe tĂ« rrisin ekspertizĂ«n nĂ« pĂ«rdorimin e tij, duke e bĂ«rĂ« migrimin mĂ« tĂ« lehtĂ«.
Duke filluar nga versioni 2.3.0, Apache Spark ka fituar mbështetje zyrtare për running tasks në klusterin Kubernetes dhe sot do të flasim për pjekurinë aktuale të këtij qasjeje, variacionet e ndryshme të përdorimit të saj dhe pengesat me të cilat do të përballeni gjatë implementimit.
Së pari, le të shqyrtojmë procesin e zhvillimit të detyrave dhe aplikacioneve bazuar në Apache Spark dhe të identifikojmë raste tipike në të cilat është e nevojshme të ekzekutoni një detyrë në klasterin Kubernetes. Përgatitja e këtij postimi përdor OpenShift si distribuicion dhe do të paraqiten komandat relevante për utilitarin e tij të linjës së komandës (oc). Për distribuionet e tjera të Kubernetes, mund të përdoren komandat përkatëse të utilitarit standard të linjës së komandës Kubernetes (kubectl) ose homologët e tyre (për shembull, për oc adm policy).
Përdorimi i parë është spark-submit
Gjatë zhvillimit të detyrave dhe aplikacioneve, zhvilluesi ka nevojë të ekzekutojë detyrat për të debug-uar transformimin e të dhënave. Teoretikisht, për këto qëllime mund të përdoren 'stubs', por zhvillimi me pjesëmarrje të instanceve reale (edhe nëse teste) të sistemeve përfundimtare, ka treguar se është më i shpejtë dhe më cilësor në këtë klasë problemashe. Në rastin kur kryejmë debugging në instance reale të sistemeve përfundimtare, mund të kemi dy skenarë të punës:
- zhvilluesi ekzekuton detyrën Spark lokal në modalitetin standalone;

- zhvilluesi ekzekuton detyrën Spark në një klasër Kubernetes në kontur testimi.

Varianti i parë ka të drejtë ekzistimi, por sjell një sërë disavantazhesh:
- çdo zhvillues ka nevojë të sigurojë akses nga vendi i punës deri te të gjitha instance të nevojshme të sistemeve përfundimtare;
- në makinën e punës nevojiten resurse të mjaftueshme për të ekzekutuar detyrën që po zhvillohet.
Varianti i dytĂ« Ă«shtĂ« pa kĂ«to disavantazhe, pasi pĂ«rdorimi i klasĂ«r Kubernetes lejon alokimin e pool-it tĂ« nevojshĂ«m tĂ« burimeve pĂ«r ekzekutimin e detyrave dhe siguron qasje tĂ« nevojshme te instance tĂ« sistemeve pĂ«rfundimtare, duke ofruar qasje fleksibĂ«l pĂ«rmes modelit tĂ« rolit Kubernetes pĂ«r tĂ« gjithĂ« anĂ«tarĂ«t e ekipit tĂ« zhvillimit. Ta tregojmĂ« atĂ« si variantin e parĂ« tĂ« pĂ«rdorimit â ekzekutimi i detyrave Spark nga makina lokale e zhvilluesit nĂ« klasĂ«n Kubernetes nĂ« konturin testues.
Le të flasim më shumë rreth procesit të konfigurimit të Spark për ekzekutimin lokal. Për të filluar përdorimin e Spark, është e nevojshme ta instaloni:
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
Kemi nevojë për të mbledhur paketat e nevojshme për punën me Kubernetes:
cd spark-2.4.5/
./build/mvn -Pkubernetes -DskipTests clean package
Ndërtesa e plotë merr shumë kohë, dhe për krijimin e imazheve Docker dhe ekzekutimin e tyre në klasën Kubernetes në realitet nevojiten vetëm skedarët jar nga direktoria 'assembly/', prandaj është e mundur të mbledhim vetëm këtë nënprojekt:
./build/mvn -f ./assembly/pom.xml -Pkubernetes -DskipTests clean package
Për të ekzekutuar detyrat Spark në Kubernetes, është e nevojshme të krijoni një imazh Docker, i cili do të përdoret si bazë. Këtu mund të ketë 2 qasje:
- Imazhi Docker i krijuar përfshin kodin ekzekutues të detyrës Spark;
- Imazhi i krijuar përmban vetëm Spark dhe varësitë e nevojshme, kodi ekzekutiv vendoset në distancë (p.sh., në HDFS).
Fillimisht, le të krijojmë imazhin Docker, i cili përmban një shembull testimi të detyrës Spark. Për të krijuar imazhe Docker, Spark ka një utilitar përkatës të quajtur "docker-image-tool". Le të shohim ndihmën për këtë:
.\/bin\/docker-image-tool.sh --help
Me ndihmën e saj mund të krijoni imazhe Docker dhe t'i ngarkoni ato në regjistrat e largët, por për shkaqe të natyrshme ajo ka disa disavantazhe:
- detyrimisht krijon menjĂ«herĂ« 3 imazhe Docker â pĂ«r Spark, PySpark dhe R;
- nuk lejon caktimin e emrit të imazhit.
Prandaj, ne do të përdorim një version të modifikuar të këtij utilitari, të dhënë më poshtë:
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
Me ndihmĂ«n e saj, ne krijojmĂ« imazhin bazĂ« tĂ« Spark, i cili pĂ«rmban njĂ« detyrĂ« testuese pĂ«r llogaritjen e numrit Pi me ndihmĂ«n e Spark (kĂ«tu {docker-registry-url} â URL e regjistrit tuaj tĂ« imazheve Docker, {repo} â emri i depozitĂ«s brenda regjistrit qĂ« pĂ«rputhet me projektin nĂ« OpenShift, {image-name} â emri i imazhit (nĂ«se pĂ«rdoret ndarja me tri nivele tĂ« imazheve, p.sh., si nĂ« regjistrin e integruar tĂ« imazheve Red Hat OpenShift), {tag} â etiketa e kĂ«saj versioni tĂ« imazhit):
.\/bin\/docker-image-tool-upd.sh -f resource-managers\/kubernetes\/docker\/src\/main\/dockerfiles\/spark\/Dockerfile -r {docker-registry-url}\/ {repo} -i {image-name} -t {tag} build
Autentikohemi nĂ« klasterin OKD me ndihmĂ«n e utilitarit tĂ« konsolĂ«s (kĂ«tu {OKD-API-URL} â URL e API-sĂ« sĂ« klasterit OKD):
oc login {OKD-API-URL}
Marrim tokenin e përdoruesit aktual për autentifikim në Docker Registry:
oc whoami -t
Autentikohemi në Docker Registry të brendshëm të klasterit OKD (si fjalëkalim përdorim tokenin e marrë me komandën e mëparshme):
docker login {docker-registry-url}
Ngarkojmë imazhin e ndërtuar Docker në Docker Registry OKD:
.\/bin\/docker-image-tool-upd.sh -r {docker-registry-url}\/ {repo} -i {image-name} -t {tag} push
KontrollojmĂ« qĂ« imazhi i ndĂ«rtuar Ă«shtĂ« i disponueshĂ«m nĂ« OKD. PĂ«r kĂ«tĂ«, hapim nĂ« shfletues URL-nĂ« me listĂ«n e imazheve tĂ« projektit pĂ«rkatĂ«s (kĂ«tu {project} â emri i projektit brenda klasterit OpenShift, {OKD-WEBUI-URL} â URL e konsolĂ«s Web tĂ« OpenShift) â https:\/{OKD-WEBUI-URL}\/console\/project\/ {project}\/browse\/images\/ {image-name}.
Për të filluar detyrat, duhet të krijohet një llogari shërbimi me privilegje për të nisur pod-et nën root (do ta diskutojmë më vonë):
oc create sa spark -n {project}
oc adm policy add-scc-to-user anyuid -z spark -n {project}
Do të ekzekutojmë komandën spark-submit për të publikuar detyrën Spark në klasterin OKD, duke caktuar llogarinë e shërbimit të krijuar dhe imazhin Docker:
/opt/spark/bin/spark-submit --name spark-test --class org.apache.spark.examples.SparkPi --conf spark.executor.instances=3 --conf spark.kubernetes.authenticate.driver.serviceAccountName=spark --conf spark.kubernetes.namespace={project} --conf spark.submit.deployMode=cluster --conf spark.kubernetes.container.image={docker-registry-url}/{repo}/{image-name}:{tag} --conf spark.master=k8s://https://{OKD-API-URL} local:///opt/spark/examples/target/scala-2.11/jars/spark-examples_2.11-2.4.5.jar
Këtu:
âname â emri i detyrĂ«s, e cila do tĂ« kontribuojĂ« nĂ« formimin e emrit tĂ« pod-eve Kubernetes;
âklasĂ« â klasa e skedarit ekzekutues qĂ« thirret gjatĂ« fillimit tĂ« detyrĂ«s;
âkonf â parametrat e konfigurimit tĂ« Spark;
spark.executor.instances â numri i ekzekutorĂ«ve tĂ« Spark qĂ« do tĂ« ekzekutohen;
spark.kubernetes.authenticate.driver.serviceAccountName â emri i llogarisĂ« shĂ«rbyese Kubernetes qĂ« pĂ«rdoret gjatĂ« fillimit tĂ« pod-Ă«ve (pĂ«r tĂ« pĂ«rcaktuar kontekstin e sigurisĂ« dhe mundĂ«sitĂ« gjatĂ« ndĂ«rveprimit me API-nĂ« e Kubernetes);
spark.kubernetes.namespace â hapĂ«sira emĂ«rore e Kubernetes, nĂ« tĂ« cilĂ«n do tĂ« ekzekutohen pod-Ă«t e drejtuesit dhe ekzekutorĂ«ve;
spark.submit.deployMode â mĂ«nyra e ekzekutimit tĂ« Spark (pĂ«r spark-submit standard pĂ«rdoret «cluster», pĂ«r Spark Operator dhe versionet mĂ« tĂ« vonshme tĂ« Spark «client»);
spark.kubernetes.container.image â imazhi Docker qĂ« pĂ«rdoret pĂ«r tĂ« ekzekutuar pod-Ă«t;
spark.master â URL-ja e API-sĂ« sĂ« Kubernetes (cila tregohet pĂ«r pĂ«rdorim nga makina lokale);
local:// â rruga pĂ«r skedarin ekzekutues tĂ« Spark brenda imazhit Docker.
Shkoni te projekti pĂ«rkatĂ«s OKD dhe shqyrtoni pod-Ă«t e krijuar â https://{OKD-WEBUI-URL}/console/project/{project}/browse/pods.
PĂ«r tĂ« thjeshtuar procesin e zhvillimit mund tĂ« pĂ«rdoret njĂ« variant tjetĂ«r, nĂ« tĂ« cilin krijohet njĂ« imazh themelor i pĂ«rbashkĂ«t Spark qĂ« pĂ«rdoret nga tĂ« gjitha detyrat gjatĂ« ekzekutimit, ndĂ«rsa snapshot-et e skedarĂ«ve ekzekutues publikohen nĂ« njĂ« ruajtje tĂ« jashtme (pĂ«r shembull, Hadoop) dhe caktohen gjatĂ« thirrjes sĂ« spark-submit si lidhje. NĂ« kĂ«tĂ« rast mund tĂ« ekzekutoni versione tĂ« ndryshme tĂ« detyrave Spark pa rikonstruar imazhet Docker, duke pĂ«rdorur pĂ«r publikimin e imazheve, pĂ«r shembull, WebHDFS. DĂ«rgoni njĂ« kĂ«rkesĂ« pĂ«r krijimin e skedarit (kĂ«tu {host} â host-i i shĂ«rbimit WebHDFS, {port} â porta e shĂ«rbimit WebHDFS, {path-to-file-on-hdfs} â rruga e dĂ«shiruar pĂ«r skedarin nĂ« HDFS):
curl -i -X PUT "http://{host}:{port}/webhdfs/v1/{path-to-file-on-hdfs}?op=CREATE
NĂ« kĂ«tĂ« rast do tĂ« merrni njĂ« pĂ«rgjigje tĂ« kĂ«tij lloji (kĂ«tu {location} â Ă«shtĂ« URL-ja qĂ« duhet tĂ« pĂ«rdoret pĂ«r ngarkimin e skedarit):
HTTP/1.1 307 TEMPORARY_REDIRECT
Location: {location}
Content-Length: 0
Ngarkoni skedarin ekzekutues tĂ« Spark nĂ« HDFS (kĂ«tu {path-to-local-file} â rruga pĂ«r skedarin ekzekutues tĂ« Spark nĂ« hostin aktual):
curl -i -X PUT -T {path-to-local-file} "{location}"
Pas kĂ«saj mund tĂ« bĂ«ni spark-submit duke pĂ«rdorur skedarin e Spark, i ngarkuar nĂ« HDFS (kĂ«tu {class-name} â emri i klasĂ«s qĂ« kĂ«rkohet tĂ« ekzekutohet pĂ«r realizimin e detyrĂ«s):
/opt/spark/bin/spark-submit --name spark-test --class {class-name} --conf spark.executor.instances=3 --conf spark.kubernetes.authenticate.driver.serviceAccountName=spark --conf spark.kubernetes.namespace={project} --conf spark.submit.deployMode=cluster --conf spark.kubernetes.container.image={docker-registry-url}/{repo}/{image-name}:{tag} --conf spark.master=k8s://https://{OKD-API-URL} hdfs://{host}:{port}/{path-to-file-on-hdfs}
NĂ« kĂ«tĂ« rast duhet tĂ« theksohet se pĂ«r qasje nĂ« HDFS dhe pĂ«r tĂ« siguruar funksionimin e detyrĂ«s, mund tĂ« jetĂ« e nevojshme tĂ« ndryshoni Dockerfile-n dhe skriptin entrypoint.sh â tĂ« shtoni nĂ« Dockerfile direktivĂ«n pĂ«r kopjimin e bibliotekave tĂ« varura nĂ« drejtorinĂ« /opt/spark/jars dhe tĂ« pĂ«rfshini skedarin e konfigurimit HDFS nĂ« SPARK_CLASSPATH nĂ« entrypoint.sh.
Varianti i dytĂ« i pĂ«rdorimit â Apache Livy
Më pas, kur detyra është zhvilluar dhe është e nevojshme të testoni rezultatin e marra, lind pyetja e ekzekutimit të saj brenda procesit CI/CD dhe ndjekjes së statusit të ekzekutimit të saj. Sigurisht, mund ta ekzekutoni atë edhe me thirrje lokale spark-submit, por kjo e komplikon infrastrukturën CI/CD pasi kërkon instalimin dhe konfigurimin e Spark në agjentët/rundbukret e serverit CI dhe përgatitjen e aksesit në API-në Kubernetes. Për këtë rast, aplikimi i dëshiruar është zgjedhja e përdorimit të Apache Livy si REST API për të ekzekutuar detyrat Spark, të vendosur brenda klasterit Kubernetes. Me ndihmën e tij mund të ekzekutoni detyrat Spark në klasterin Kubernetes duke përdorur thirrje të zakonshme cURL, që lehtë realizohet mbi ndonjë zgjidhje CI, dhe vendosja e tij brenda klasterit Kubernetes zgjidh çështjen e autentifikimit gjatë bashkëveprimit me API-në Kubernetes.

TĂ« veçojmĂ« atĂ« si variantin e dytĂ« tĂ« pĂ«rdorimit â ekzekutimi i detyrave Spark brenda procesit CI/CD nĂ« klasterin Kubernetes nĂ« kontestin testues.
Pak fjalĂ« mbi Apache Livy â ai funksionon si server HTTP, duke ofruar njĂ« ndĂ«rfaqe Web dhe RESTful API, qĂ« lejon tĂ« ekzekutoni spark-submit nĂ« distancĂ«, duke kaluar parametrat e nevojshĂ«m. Tradicionalisht ai ofrohej si pjesĂ« e distribuimit HDP, por gjithashtu mund tĂ« implementohet nĂ« OKD ose ndonjĂ« instalim tjetĂ«r Kubernetes me ndihmĂ«n e manifestit dhe setit tĂ« imazheve Docker pĂ«rkatĂ«s, pĂ«r shembull, ky â . PĂ«r rastin tonĂ«, njĂ« imazh Docker i ngjashĂ«m u ndĂ«rtua, qĂ« pĂ«rfshin Spark versionin 2.4.5 nga Dockerfile i mĂ«poshtĂ«m:
FROM java:8-alpine
ENV SPARK_HOME=/opt/spark
ENV LIVY_HOME=/opt/livy
ENV HADOOP_CONF_DIR=/etc/hadoop/conf
ENV SPARK_USER=spark
WORKDIR /opt
RUN apk add --update openssl wget bash &&
wget -P /opt https://downloads.apache.org/spark/spark-2.4.5/spark-2.4.5-bin-hadoop2.7.tgz &&
tar xvzf spark-2.4.5-bin-hadoop2.7.tgz &&
rm spark-2.4.5-bin-hadoop2.7.tgz &&
ln -s /opt/spark-2.4.5-bin-hadoop2.7 /opt/spark
RUN wget http://mirror.its.dal.ca/apache/incubator/livy/0.7.0-incubating/apache-livy-0.7.0-incubating-bin.zip &&
unzip apache-livy-0.7.0-incubating-bin.zip &&
rm apache-livy-0.7.0-incubating-bin.zip &&
ln -s /opt/apache-livy-0.7.0-incubating-bin /opt/livy &&
mkdir /var/log/livy &&
ln -s /var/log/livy /opt/livy/logs &&
cp /opt/livy/conf/log4j.properties.template /opt/livy/conf/log4j.properties
ADD livy.conf /opt/livy/conf
ADD spark-defaults.conf /opt/spark/conf/spark-defaults.conf
ADD entrypoint.sh /entrypoint.sh
ENV PATH="/opt/livy/bin:${PATH}"
EXPOSE 8998
ENTRYPOINT ["/entrypoint.sh"]
CMD ["livy-server"]
Imazhi i krijuar mund tĂ« bĂ«het i disponueshĂ«m dhe tĂ« ngarkohet nĂ« regjistrin tuaj Docker, siç Ă«shtĂ« regjistri i brendshĂ«m OKD. PĂ«r ta vendosur pĂ«rdoret manifesti si nĂ« vijim ({registry-url} â URL e regjistrit tĂ« imazheve Docker, {image-name} â emri i imazhit Docker, {tag} â etiketa e imazhit Docker, {livy-url} â URL e dĂ«shiruar ku do tĂ« jetĂ« nĂ« dispozicion serveri Livy; manifesti "Route" aplikohet nĂ« rast se ndĂ«rrimi i Kubernetes pĂ«rdor Red Hat OpenShift, ndryshe aplikohet manifesti pĂ«rkatĂ«s Ingress ose Servici i tipit NodePort):
---
apiVersion: apps/v1
kind: Deployment
metadata:
labels:
component: livy
name: livy
spec:
progressDeadlineSeconds: 600
replicas: 1
revisionHistoryLimit: 10
selector:
matchLabels:
component: livy
strategy:
rollingUpdate:
maxSurge: 25%
maxUnavailable: 25%
type: RollingUpdate
template:
metadata:
creationTimestamp: null
labels:
component: livy
spec:
containers:
- command:
- livy-server
env:
- name: K8S_API_HOST
value: localhost
- name: SPARK_KUBERNETES_IMAGE
value: 'gnut3ll4/spark:v1.0.14'
image: '{registry-url}/{image-name}:{tag}'
imagePullPolicy: Always
name: livy
ports:
- containerPort: 8998
name: livy-rest
protocol: TCP
resources: {}
terminationMessagePath: /dev/termination-log
terminationMessagePolicy: File
volumeMounts:
- mountPath: /var/log/livy
name: livy-log
- mountPath: /opt/.livy-sessions/
name: livy-sessions
- mountPath: /opt/livy/conf/livy.conf
name: livy-config
subPath: livy.conf
- mountPath: /opt/spark/conf/spark-defaults.conf
name: spark-config
subPath: spark-defaults.conf
- command:
- /usr/local/bin/kubectl
- proxy
- '--port'
- '8443'
image: 'gnut3ll4/kubectl-sidecar:latest'
imagePullPolicy: Always
name: kubectl
ports:
- containerPort: 8443
name: k8s-api
protocol: TCP
resources: {}
terminationMessagePath: /dev/termination-log
terminationMessagePolicy: File
dnsPolicy: ClusterFirst
restartPolicy: Always
schedulerName: default-scheduler
securityContext: {}
serviceAccount: spark
serviceAccountName: spark
terminationGracePeriodSeconds: 30
volumes:
- emptyDir: {}
name: livy-log
- emptyDir: {}
name: livy-sessions
- configMap:
defaultMode: 420
items:
- key: livy.conf
path: livy.conf
name: livy-config
name: livy-config
- configMap:
defaultMode: 420
items:
- key: spark-defaults.conf
path: spark-defaults.conf
name: livy-config
name: spark-config
---
apiVersion: v1
kind: ConfigMap
metadata:
name: livy-config
data:
livy.conf: |-
livy.spark.deploy-mode=cluster
livy.file.local-dir-whitelist=/opt/.livy-sessions/
livy.spark.master=k8s://http://localhost:8443
livy.server.session.state-retain.sec = 8h
spark-defaults.conf: 'spark.kubernetes.container.image "gnut3ll4/spark:v1.0.14"'
---
apiVersion: v1
kind: Service
metadata:
labels:
app: livy
name: livy
spec:
ports:
- name: livy-rest
port: 8998
protocol: TCP
targetPort: 8998
selector:
component: livy
sessionAffinity: None
type: ClusterIP
---
apiVersion: route.openshift.io/v1
kind: Route
metadata:
labels:
app: livy
name: livy
spec:
host: {livy-url}
port:
targetPort: livy-rest
to:
kind: Service
name: livy
weight: 100
wildcardPolicy: None
Pas aplikimit të tij dhe nisjes me sukses të pod-it, ndërfaqja grafike e Livy është e aksesueshme përmes lidhjes: http://{livy-url}/ui. Me Livy, ne mund të publikojmë detyrën tonë Spark duke përdorur një kërkesë REST, për shembull, nga Postman. Një shembull koleksioni me kërkesa është paraqitur më poshtë (në array-in "args" mund të kalohen argumente konfigurimi me variablat që janë të nevojshme për funksionimin e detyrës që do të nisi):
{
"info": {
"_postman_id": "be135198-d2ff-47b6-a33e-0d27b9dba4c8",
"name": "Spark Livy",
"schema": "https://schema.getpostman.com/json/collection/v2.1.0/collection.json"
},
"item": [
{
"name": "1 Submit job with jar",
"request": {
"method": "POST",
"header": [
{
"key": "Content-Type",
"value": "application/json"
}
],
"body": {
"mode": "raw",
"raw": "{nt\"file\": \"local://opt/spark/examples/target/scala-2.11/jars/spark-examples_2.11-2.4.5.jar\", nt\"className\": \"org.apache.spark.examples.SparkPi\",nt\"numExecutors\":1,nt\"name\": \"spark-test-1\",nt\"conf\": {ntt\"spark.jars.ivy\": \"/tmp/.ivy\",ntt\"spark.kubernetes.authenticate.driver.serviceAccountName\": \"spark\",ntt\"spark.kubernetes.namespace\": \"{project}\",ntt\"spark.kubernetes.container.image\": \"{docker-registry-url}/{repo}/{image-name}:{tag}\"nt}n}"
},
"url": {
"raw": "http://{livy-url}/batches",
"protocol": "http",
"host": [
"{livy-url}"
],
"path": [
"batches"
]
}
},
"response": []
},
{
"name": "2 Submit job without jar",
"request": {
"method": "POST",
"header": [
{
"key": "Content-Type",
"value": "application/json"
}
],
"body": {
"mode": "raw",
"raw": "{nt\"file\": \"hdfs://{host}:{port}/{path-to-file-on-hdfs}\", nt\"className\": \"{class-name}\",nt\"numExecutors\":1,nt\"name\": \"spark-test-2\",nt\"proxyUser\": \"0\",nt\"conf\": {ntt\"spark.jars.ivy\": \"/tmp/.ivy\",ntt\"spark.kubernetes.authenticate.driver.serviceAccountName\": \"spark\",ntt\"spark.kubernetes.namespace\": \"{project}\",ntt\"spark.kubernetes.container.image\": \"{docker-registry-url}/{repo}/{image-name}:{tag}\"nt},nt\"args\": [ntt\"HADOOP_CONF_DIR=/opt/spark/hadoop-conf\",ntt\"MASTER=k8s://https://kubernetes.default.svc:8443\"nt]n}"
},
"url": {
"raw": "http://{livy-url}/batches",
"protocol": "http",
"host": [
"{livy-url}"
],
"path": [
"batches"
]
}
},
"response": []
}
],
"event": [
{
"listen": "prerequest",
"script": {
"id": "41bea1d0-278c-40c9-ad42-bf2e6268897d",
"type": "text/javascript",
"exec": [
""
]
}
},
{
"listen": "test",
"script": {
"id": "3cdd7736-a885-4a2d-9668-bd75798f4560",
"type": "text/javascript",
"exec": [
""
]
}
}
],
"protocolProfileBehavior": {}
}
KryejmĂ« kĂ«rkesĂ«n e parĂ« nga koleksioni, kalojmĂ« nĂ« ndĂ«rfaqen OKD dhe verifikojmĂ« qĂ« detyra Ă«shtĂ« nisur me sukses â https://{OKD-WEBUI-URL}/console/project/{project}/browse/pods. NĂ« kĂ«tĂ« rast, nĂ« ndĂ«rfaqen Livy (http://{livy-url}/ui) do tĂ« shfaqet njĂ« sesion, brenda tĂ« cilit me ndihmĂ«n e API Livy ose ndĂ«rfaqes grafike mund tĂ« ndjekim avancimin e detyrĂ«s dhe tĂ« studiojmĂ« log-et e sesionit.
Tani Äe tregojmĂ« mekanizmin e funksionimit tĂ« Livy. PĂ«r kĂ«tĂ«, do tĂ« shqyrtojmĂ« regjistrat e kontejnerit Livy brenda pod-it me serverin Livy â https://{OKD-WEBUI-URL}/console/project/{project}/browse/pods/{livy-pod-name}?tab=logs. Prej tyre Ă«shtĂ« e qartĂ« se, kur thirret REST API Livy, nĂ« kontejnerin e emĂ«rtuar «livy» ekzekutohet spark-submit, i ngjashĂ«m me atĂ« qĂ« pĂ«rdorĂ«m mĂ« sipĂ«r (kĂ«tu {livy-pod-name} Ă«shtĂ« emri i pod-it tĂ« krijuar me serverin Livy). NĂ« koleksion Ă«shtĂ« paraqitur gjithashtu njĂ« kĂ«rkesĂ« e dytĂ«, e cila lejon ekzekutimin e detyrave me vendosjen e skedave Spark nĂ« distancĂ« pĂ«rmes serverit Livy.
Varianti i tretĂ« i pĂ«rdorimit â Spark Operator
Tani qĂ« detyra Ă«shtĂ« testuar, ngrihet pyetja e ekzekutimit tĂ« saj tĂ« rregullt. MĂ«nyra natyrore pĂ«r ekzekutimin e rregullt tĂ« detyrave nĂ« klasterin Kubernetes Ă«shtĂ« entiteti CronJob dhe mund ta pĂ«rdorim atĂ«, por nĂ« kĂ«tĂ« moment, po fiton popullaritet pĂ«rdorimi i operatorĂ«ve pĂ«r menaxhimin e aplikacioneve nĂ« Kubernetes dhe pĂ«r Spark ekziston njĂ« operator mjaft i pjekur, i cili pĂ«rdoret gjithashtu nĂ« zgjidhjet e nivelit Enterprise (p.sh., Lightbend FastData Platform). Ne rekomandojmĂ« ta pĂ«rdorni atĂ« â versioni aktual stabil i Spark (2.4.5) ka mundĂ«si mjaft tĂ« kufizuara pĂ«r konfigurimin e ekzekutimit tĂ« detyrave Spark nĂ« Kubernetes, pĂ«rveç qĂ« nĂ« versionin e ardhshĂ«m kryesor (3.0.0) Ă«shtĂ« shpallur mbĂ«shtetje e plotĂ« pĂ«r Kubernetes, por data e daljes sĂ« saj mbetet e panjohur. Spark Operator kompenson kĂ«tĂ« dobĂ«si, duke shtuar parametra tĂ« rĂ«ndĂ«sishĂ«m konfigurimi (p.sh., montimin e ConfigMap me konfigurimin e aksesit nĂ« Hadoop nĂ« pod-et Spark) dhe mundĂ«sinĂ« e ekzekutimit tĂ« detyrave sipas njĂ« orari.

Ta nxjerrim atĂ« si njĂ« variant tĂ« tretĂ« pĂ«rdorimi â ekzekutimi i rregullt i detyrave Spark nĂ« klasterin Kubernetes nĂ« njĂ« mjedis prodhimi.
Spark Operator ka kod tĂ« hapur dhe zhvillohet brenda Google Cloud Platform â . Instalimi i tij mund tĂ« kryhet nĂ« 3 mĂ«nyra:
- Si pjesë e instalimit të Lightbend FastData Platform/Cloudflow;
- Me ndihmën e Helm:
helm repo add incubator http://storage.googleapis.com/kubernetes-charts-incubator helm install incubator/sparkoperator --namespace spark-operator - Duke përdorimi i manifestëve nga depoja zyrtare (https://github.com/GoogleCloudPlatform/spark-on-k8s-operator/tree/master/manifest). Duhet të theksohet se Cloudflow përfshin operatorin me versionin e API-t v1beta1. Nëse ky tip instalimi përdoret, përshkrimet e manifestëve të aplikacioneve Spark duhet të ndërtohen mbi bazën e shembujve nga etiketat në Git me versionin përkatës të API-t, për shembull, "v1beta1-0.9.0-2.4.0". Versioni i operatorit mund të përftohet në përshkrimin e CRD-së që përfshihet në operator në fjalorin "versions":
oc get crd sparkapplications.sparkoperator.k8s.io -o yaml
Nëse operatori është instaluar saktë, në projektin përkatës do të shfaqet një pod aktiv me operatorin Spark (për shembull, cloudflow-fdp-sparkoperator në hapësirën Cloudflow për instalimin e Cloudflow) dhe do të shfaqet lloji përkatës i burimeve Kubernetes me emrin "sparkapplications". Aplikacionet e disponueshme Spark mund të studiohen me komandën e mëposhtme:
oc get sparkapplications -n {project}
Për të ekzekutuar detyra duke përdorur Spark Operator, duhet të bëhen 3 gjëra:
- të krijoni një imazh Docker që përfshin të gjitha bibliotekat e nevojshme, si dhe skedarët konfigurues dhe ekzekutivë. Në pamjen e përfundimtare, ky është imazhi i krijuar gjatë etapës CI/CD dhe i testuar në klasterin e testimit;
- të publikoni imazhin Docker në një regjistër që është i disponueshëm nga klasteri Kubernetes;
- të formoni një manifest me llojin "SparkApplication" dhe përshkrimin e detyrës që do të ekzekutohet. Shembujt e manifestëve janë të disponueshëm në depozitat zyrtare (për shembull, ). Duhet të theksohen disa pika të rëndësishme në lidhje me manifestin:
- në fjalorin "apiVersion" duhet të përmendet versioni i API-t përkatës me versionin e operatorit;
- në fjalorin "metadata.namespace" duhet të shënohet hapësira emërore ku do të ekzekutohet aplikacioni;
- në fjalorin "spec.image" duhet të jepet adresa e imazhit të krijuar Docker në regjistrin e disponueshëm;
- në fjalorin "spec.mainClass" duhet të jepet klasa e detyrës Spark që kërkohet të ekzekutohet gjatë fillimit të procesit;
- në fjalorin "spec.mainApplicationFile" duhet të jepet rruga drejt skedarit ekzekutiv jar;
- në fjalorin "spec.sparkVersion" duhet të shënohet versioni i Spark-it që përdoret;
- në fjalorin "spec.driver.serviceAccount" duhet të jepet llogaria e shërbimit brenda hapësirës emërore përkatëse të Kubernetes-it, që do të përdoret për të ekzekutuar aplikacionin;
- në fjalorin "spec.executor" duhet të jepen burimet e dedikuara aplikacionit;
- Në fjalorin «spec.volumeMounts» duhet të specifikohet një direktori lokale, në të cilën do të krijohen skedarët lokalë të detyrës Spark.
Shembulli i formimit të manifestit (këtu {spark-service-account} është llogaria e shërbimit brenda klasterit Kubernetes për të ekzekutuar detyrat Spark):
apiVersion: "sparkoperator.k8s.io/v1beta1"
kind: SparkApplication
metadata:
name: spark-pi
namespace: {project}
spec:
type: Scala
mode: cluster
image: "gcr.io/spark-operator/spark:v2.4.0"
imagePullPolicy: Always
mainClass: org.apache.spark.examples.SparkPi
mainApplicationFile: "local:///opt/spark/examples/jars/spark-examples_2.11-2.4.0.jar"
sparkVersion: "2.4.0"
restartPolicy:
type: Never
volumes:
- name: "test-volume"
hostPath:
path: "tmp"
type: Directory
driver:
cores: 0.1
coreLimit: "200m"
memory: "512m"
labels:
version: 2.4.0
serviceAccount: {spark-service-account}
volumeMounts:
- name: "test-volume"
mountPath: "tmp"
executor:
cores: 1
instances: 1
memory: "512m"
labels:
version: 2.4.0
volumeMounts:
- name: "test-volume"
mountPath: "tmp"
NĂ« kĂ«tĂ« manifest Ă«shtĂ« e specifikuar llogaria e shĂ«rbimit, pĂ«r tĂ« cilĂ«n kĂ«rkohet qĂ« para publikimit tĂ« manifestit tĂ« krijohen lidhet e nevojshme tĂ« rolit, qĂ« ofrojnĂ« tĂ« drejtat e nevojshme pĂ«r ndĂ«rveprimin e aplikacionit Spark me API-nĂ« Kubernetes (nĂ«se Ă«shtĂ« e nevojshme). NĂ« rastin tonĂ«, aplikacionit i duhen tĂ« drejtat pĂ«r tĂ« krijuar PodâĂ«. Le tĂ« krijojmĂ« lidhjen e nevojshme tĂ« rolit:
oc adm policy add-role-to-user edit system:serviceaccount:{project}:{spark-service-account} -n {project}
Gjithashtu, vlen tĂ« theksohet se nĂ« specifikimin e kĂ«tij manifesti mund tĂ« jetĂ« specifikuar parametri «hadoopConfigMap», i cili lejon tĂ« specifikohet ConfigMap me konfigurimin Hadoop pa pasur nevojĂ« pĂ«r ta vendosur paraprakisht skedarin pĂ«rkatĂ«s nĂ« imazhin Docker. Ai gjithashtu Ă«shtĂ« i pĂ«rshtatshĂ«m pĂ«r ekzekutimin e rregullt tĂ« detyrave â me anĂ« tĂ« parametrin «schedule» mund tĂ« specifikohet njĂ« orar pĂ«r ekzekutimin e kĂ«saj detyre.
Pas kësaj, e ruajmë manifestin tonë në skedarin spark-pi.yaml dhe e aplikojmë atë në klasterin tonë Kubernetes:
oc apply -f spark-pi.yaml
Në këtë rast, do të krijohet një objekt i tipit «sparkapplications»:
oc get sparkapplications -n {project}
> NAME AGE
> spark-pi 22h
Në këtë rast, do të krijohet një pod me aplikacionin, statusi i të cilit do të shfaqet në «sparkapplications» të krijuar. Mund të shihet me komandën e mëposhtme:
oc get sparkapplications spark-pi -o yaml -n {project}
Pasi të përfundojë detyra, POD-i do të kalojë në statusin «Completed», i cili gjithashtu do të përditësohet në «sparkapplications». Log-et e aplikacionit mund të shihen në shfletues ose me komandën e mëposhtme (këtu {sparkapplications-pod-name} është emri i podit të detyrës së ekzekutuar):
oc logs {sparkapplications-pod-name} -n {project}
Menaxhimi i detyrave të Spark mund të kryhet edhe përmes një utilitari të specializuar, sparkctl. Për ta instaluar, klonojmë depozitat me kodin e tij burimor, instalojmë Go dhe e ndërtomë këtë utilitar:
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
Le të shqyrtojmë listën e detyrave të ekzekutuara të Spark:
sparkctl list -n {project}
Le të krijojmë një përshkrim për detyrën e Spark:
vi spark-app.yaml
apiVersion: "sparkoperator.k8s.io/v1beta1"
kind: SparkApplication
metadata:
name: spark-pi
namespace: {project}
spec:
type: Scala
mode: cluster
image: "gcr.io/spark-operator/spark:v2.4.0"
imagePullPolicy: Always
mainClass: org.apache.spark.examples.SparkPi
mainApplicationFile: "local:///opt/spark/examples/jars/spark-examples_2.11-2.4.0.jar"
sparkVersion: "2.4.0"
restartPolicy:
type: Never
volumes:
- name: "test-volume"
hostPath:
path: "/tmp"
type: Directory
driver:
cores: 1
coreLimit: "1000m"
memory: "512m"
labels:
version: 2.4.0
serviceAccount: spark
volumeMounts:
- name: "test-volume"
mountPath: "/tmp"
executor:
cores: 1
instances: 1
memory: "512m"
labels:
version: 2.4.0
volumeMounts:
- name: "test-volume"
mountPath: "/tmp"
Le të ekzekutojmë detyrën e përshkruar përmes sparkctl:
sparkctl create spark-app.yaml -n {project}
Le të shqyrtojmë listën e detyrave të ekzekutuara të Spark:
sparkctl list -n {project}
Le të shqyrtojmë listën e ngjarjeve të detyrës së ekzekutuar të Spark:
sparkctl event spark-pi -n {project} -f
Le të shqyrtojmë statusin e detyrës së ekzekutuar të Spark:
sparkctl status spark-pi -n {project}
Më në fund, dëshiroj të shqyrtoj faktorët negativë të përdorimit të versionit aktual të stabilizuar të Spark (2.4.5) në Kubernetes:
- Minusi i parë, dhe ndoshta kryesor, është mungesa e Loksalitetit të Dhënave. Pavarësisht nga të gjitha disavantazhet, YARN kishte dhe avantazhe në përdorimin e tij, për shembull, principi i dërgimit të kodit tek të dhënat (e jo të dhënat tek kodi). Falë këtij principi, detyrat Spark kryheshin në nyjat ku ndodheshin të dhënat që merrnin pjesë në llogaritje, duke e reduktuar ndjeshëm kohën e dërgimit të të dhënave përmes rrjetit. Kur përdorim Kubernetes, përballëjme me nevojën për të lëvizur të dhënat nëpër rrjet që janë të angazhuara në punën e detyrës. Nëse ato janë mjaft të mëdha, koha e ekzekutimit të detyrës mund të rritet ndjeshëm, si dhe do të kërkohet një hapësirë e konsiderueshme disku e caktuar për instancat e detyrës Spark për ruajtjen e përkohshme. Ky disavantazh mund të reduktohet duke përdorur mjete softuerike të specializuara që sigurojnë loksalitetin e të dhënave në Kubernetes (për shembull, Alluxio), por kjo në thelb do të thotë se është e nevojshme të ruhet njëkopje e plotë e të dhënave në nyjat e klustrit Kubernetes.
- Disavantazhi i dytĂ« i rĂ«ndĂ«sishĂ«m Ă«shtĂ« siguria. Nga e drejta, funksionet qĂ« kanĂ« tĂ« bĂ«jnĂ« me sigurimin e sigurisĂ« lidhur me ekzekutimin e detyrave Spark janĂ« tĂ« çactivizuara, dhe opsioni i pĂ«rdorimit tĂ« Kerberos nĂ« dokumentacionin zyrtar nuk Ă«shtĂ« mbuluar (ndonĂ«se parametrat pĂ«rkatĂ«s u shfaqĂ«n nĂ« versionin 3.0.0, qĂ« do tĂ« kĂ«rkojĂ« punĂ« shtesĂ«), dhe nĂ« dokumentacionin pĂ«r sigurimin e sigurisĂ« gjatĂ« pĂ«rdorimit tĂ« Spark (https://spark.apache.org/docs/2.4.5/security.html) si depozitues çelĂ«sash pĂ«rmenden vetĂ«m YARN, Mesos dhe Klienti Standalone. Gjithashtu, pĂ«rdoruesi, nĂ«n tĂ« cilin ekzekutohen detyrat Spark, nuk mund tĂ« pĂ«rcaktohet drejtpĂ«rdrejt â ne vetĂ«m caktuam njĂ« llogari shĂ«rbimi, nĂ«n tĂ« cilĂ«n do tĂ« punojĂ« pod-i, ndĂ«rsa pĂ«rdoruesi zgjidhet sipas politikave tĂ« vendosura pĂ«r sigurinĂ«. NĂ« kĂ«tĂ« mĂ«nyrĂ«, ose pĂ«rdoret pĂ«rdoruesi root, qĂ« nuk Ă«shtĂ« i sigurt nĂ« njĂ« mjedis prodhimi, ose njĂ« pĂ«rdorues me UID rastĂ«sor, qĂ« Ă«shtĂ« i paqartĂ« kur vjen puna pĂ«r shpĂ«rndarjen e tĂ« drejtave tĂ« aksesit nĂ« tĂ« dhĂ«na (qĂ« zgjidhet pĂ«rmes krijimit tĂ« PodSecurityPolicies dhe lidhjes sĂ« tyre me llogaritĂ« pĂ«rkatĂ«se shĂ«rbyese). Aktualisht, kjo zgjidhet ose duke vendosur tĂ« gjitha skedarĂ«t e nevojshĂ«m drejtpĂ«rdrejt nĂ« imazhin Docker, ose duke modifikuar skriptin e ekzekutimit tĂ« Spark pĂ«r tĂ« pĂ«rdorur mekanizmin e ruajtjes dhe marrjes sĂ« sekretĂ«ve, tĂ« pranuar nĂ« organizatĂ«n tuaj.
- Nisja e detyrave Spark me Kubernetes Ă«shtĂ« ende nĂ« njĂ« gjendje eksperimentale dhe nĂ« tĂ« ardhmen ka shumĂ« mundĂ«si qĂ« tĂ« ndodhin ndryshime tĂ« rĂ«ndĂ«sishme nĂ« artefaktet e pĂ«rdorura (skedarĂ«t e konfigurimit, imazhet bazĂ« tĂ« Docker-it dhe skenarĂ«t e nisjes). NĂ« tĂ« vĂ«rtetĂ« â gjatĂ« pĂ«rgatitjes sĂ« materialit u testuan versionet 2.3.0 dhe 2.4.5, dhe sjellja ishte ndjeshĂ«m e ndryshme.
Do tĂ« presim azhurnimet â pak kohĂ« mĂ« parĂ« doli versioni i ri i Spark (3.0.0), i cili solli ndryshime tĂ« dukshme nĂ« funksionimin e Spark nĂ« Kubernetes, por mbajti statusin eksperimental tĂ« mbĂ«shtetjes pĂ«r kĂ«tĂ« menaxher burimesh. Ndoshta, azhurnimet e ardhshme do tĂ« lejojnĂ« me tĂ« vĂ«rtetĂ« tĂ« rekomandohet braktisja e YARN dhe tĂ« nisen detyrat Spark nĂ« Kubernetes, pa u shqetĂ«suar pĂ«r sigurinĂ« e sistemit tuaj dhe pa pasur nevojĂ« pĂ«r pĂ«rmirĂ«simin e komponentĂ«ve funksionalĂ« nga ana juaj.
Fin.
Burimi: habr.com


