Nisemi Apache Spark në Kubernetes

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

Nisemi Apache Spark në Kubernetes

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;

    Nisemi Apache Spark në Kubernetes

  • zhvilluesi ekzekuton detyrĂ«n Spark nĂ« njĂ« klasĂ«r Kubernetes nĂ« kontur testimi.

    Nisemi Apache Spark në Kubernetes

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.

Nisemi Apache Spark 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 — github.com/ttauveron/k8s-big-data-experiments/tree/master/livy-spark-2.3. 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.

Nisemi Apache Spark në Kubernetes
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 — github.com/GoogleCloudPlatform/spark-on-k8s-operator. Instalimi i tij mund tĂ« kryhet nĂ« 3 mĂ«nyra:

  1. Si pjesë e instalimit të Lightbend FastData Platform/Cloudflow;
  2. Me ndihmën e Helm:
    helm repo add incubator http://storage.googleapis.com/kubernetes-charts-incubator
    helm install incubator/sparkoperator --namespace spark-operator
    	

  3. 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, github.com/GoogleCloudPlatform/spark-on-k8s-operator/blob/v1beta1-0.9.0-2.4.0/examples/spark-pi.yaml). Duhet tĂ« theksohen disa pika tĂ« rĂ«ndĂ«sishme nĂ« lidhje me manifestin:
    1. në fjalorin "apiVersion" duhet të përmendet versioni i API-t përkatës me versionin e operatorit;
    2. në fjalorin "metadata.namespace" duhet të shënohet hapësira emërore ku do të ekzekutohet aplikacioni;
    3. në fjalorin "spec.image" duhet të jepet adresa e imazhit të krijuar Docker në regjistrin e disponueshëm;
    4. në fjalorin "spec.mainClass" duhet të jepet klasa e detyrës Spark që kërkohet të ekzekutohet gjatë fillimit të procesit;
    5. në fjalorin "spec.mainApplicationFile" duhet të jepet rruga drejt skedarit ekzekutiv jar;
    6. në fjalorin "spec.sparkVersion" duhet të shënohet versioni i Spark-it që përdoret;
    7. 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;
    8. në fjalorin "spec.executor" duhet të jepen burimet e dedikuara aplikacionit;
    9. 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:

  1. 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.
  2. 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.
  3. 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

Blini hosting tĂ« besueshĂ«m pĂ«r faqe interneti me mbrojtje nga DDoS, serverĂ« VPS VDS đŸ”„ Blini hosting tĂ« besueshĂ«m pĂ«r faqe interneti me mbrojtje nga DDoS, serverĂ« VPS VDS | ProHoster