కుబెర్నెట్స్‌లో అపాచీ స్పార్క్ రన్ అవుతోంది

ప్రియమైన పాఠకులారా, శుభ మధ్యాహ్నం. ఈ రోజు మనం అపాచీ స్పార్క్ మరియు దాని అభివృద్ధి అవకాశాల గురించి కొంచెం మాట్లాడుతాము.

కుబెర్నెట్స్‌లో అపాచీ స్పార్క్ రన్ అవుతోంది

బిగ్ డేటా యొక్క ఆధునిక ప్రపంచంలో, Apache Spark అనేది బ్యాచ్ డేటా ప్రాసెసింగ్ టాస్క్‌లను అభివృద్ధి చేయడానికి వాస్తవ ప్రమాణం. అదనంగా, ఇది మైక్రో బ్యాచ్ కాన్సెప్ట్‌లో పనిచేసే స్ట్రీమింగ్ అప్లికేషన్‌లను రూపొందించడానికి కూడా ఉపయోగించబడుతుంది, చిన్న భాగాలలో డేటాను ప్రాసెస్ చేయడం మరియు షిప్పింగ్ చేయడం (స్పార్క్ స్ట్రక్చర్డ్ స్ట్రీమింగ్). మరియు సాంప్రదాయకంగా ఇది మొత్తం హడూప్ స్టాక్‌లో భాగంగా ఉంది, YARN (లేదా కొన్ని సందర్భాల్లో Apache Mesos)ని రిసోర్స్ మేనేజర్‌గా ఉపయోగిస్తుంది. 2020 నాటికి, మంచి హడూప్ పంపిణీలు లేకపోవడం వల్ల చాలా కంపెనీలకు దాని సాంప్రదాయ రూపంలో దాని ఉపయోగం ప్రశ్నార్థకమైంది - HDP మరియు CDH అభివృద్ధి ఆగిపోయింది, CDH బాగా అభివృద్ధి చెందలేదు మరియు అధిక ధరను కలిగి ఉంది మరియు మిగిలిన హడూప్ సరఫరాదారులు ఉనికిలో ఉండదు లేదా మసక భవిష్యత్తును కలిగి ఉంటుంది. అందువల్ల, కుబెర్నెట్‌లను ఉపయోగించి అపాచీ స్పార్క్‌ను ప్రారంభించడం కమ్యూనిటీ మరియు పెద్ద కంపెనీలలో ఆసక్తిని పెంచుతుంది - ప్రైవేట్ మరియు పబ్లిక్ క్లౌడ్‌లలో కంటైనర్ ఆర్కెస్ట్రేషన్ మరియు రిసోర్స్ మేనేజ్‌మెంట్‌లో ప్రమాణంగా మారింది, ఇది YARNలో స్పార్క్ టాస్క్‌ల యొక్క అసౌకర్య వనరుల షెడ్యూల్‌తో సమస్యను పరిష్కరిస్తుంది మరియు అందిస్తుంది. అన్ని పరిమాణాలు మరియు చారల కంపెనీల కోసం అనేక వాణిజ్య మరియు బహిరంగ పంపిణీలతో స్థిరంగా అభివృద్ధి చెందుతున్న వేదిక. అదనంగా, జనాదరణ పొందిన నేపథ్యంలో, చాలా మంది ఇప్పటికే వారి స్వంత సంస్థాపనలను పొందగలిగారు మరియు దాని ఉపయోగంలో వారి నైపుణ్యాన్ని పెంచుకున్నారు, ఇది కదలికను సులభతరం చేస్తుంది.

వెర్షన్ 2.3.0తో ప్రారంభించి, అపాచీ స్పార్క్ కుబెర్నెటెస్ క్లస్టర్‌లో టాస్క్‌లను అమలు చేయడానికి అధికారిక మద్దతును పొందింది మరియు ఈ రోజు, మేము ఈ విధానం యొక్క ప్రస్తుత పరిపక్వత, దాని ఉపయోగం కోసం వివిధ ఎంపికలు మరియు అమలు సమయంలో ఎదురయ్యే ఆపదల గురించి మాట్లాడుతాము.

అన్నింటిలో మొదటిది, Apache Spark ఆధారంగా టాస్క్‌లు మరియు అప్లికేషన్‌లను అభివృద్ధి చేసే ప్రక్రియను చూద్దాం మరియు మీరు Kubernetes క్లస్టర్‌లో టాస్క్‌ను అమలు చేయాల్సిన సాధారణ సందర్భాలను హైలైట్ చేయండి. ఈ పోస్ట్‌ను సిద్ధం చేయడంలో, OpenShift పంపిణీగా ఉపయోగించబడుతుంది మరియు దాని కమాండ్ లైన్ యుటిలిటీ (oc)కి సంబంధించిన ఆదేశాలు ఇవ్వబడతాయి. ఇతర Kubernetes పంపిణీల కోసం, ప్రామాణిక Kubernetes కమాండ్ లైన్ యుటిలిటీ (kubectl) నుండి సంబంధిత ఆదేశాలు లేదా వాటి అనలాగ్‌లు (ఉదాహరణకు, oc adm పాలసీ కోసం) ఉపయోగించబడతాయి.

మొదటి ఉపయోగం కేసు - స్పార్క్-సమర్పణ

టాస్క్‌లు మరియు అప్లికేషన్‌ల అభివృద్ధి సమయంలో, డెవలపర్ డేటా పరివర్తనను డీబగ్ చేయడానికి టాస్క్‌లను అమలు చేయాలి. సిద్ధాంతపరంగా, స్టబ్‌లను ఈ ప్రయోజనాల కోసం ఉపయోగించవచ్చు, అయితే ఎండ్ సిస్టమ్‌ల యొక్క నిజమైన (పరీక్ష అయినప్పటికీ) ఉదాహరణల భాగస్వామ్యంతో అభివృద్ధి ఈ తరగతి టాస్క్‌లలో వేగంగా మరియు మెరుగ్గా ఉన్నట్లు నిరూపించబడింది. ఎండ్ సిస్టమ్‌ల యొక్క నిజమైన సందర్భాలలో మేము డీబగ్ చేసినప్పుడు, రెండు దృశ్యాలు సాధ్యమే:

  • డెవలపర్ స్థానికంగా స్వతంత్ర మోడ్‌లో స్పార్క్ టాస్క్‌ను అమలు చేస్తారు;

    కుబెర్నెట్స్‌లో అపాచీ స్పార్క్ రన్ అవుతోంది

  • ఒక డెవలపర్ టెస్ట్ లూప్‌లో కుబెర్నెటెస్ క్లస్టర్‌లో స్పార్క్ టాస్క్‌ను అమలు చేస్తాడు.

    కుబెర్నెట్స్‌లో అపాచీ స్పార్క్ రన్ అవుతోంది

మొదటి ఎంపికకు ఉనికిలో హక్కు ఉంది, కానీ అనేక ప్రతికూలతలు ఉన్నాయి:

  • ప్రతి డెవలపర్‌కు పని స్థలం నుండి అతనికి అవసరమైన ముగింపు సిస్టమ్‌ల యొక్క అన్ని సందర్భాల్లో యాక్సెస్ అందించాలి;
  • అభివృద్ధి చేస్తున్న పనిని అమలు చేయడానికి వర్కింగ్ మెషీన్‌లో తగినంత మొత్తంలో వనరులు అవసరం.

రెండవ ఎంపికకు ఈ ప్రతికూలతలు లేవు, ఎందుకంటే కుబెర్నెటెస్ క్లస్టర్‌ని ఉపయోగించడం వలన మీరు రన్నింగ్ టాస్క్‌లకు అవసరమైన రిసోర్స్ పూల్‌ని కేటాయించవచ్చు మరియు ఎండ్ సిస్టమ్ ఇన్‌స్టాన్స్‌లకు అవసరమైన యాక్సెస్‌ను అందించవచ్చు, కుబెర్నెట్స్ రోల్ మోడల్‌ని ఉపయోగించి దానికి యాక్సెస్‌ను సులభంగా అందిస్తుంది. అభివృద్ధి బృందంలోని సభ్యులందరూ. దీనిని మొదటి ఉపయోగ సందర్భంగా హైలైట్ చేద్దాం - టెస్ట్ సర్క్యూట్‌లోని కుబెర్నెట్స్ క్లస్టర్‌లో స్థానిక డెవలపర్ మెషీన్ నుండి స్పార్క్ టాస్క్‌లను ప్రారంభించడం.

స్థానికంగా అమలు చేయడానికి స్పార్క్‌ని సెటప్ చేసే ప్రక్రియ గురించి మరింత మాట్లాడుకుందాం. స్పార్క్‌ని ఉపయోగించడం ప్రారంభించడానికి మీరు దీన్ని ఇన్‌స్టాల్ చేయాలి:

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

పూర్తి బిల్డ్‌కి చాలా సమయం పడుతుంది మరియు డాకర్ ఇమేజ్‌లను సృష్టించడానికి మరియు వాటిని కుబెర్నెట్స్ క్లస్టర్‌లో రన్ చేయడానికి, మీకు నిజంగా “అసెంబ్లీ/” డైరెక్టరీ నుండి జార్ ఫైల్‌లు మాత్రమే అవసరం, కాబట్టి మీరు ఈ సబ్‌ప్రాజెక్ట్‌ను మాత్రమే రూపొందించగలరు:

./build/mvn -f ./assembly/pom.xml -Pkubernetes -DskipTests clean package

Kubernetesలో Spark జాబ్‌లను అమలు చేయడానికి, మీరు బేస్ ఇమేజ్‌గా ఉపయోగించడానికి డాకర్ చిత్రాన్ని సృష్టించాలి. ఇక్కడ 2 సాధ్యమైన విధానాలు ఉన్నాయి:

  • రూపొందించబడిన డాకర్ ఇమేజ్ ఎక్జిక్యూటబుల్ స్పార్క్ టాస్క్ కోడ్‌ను కలిగి ఉంటుంది;
  • సృష్టించబడిన చిత్రం స్పార్క్ మరియు అవసరమైన డిపెండెన్సీలను మాత్రమే కలిగి ఉంటుంది, ఎక్జిక్యూటబుల్ కోడ్ రిమోట్‌గా హోస్ట్ చేయబడింది (ఉదాహరణకు, HDFSలో).

ముందుగా, స్పార్క్ టాస్క్ యొక్క పరీక్ష ఉదాహరణను కలిగి ఉన్న డాకర్ చిత్రాన్ని రూపొందిద్దాం. డాకర్ చిత్రాలను రూపొందించడానికి, స్పార్క్ "డాకర్-ఇమేజ్-టూల్" అనే యుటిలిటీని కలిగి ఉంది. దానిపై సహాయాన్ని అధ్యయనం చేద్దాం:

./bin/docker-image-tool.sh --help

దాని సహాయంతో, మీరు డాకర్ చిత్రాలను సృష్టించవచ్చు మరియు వాటిని రిమోట్ రిజిస్ట్రీలకు అప్‌లోడ్ చేయవచ్చు, కానీ డిఫాల్ట్‌గా దీనికి అనేక ప్రతికూలతలు ఉన్నాయి:

  • విఫలం లేకుండా ఒకేసారి 3 డాకర్ చిత్రాలను సృష్టిస్తుంది - 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

దాని సహాయంతో, మేము స్పార్క్‌ని ఉపయోగించి పైని లెక్కించడానికి ఒక టెస్ట్ టాస్క్‌ని కలిగి ఉన్న ప్రాథమిక స్పార్క్ చిత్రాన్ని సమీకరించాము (ఇక్కడ {docker-registry-url} అనేది మీ డాకర్ ఇమేజ్ రిజిస్ట్రీ యొక్క URL, {repo} అనేది రిజిస్ట్రీలోని రిపోజిటరీ పేరు, ఇది OpenShift , {image-name} - చిత్రం పేరు (చిత్రాల యొక్క మూడు-స్థాయి విభజనను ఉపయోగించినట్లయితే, ఉదాహరణకు, Red Hat OpenShift ఇమేజ్‌ల ఇంటిగ్రేటెడ్ రిజిస్ట్రీలో వలె), {tag} - దీని యొక్క ట్యాగ్‌తో సరిపోలుతుంది చిత్రం యొక్క వెర్షన్):

./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

కన్సోల్ యుటిలిటీని ఉపయోగించి OKD క్లస్టర్‌కి లాగిన్ చేయండి (ఇక్కడ {OKD-API-URL} అనేది OKD క్లస్టర్ API URL):

oc login {OKD-API-URL}

డాకర్ రిజిస్ట్రీలో అధికారం కోసం ప్రస్తుత వినియోగదారు టోకెన్‌ని పొందండి:

oc whoami -t

OKD క్లస్టర్ యొక్క అంతర్గత డాకర్ రిజిస్ట్రీకి లాగిన్ చేయండి (మునుపటి ఆదేశాన్ని ఉపయోగించి పొందిన టోకెన్‌ను మేము పాస్‌వర్డ్‌గా ఉపయోగిస్తాము):

docker login {docker-registry-url}

అసెంబుల్ చేసిన డాకర్ ఇమేజ్‌ని డాకర్ రిజిస్ట్రీ OKDకి అప్‌లోడ్ చేద్దాం:

./bin/docker-image-tool-upd.sh -r {docker-registry-url}/{repo} -i {image-name} -t {tag} push

అసెంబుల్ చేసిన చిత్రం OKDలో అందుబాటులో ఉందో లేదో తనిఖీ చేద్దాం. దీన్ని చేయడానికి, సంబంధిత ప్రాజెక్ట్ యొక్క చిత్రాల జాబితాతో బ్రౌజర్‌లో URLని తెరవండి (ఇక్కడ {project} అనేది OpenShift క్లస్టర్‌లోని ప్రాజెక్ట్ పేరు, {OKD-WEBUI-URL} అనేది OpenShift వెబ్ కన్సోల్ యొక్క URL. ) - https://{OKD-WEBUI-URL}/console /project/{project}/browse/images/{image-name}.

టాస్క్‌లను అమలు చేయడానికి, పాడ్‌లను రూట్‌గా అమలు చేయడానికి ప్రత్యేక అధికారాలతో సేవా ఖాతా సృష్టించబడాలి (మేము ఈ అంశాన్ని తర్వాత చర్చిస్తాము):

oc create sa spark -n {project}
oc adm policy add-scc-to-user anyuid -z spark -n {project}

సృష్టించిన సేవా ఖాతా మరియు డాకర్ చిత్రాన్ని పేర్కొంటూ OKD క్లస్టర్‌కు స్పార్క్ టాస్క్‌ను ప్రచురించడానికి స్పార్క్-సబ్మిట్ ఆదేశాన్ని అమలు చేద్దాం:

 /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

ఇక్కడ:

-పేరు - కుబెర్నెట్స్ పాడ్‌ల పేరు ఏర్పడటంలో పాల్గొనే పని పేరు;

-క్లాస్ — ఎక్జిక్యూటబుల్ ఫైల్ క్లాస్, టాస్క్ ప్రారంభమైనప్పుడు అంటారు;

—conf — స్పార్క్ కాన్ఫిగరేషన్ పారామితులు;

spark.executor.instances — ప్రారంభించాల్సిన స్పార్క్ ఎగ్జిక్యూటర్‌ల సంఖ్య;

spark.kubernetes.authenticate.driver.serviceAccountName - పాడ్‌లను ప్రారంభించేటప్పుడు ఉపయోగించే Kubernetes సేవా ఖాతా పేరు (Kubernetes APIతో పరస్పర చర్య చేస్తున్నప్పుడు భద్రతా సందర్భం మరియు సామర్థ్యాలను నిర్వచించడానికి);

spark.kubernetes.namespace — డ్రైవర్ మరియు ఎగ్జిక్యూటర్ పాడ్‌లు ప్రారంభించబడే కుబెర్నెట్స్ నేమ్‌స్పేస్;

spark.submit.deployMode — స్పార్క్‌ను ప్రారంభించే పద్ధతి (ప్రామాణిక స్పార్క్-సమర్పణ "క్లస్టర్" కోసం ఉపయోగించబడుతుంది, స్పార్క్ ఆపరేటర్ మరియు స్పార్క్ "క్లయింట్" యొక్క తదుపరి సంస్కరణల కోసం);

spark.kubernetes.container.image - పాడ్‌లను లాంచ్ చేయడానికి ఉపయోగించే డాకర్ ఇమేజ్;

spark.master - Kubernetes API URL (బాహ్య పేర్కొనబడింది కాబట్టి స్థానిక మెషీన్ నుండి యాక్సెస్ జరుగుతుంది);

local:// అనేది డాకర్ ఇమేజ్ లోపల ఎక్జిక్యూటబుల్ స్పార్క్‌కి మార్గం.

మేము సంబంధిత OKD ప్రాజెక్ట్‌కి వెళ్లి, సృష్టించిన పాడ్‌లను అధ్యయనం చేస్తాము - https://{OKD-WEBUI-URL}/console/project/{project}/browse/pods.

అభివృద్ధి ప్రక్రియను సులభతరం చేయడానికి, మరొక ఎంపికను ఉపయోగించవచ్చు, దీనిలో Spark యొక్క సాధారణ బేస్ ఇమేజ్ సృష్టించబడుతుంది, అమలు చేయడానికి అన్ని టాస్క్‌ల ద్వారా ఉపయోగించబడుతుంది మరియు ఎక్జిక్యూటబుల్ ఫైల్‌ల స్నాప్‌షాట్‌లు బాహ్య నిల్వకు ప్రచురించబడతాయి (ఉదాహరణకు, హడూప్) మరియు కాల్ చేసినప్పుడు పేర్కొనబడతాయి. స్పార్క్-ఒక లింక్‌గా సమర్పించండి. ఈ సందర్భంలో, మీరు డాకర్ చిత్రాలను పునర్నిర్మించకుండా స్పార్క్ టాస్క్‌ల యొక్క విభిన్న సంస్కరణలను అమలు చేయవచ్చు, ఉదాహరణకు, చిత్రాలను ప్రచురించడానికి 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} అనేది ఫైల్‌ను డౌన్‌లోడ్ చేయడానికి ఉపయోగించాల్సిన URL):

HTTP/1.1 307 TEMPORARY_REDIRECT
Location: {location}
Content-Length: 0

Spark ఎక్జిక్యూటబుల్ ఫైల్‌ను HDFSలోకి లోడ్ చేయండి (ఇక్కడ {path-to-local-file} అనేది ప్రస్తుత హోస్ట్‌లోని Spark ఎక్జిక్యూటబుల్ ఫైల్‌కి మార్గం):

curl -i -X PUT -T {path-to-local-file} "{location}"

దీని తర్వాత, మేము HDFSకి అప్‌లోడ్ చేసిన స్పార్క్ ఫైల్‌ని ఉపయోగించి స్పార్క్-సమర్పించవచ్చు (ఇక్కడ {class-name} అనేది టాస్క్‌ను పూర్తి చేయడానికి ప్రారంభించాల్సిన తరగతి పేరు):

/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}

HDFSని యాక్సెస్ చేయడానికి మరియు పనిని నిర్ధారించడానికి, మీరు Dockerfile మరియు entrypoint.sh స్క్రిప్ట్‌ను మార్చవలసి ఉంటుందని గమనించాలి - డిపెండెంట్ లైబ్రరీలను /opt/spark/jars డైరెక్టరీకి కాపీ చేయడానికి డాకర్‌ఫైల్‌కు ఆదేశాన్ని జోడించండి మరియు SPARK_CLASSPATHలో HDFS కాన్ఫిగరేషన్ ఫైల్‌ను ఎంట్రీ పాయింట్‌లో చేర్చండి. sh.

రెండవ ఉపయోగం కేసు - Apache Livy

ఇంకా, ఒక పనిని అభివృద్ధి చేసి, ఫలితాన్ని పరీక్షించవలసి వచ్చినప్పుడు, దానిని CI/CD ప్రక్రియలో భాగంగా ప్రారంభించడం మరియు దాని అమలు స్థితిని ట్రాక్ చేయడం అనే ప్రశ్న తలెత్తుతుంది. వాస్తవానికి, మీరు స్థానిక స్పార్క్-సమర్పించే కాల్‌ని ఉపయోగించి దీన్ని అమలు చేయవచ్చు, అయితే ఇది CI/CD అవస్థాపనను క్లిష్టతరం చేస్తుంది ఎందుకంటే దీనికి CI సర్వర్ ఏజెంట్‌లు/రన్నర్‌లలో స్పార్క్‌ను ఇన్‌స్టాల్ చేయడం మరియు కాన్ఫిగర్ చేయడం మరియు కుబెర్నెటెస్ APIకి యాక్సెస్‌ను సెటప్ చేయడం అవసరం. ఈ సందర్భంలో, Kubernetes క్లస్టర్‌లో హోస్ట్ చేయబడిన స్పార్క్ టాస్క్‌లను అమలు చేయడం కోసం Apache Livyని REST APIగా ఉపయోగించడాన్ని లక్ష్య అమలు ఎంచుకుంది. దాని సహాయంతో, మీరు సాధారణ కర్ల్ అభ్యర్థనలను ఉపయోగించి Kubernetes క్లస్టర్‌లో స్పార్క్ టాస్క్‌లను అమలు చేయవచ్చు, ఇది ఏదైనా CI సొల్యూషన్ ఆధారంగా సులభంగా అమలు చేయబడుతుంది మరియు Kubernetes APIతో ఇంటరాక్ట్ అవుతున్నప్పుడు Kubernetes క్లస్టర్‌లో దాని ప్లేస్‌మెంట్ ప్రామాణీకరణ సమస్యను పరిష్కరిస్తుంది.

కుబెర్నెట్స్‌లో అపాచీ స్పార్క్ రన్ అవుతోంది

దీనిని రెండవ ఉపయోగ సందర్భంగా హైలైట్ చేద్దాం - టెస్ట్ లూప్‌లోని కుబెర్నెట్స్ క్లస్టర్‌లో CI/CD ప్రక్రియలో భాగంగా స్పార్క్ టాస్క్‌లను అమలు చేస్తోంది.

Apache Livy గురించి కొంచెం - ఇది వెబ్ ఇంటర్‌ఫేస్‌ను అందించే HTTP సర్వర్‌గా మరియు అవసరమైన పారామితులను పాస్ చేయడం ద్వారా స్పార్క్-సమర్పణను రిమోట్‌గా ప్రారంభించేందుకు మిమ్మల్ని అనుమతించే RESTful APIగా పనిచేస్తుంది. సాంప్రదాయకంగా ఇది HDP పంపిణీలో భాగంగా రవాణా చేయబడింది, కానీ తగిన మానిఫెస్ట్ మరియు ఇలాంటి డాకర్ చిత్రాల సెట్‌ను ఉపయోగించి OKD లేదా ఏదైనా ఇతర కుబెర్నెట్స్ ఇన్‌స్టాలేషన్‌కు కూడా అమలు చేయవచ్చు - github.com/ttauveron/k8s-big-data-experiments/tree/master/livy-spark-2.3. మా విషయంలో, కింది డాకర్‌ఫైల్ నుండి స్పార్క్ వెర్షన్ 2.4.5తో సహా ఇలాంటి డాకర్ చిత్రం నిర్మించబడింది:

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"]

రూపొందించబడిన చిత్రం అంతర్గత OKD రిపోజిటరీ వంటి మీ ప్రస్తుత డాకర్ రిపోజిటరీకి నిర్మించబడి అప్‌లోడ్ చేయబడుతుంది. దీన్ని అమలు చేయడానికి, కింది మానిఫెస్ట్ ({registry-url} - డాకర్ ఇమేజ్ రిజిస్ట్రీ యొక్క URL, {image-name} - డాకర్ ఇమేజ్ పేరు, {tag} - డాకర్ ఇమేజ్ ట్యాగ్, {livy-url} - కావలసిన URLని ఉపయోగించండి సర్వర్ అందుబాటులో ఉంటుంది Livy; Red Hat OpenShiftని Kubernetes పంపిణీగా ఉపయోగించినట్లయితే “రూట్” మానిఫెస్ట్ ఉపయోగించబడుతుంది, లేకపోతే సంబంధిత Ingress లేదా సర్వీస్ మానిఫెస్ట్ రకం 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

దీన్ని వర్తింపజేసి, పాడ్‌ను విజయవంతంగా ప్రారంభించిన తర్వాత, Livy గ్రాఫికల్ ఇంటర్‌ఫేస్ లింక్‌లో అందుబాటులో ఉంటుంది: http://{livy-url}/ui. Livyతో, మేము REST అభ్యర్థనను ఉపయోగించి మా స్పార్క్ టాస్క్‌ను ప్రచురించవచ్చు, ఉదాహరణకు, పోస్ట్‌మాన్. అభ్యర్థనలతో కూడిన సేకరణ యొక్క ఉదాహరణ క్రింద ప్రదర్శించబడింది (ప్రారంభించబడిన పని యొక్క ఆపరేషన్ కోసం అవసరమైన వేరియబుల్స్‌తో కాన్ఫిగరేషన్ ఆర్గ్యుమెంట్‌లను “args” శ్రేణిలో పంపవచ్చు):

{
    "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": {}
}

సేకరణ నుండి మొదటి అభ్యర్థనను అమలు చేద్దాం, OKD ఇంటర్‌ఫేస్‌కి వెళ్లి, టాస్క్ విజయవంతంగా ప్రారంభించబడిందో లేదో తనిఖీ చేయండి - https://{OKD-WEBUI-URL}/console/project/{project}/browse/pods. అదే సమయంలో, Livy ఇంటర్‌ఫేస్ (http://{livy-url}/ui)లో ఒక సెషన్ కనిపిస్తుంది, దానిలో, Livy API లేదా గ్రాఫికల్ ఇంటర్‌ఫేస్‌ని ఉపయోగించి, మీరు పని పురోగతిని ట్రాక్ చేయవచ్చు మరియు సెషన్‌ను అధ్యయనం చేయవచ్చు. చిట్టాలు.

ఇప్పుడు Livy ఎలా పనిచేస్తుందో చూపిద్దాం. దీన్ని చేయడానికి, Livy సర్వర్‌తో పాడ్ లోపల Livy కంటైనర్ లాగ్‌లను పరిశీలిద్దాం - https://{OKD-WEBUI-URL}/console/project/{project}/browse/pods/{livy-pod-name }?టాబ్=లాగ్‌లు. "livy" అనే కంటైనర్‌లో Livy REST APIకి కాల్ చేస్తున్నప్పుడు, మనం పైన ఉపయోగించిన (ఇక్కడ {livy-pod-name} అనేది సృష్టించబడిన పాడ్ పేరు) మాదిరిగానే స్పార్క్-సమర్పణ అమలు చేయబడుతుందని వాటి నుండి మనం చూడవచ్చు. Livy సర్వర్‌తో). సేకరణ రెండవ ప్రశ్నను కూడా పరిచయం చేస్తుంది, ఇది Livy సర్వర్‌ని ఉపయోగించి ఎక్జిక్యూటబుల్ స్పార్క్‌ని రిమోట్‌గా హోస్ట్ చేసే పనులను అమలు చేయడానికి మిమ్మల్ని అనుమతిస్తుంది.

మూడవ ఉపయోగం కేసు - స్పార్క్ ఆపరేటర్

ఇప్పుడు పని పరీక్షించబడింది, దీన్ని క్రమం తప్పకుండా అమలు చేయాలనే ప్రశ్న తలెత్తుతుంది. Kubernetes క్లస్టర్‌లో విధులను క్రమం తప్పకుండా అమలు చేయడానికి స్థానిక మార్గం CronJob ఎంటిటీ మరియు మీరు దానిని ఉపయోగించవచ్చు, కానీ ప్రస్తుతానికి Kubernetesలో అప్లికేషన్‌లను నిర్వహించడానికి ఆపరేటర్‌ల ఉపయోగం బాగా ప్రాచుర్యం పొందింది మరియు Spark కోసం చాలా పరిణతి చెందిన ఆపరేటర్ ఉంది, ఇది కూడా ఎంటర్‌ప్రైజ్-స్థాయి సొల్యూషన్స్‌లో ఉపయోగించబడుతుంది (ఉదాహరణకు, లైట్‌బెండ్ ఫాస్ట్‌డేటా ప్లాట్‌ఫారమ్). మేము దీనిని ఉపయోగించమని సిఫార్సు చేస్తున్నాము - Spark (2.4.5) యొక్క ప్రస్తుత స్థిరమైన సంస్కరణ Kubernetesలో Spark టాస్క్‌లను అమలు చేయడానికి పరిమిత కాన్ఫిగరేషన్ ఎంపికలను కలిగి ఉంది, అయితే తదుపరి ప్రధాన సంస్కరణ (3.0.0) Kubernetes కోసం పూర్తి మద్దతును ప్రకటించింది, కానీ దాని విడుదల తేదీ తెలియదు. . స్పార్క్ ఆపరేటర్ ముఖ్యమైన కాన్ఫిగరేషన్ ఎంపికలను జోడించడం ద్వారా ఈ లోపాన్ని భర్తీ చేస్తుంది (ఉదాహరణకు, స్పార్క్ పాడ్‌లకు హడూప్ యాక్సెస్ కాన్ఫిగరేషన్‌తో కాన్ఫిగ్‌మ్యాప్‌ను మౌంట్ చేయడం) మరియు క్రమం తప్పకుండా షెడ్యూల్ చేయబడిన పనిని అమలు చేయగల సామర్థ్యం.

కుబెర్నెట్స్‌లో అపాచీ స్పార్క్ రన్ అవుతోంది
దీన్ని మూడవ వినియోగ సందర్భంగా హైలైట్ చేద్దాం - ప్రొడక్షన్ లూప్‌లో కుబెర్నెట్స్ క్లస్టర్‌లో స్పార్క్ టాస్క్‌లను క్రమం తప్పకుండా అమలు చేస్తుంది.

స్పార్క్ ఆపరేటర్ ఓపెన్ సోర్స్ మరియు Google క్లౌడ్ ప్లాట్‌ఫారమ్‌లో అభివృద్ధి చేయబడింది - github.com/GoogleCloudPlatform/spark-on-k8s-operator. దీని సంస్థాపన 3 విధాలుగా చేయవచ్చు:

  1. లైట్‌బెండ్ ఫాస్ట్‌డేటా ప్లాట్‌ఫారమ్/క్లౌడ్‌ఫ్లో ఇన్‌స్టాలేషన్‌లో భాగంగా;
  2. హెల్మ్ ఉపయోగించడం:
    helm repo add incubator http://storage.googleapis.com/kubernetes-charts-incubator
    helm install incubator/sparkoperator --namespace spark-operator
    	

  3. అధికారిక రిపోజిటరీ (https://github.com/GoogleCloudPlatform/spark-on-k8s-operator/tree/master/manifest) నుండి మానిఫెస్ట్‌లను ఉపయోగించడం. కింది వాటిని గమనించడం విలువ - Cloudflow API వెర్షన్ v1beta1తో ఆపరేటర్‌ని కలిగి ఉంది. ఈ రకమైన ఇన్‌స్టాలేషన్‌ను ఉపయోగించినట్లయితే, Spark అప్లికేషన్ మానిఫెస్ట్ వివరణలు తగిన API వెర్షన్‌తో Gitలోని ఉదాహరణ ట్యాగ్‌ల ఆధారంగా ఉండాలి, ఉదాహరణకు, "v1beta1-0.9.0-2.4.0". "వెర్షన్స్" డిక్షనరీలో ఆపరేటర్‌లో చేర్చబడిన CRD యొక్క వివరణలో ఆపరేటర్ యొక్క సంస్కరణను కనుగొనవచ్చు:
    oc get crd sparkapplications.sparkoperator.k8s.io -o yaml
    	

ఆపరేటర్ సరిగ్గా ఇన్‌స్టాల్ చేయబడితే, సంబంధిత ప్రాజెక్ట్‌లో స్పార్క్ ఆపరేటర్‌తో యాక్టివ్ పాడ్ కనిపిస్తుంది (ఉదాహరణకు, క్లౌడ్‌ఫ్లో ఇన్‌స్టాలేషన్ కోసం క్లౌడ్‌ఫ్లో స్పేస్‌లో క్లౌడ్‌ఫ్లో-ఎఫ్‌డిపి-స్పార్కోపరేటర్) మరియు “స్పార్క్ అప్లికేషన్స్” పేరుతో సంబంధిత కుబెర్నెట్స్ రిసోర్స్ రకం కనిపిస్తుంది. . మీరు కింది ఆదేశంతో అందుబాటులో ఉన్న స్పార్క్ అప్లికేషన్‌లను అన్వేషించవచ్చు:

oc get sparkapplications -n {project}

స్పార్క్ ఆపరేటర్‌ని ఉపయోగించి పనులను అమలు చేయడానికి మీరు 3 పనులను చేయాలి:

  • అవసరమైన అన్ని లైబ్రరీలు, అలాగే కాన్ఫిగరేషన్ మరియు ఎక్జిక్యూటబుల్ ఫైల్‌లను కలిగి ఉన్న డాకర్ చిత్రాన్ని సృష్టించండి. లక్ష్య చిత్రంలో, ఇది CI/CD దశలో సృష్టించబడిన చిత్రం మరియు పరీక్ష క్లస్టర్‌లో పరీక్షించబడింది;
  • Kubernetes క్లస్టర్ నుండి యాక్సెస్ చేయగల రిజిస్ట్రీకి డాకర్ చిత్రాన్ని ప్రచురించండి;
  • "SparkApplication" రకంతో మానిఫెస్ట్‌ను రూపొందించండి మరియు ప్రారంభించాల్సిన పని యొక్క వివరణ. ఉదాహరణ మానిఫెస్ట్‌లు అధికారిక రిపోజిటరీలో అందుబాటులో ఉన్నాయి (ఉదా. github.com/GoogleCloudPlatform/spark-on-k8s-operator/blob/v1beta1-0.9.0-2.4.0/examples/spark-pi.yaml) మ్యానిఫెస్టోలో గమనించవలసిన ముఖ్యమైన అంశాలు ఉన్నాయి:
    1. “apiVersion” నిఘంటువు తప్పనిసరిగా ఆపరేటర్ సంస్కరణకు సంబంధించిన API సంస్కరణను సూచించాలి;
    2. “metadata.namespace” నిఘంటువు తప్పనిసరిగా అప్లికేషన్ ప్రారంభించబడే నేమ్‌స్పేస్‌ను సూచించాలి;
    3. “spec.image” నిఘంటువు తప్పనిసరిగా యాక్సెస్ చేయగల రిజిస్ట్రీలో సృష్టించబడిన డాకర్ ఇమేజ్ చిరునామాను కలిగి ఉండాలి;
    4. “spec.mainClass” నిఘంటువు తప్పనిసరిగా స్పార్క్ టాస్క్ క్లాస్‌ని కలిగి ఉండాలి, అది ప్రక్రియ ప్రారంభమైనప్పుడు అమలు చేయాలి;
    5. “spec.mainApplicationFile” నిఘంటువు తప్పనిసరిగా ఎక్జిక్యూటబుల్ జార్ ఫైల్‌కు పాత్‌ను కలిగి ఉండాలి;
    6. "spec.sparkVersion" నిఘంటువు తప్పనిసరిగా ఉపయోగించబడుతున్న స్పార్క్ సంస్కరణను సూచించాలి;
    7. “spec.driver.serviceAccount” డిక్షనరీ తప్పనిసరిగా అప్లికేషన్‌ను అమలు చేయడానికి ఉపయోగించే సంబంధిత కుబెర్నెట్స్ నేమ్‌స్పేస్‌లోని సేవా ఖాతాను పేర్కొనాలి;
    8. "spec.executor" నిఘంటువు తప్పనిసరిగా అప్లికేషన్‌కు కేటాయించబడిన వనరుల సంఖ్యను సూచించాలి;
    9. "spec.volumeMounts" నిఘంటువు తప్పనిసరిగా స్థానిక స్పార్క్ టాస్క్ ఫైల్‌లు సృష్టించబడే స్థానిక డైరెక్టరీని పేర్కొనాలి.

మానిఫెస్ట్‌ను రూపొందించడానికి ఒక ఉదాహరణ (ఇక్కడ {spark-service-account} అనేది Spark టాస్క్‌లను అమలు చేయడానికి Kubernetes క్లస్టర్‌లోని సేవా ఖాతా):

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"

ఈ మానిఫెస్ట్ ఒక సేవా ఖాతాను నిర్దేశిస్తుంది, దీని కోసం మానిఫెస్ట్‌ను ప్రచురించే ముందు, మీరు తప్పనిసరిగా స్పార్క్ అప్లికేషన్ Kubernetes API (అవసరమైతే)తో పరస్పర చర్య చేయడానికి అవసరమైన యాక్సెస్ హక్కులను అందించే అవసరమైన రోల్ బైండింగ్‌లను తప్పనిసరిగా సృష్టించాలి. మా విషయంలో, పాడ్‌లను సృష్టించడానికి అనువర్తనానికి హక్కులు అవసరం. అవసరమైన రోల్ బైండింగ్‌ని క్రియేట్ చేద్దాం:

oc adm policy add-role-to-user edit system:serviceaccount:{project}:{spark-service-account} -n {project}

ఈ మానిఫెస్ట్ స్పెసిఫికేషన్‌లో "hadoopConfigMap" పరామితి ఉండవచ్చు, ఇది డాకర్ ఇమేజ్‌లో సంబంధిత ఫైల్‌ను ముందుగా ఉంచకుండా Hadoop కాన్ఫిగరేషన్‌తో ConfigMapని పేర్కొనడానికి మిమ్మల్ని అనుమతిస్తుంది. ఇది క్రమం తప్పకుండా పనులను అమలు చేయడానికి కూడా అనుకూలంగా ఉంటుంది - “షెడ్యూల్” పరామితిని ఉపయోగించి, ఇచ్చిన పనిని అమలు చేయడానికి షెడ్యూల్‌ను పేర్కొనవచ్చు.

ఆ తర్వాత, మేము మా మానిఫెస్ట్‌ని spark-pi.yaml ఫైల్‌లో సేవ్ చేసి, దానిని మా కుబెర్నెట్స్ క్లస్టర్‌కి వర్తింపజేస్తాము:

oc apply -f spark-pi.yaml

ఇది "స్పార్క్ అప్లికేషన్స్" రకం వస్తువును సృష్టిస్తుంది:

oc get sparkapplications -n {project}
> NAME       AGE
> spark-pi   22h

ఈ సందర్భంలో, అప్లికేషన్‌తో పాడ్ సృష్టించబడుతుంది, దీని స్థితి సృష్టించబడిన "స్పార్క్ అప్లికేషన్స్"లో ప్రదర్శించబడుతుంది. మీరు దీన్ని క్రింది ఆదేశంతో చూడవచ్చు:

oc get sparkapplications spark-pi -o yaml -n {project}

పని పూర్తయిన తర్వాత, POD "పూర్తయింది" స్థితికి తరలించబడుతుంది, ఇది "స్పార్క్ అప్లికేషన్స్"లో కూడా నవీకరించబడుతుంది. అప్లికేషన్ లాగ్‌లను బ్రౌజర్‌లో లేదా కింది ఆదేశాన్ని ఉపయోగించి వీక్షించవచ్చు (ఇక్కడ {sparkapplications-pod-name} అనేది నడుస్తున్న టాస్క్ యొక్క పాడ్ పేరు):

oc logs {sparkapplications-pod-name} -n {project}

స్పార్క్ టాస్క్‌లను ప్రత్యేకమైన sparkctl యుటిలిటీని ఉపయోగించి కూడా నిర్వహించవచ్చు. దీన్ని ఇన్‌స్టాల్ చేయడానికి, రిపోజిటరీని దాని సోర్స్ కోడ్‌తో క్లోన్ చేయండి, గోను ఇన్‌స్టాల్ చేసి, ఈ యుటిలిటీని రూపొందించండి:

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

రన్నింగ్ స్పార్క్ టాస్క్‌ల జాబితాను పరిశీలిద్దాం:

sparkctl list -n {project}

స్పార్క్ టాస్క్ కోసం వివరణను క్రియేట్ చేద్దాం:

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"

sparkctlని ఉపయోగించి వివరించిన పనిని అమలు చేద్దాం:

sparkctl create spark-app.yaml -n {project}

రన్నింగ్ స్పార్క్ టాస్క్‌ల జాబితాను పరిశీలిద్దాం:

sparkctl list -n {project}

ప్రారంభించబడిన స్పార్క్ టాస్క్ యొక్క ఈవెంట్‌ల జాబితాను పరిశీలిద్దాం:

sparkctl event spark-pi -n {project} -f

నడుస్తున్న స్పార్క్ టాస్క్ స్థితిని పరిశీలిద్దాం:

sparkctl status spark-pi -n {project}

ముగింపులో, కుబెర్నెట్స్‌లో స్పార్క్ (2.4.5) యొక్క ప్రస్తుత స్థిరమైన సంస్కరణను ఉపయోగించడం వల్ల కనుగొనబడిన ప్రతికూలతలను నేను పరిగణించాలనుకుంటున్నాను:

  1. మొదటి మరియు, బహుశా, ప్రధాన ప్రతికూలత డేటా స్థానికత లేకపోవడం. YARN యొక్క అన్ని లోపాలు ఉన్నప్పటికీ, దానిని ఉపయోగించడం వల్ల ప్రయోజనాలు కూడా ఉన్నాయి, ఉదాహరణకు, డేటాకు కోడ్‌ను పంపిణీ చేసే సూత్రం (డేటా నుండి కోడ్‌కు బదులుగా). దానికి ధన్యవాదాలు, గణనలలో పాల్గొన్న డేటా ఉన్న నోడ్స్‌లో స్పార్క్ పనులు అమలు చేయబడ్డాయి మరియు నెట్‌వర్క్ ద్వారా డేటాను బట్వాడా చేయడానికి పట్టే సమయం గణనీయంగా తగ్గింది. Kubernetes ఉపయోగిస్తున్నప్పుడు, మేము నెట్‌వర్క్ అంతటా టాస్క్‌లో పాల్గొన్న డేటాను తరలించాల్సిన అవసరాన్ని ఎదుర్కొంటాము. అవి తగినంత పెద్దవిగా ఉంటే, టాస్క్ ఎగ్జిక్యూషన్ సమయం గణనీయంగా పెరుగుతుంది మరియు స్పార్క్ టాస్క్ ఇన్‌స్టాన్స్‌లకు వాటి తాత్కాలిక నిల్వ కోసం చాలా పెద్ద మొత్తంలో డిస్క్ స్థలం కేటాయించబడుతుంది. Kubernetes (ఉదాహరణకు, Alluxio)లో డేటా స్థానికతను నిర్ధారించే ప్రత్యేక సాఫ్ట్‌వేర్‌ను ఉపయోగించడం ద్వారా ఈ ప్రతికూలతను తగ్గించవచ్చు, అయితే దీని అర్థం కుబెర్నెట్స్ క్లస్టర్ యొక్క నోడ్‌లలో డేటా యొక్క పూర్తి కాపీని నిల్వ చేయాల్సిన అవసరం ఉంది.
  2. రెండవ ముఖ్యమైన ప్రతికూలత భద్రత. డిఫాల్ట్‌గా, రన్నింగ్ స్పార్క్ టాస్క్‌లకు సంబంధించిన సెక్యూరిటీ-సంబంధిత ఫీచర్‌లు నిలిపివేయబడ్డాయి, అధికారిక డాక్యుమెంటేషన్‌లో Kerberos ఉపయోగం కవర్ చేయబడదు (సంబంధిత ఎంపికలు వెర్షన్ 3.0.0లో ప్రవేశపెట్టబడినప్పటికీ, దీనికి అదనపు పని అవసరం), మరియు భద్రతా డాక్యుమెంటేషన్ Spark (https://spark.apache.org/docs/2.4.5/security.html) ఉపయోగించి YARN, Mesos మరియు స్వతంత్ర క్లస్టర్ మాత్రమే కీ స్టోర్‌లుగా కనిపిస్తాయి. అదే సమయంలో, స్పార్క్ టాస్క్‌లు ప్రారంభించబడిన వినియోగదారుని నేరుగా పేర్కొనలేరు - మేము అది పనిచేసే సేవా ఖాతాను మాత్రమే నిర్దేశిస్తాము మరియు వినియోగదారు కాన్ఫిగర్ చేయబడిన భద్రతా విధానాల ఆధారంగా ఎంపిక చేయబడతారు. ఈ విషయంలో, ఉత్పాదక వాతావరణంలో సురక్షితమైన రూట్ వినియోగదారు లేదా యాదృచ్ఛిక UID ఉన్న వినియోగదారు ఉపయోగించబడతారు, ఇది డేటాకు యాక్సెస్ హక్కులను పంపిణీ చేసేటప్పుడు అసౌకర్యంగా ఉంటుంది (దీనిని PodSecurityPolicies సృష్టించడం ద్వారా మరియు వాటిని లింక్ చేయడం ద్వారా పరిష్కరించవచ్చు సంబంధిత సేవా ఖాతాలు). ప్రస్తుతం, అవసరమైన అన్ని ఫైల్‌లను నేరుగా డాకర్ ఇమేజ్‌లో ఉంచడం లేదా మీ సంస్థలో స్వీకరించిన రహస్యాలను నిల్వ చేయడం మరియు తిరిగి పొందడం కోసం మెకానిజంను ఉపయోగించడానికి స్పార్క్ లాంచ్ స్క్రిప్ట్‌ను సవరించడం దీనికి పరిష్కారం.
  3. Kubernetesని ఉపయోగించి స్పార్క్ జాబ్‌లను అమలు చేయడం అధికారికంగా ఇప్పటికీ ప్రయోగాత్మక మోడ్‌లో ఉంది మరియు భవిష్యత్తులో ఉపయోగించిన కళాఖండాలలో (కాన్ఫిగరేషన్ ఫైల్‌లు, డాకర్ బేస్ ఇమేజ్‌లు మరియు లాంచ్ స్క్రిప్ట్‌లు) గణనీయమైన మార్పులు ఉండవచ్చు. నిజానికి, మెటీరియల్‌ని సిద్ధం చేస్తున్నప్పుడు, 2.3.0 మరియు 2.4.5 వెర్షన్‌లు పరీక్షించబడ్డాయి, ప్రవర్తన గణనీయంగా భిన్నంగా ఉంటుంది.

అప్‌డేట్‌ల కోసం వేచి చూద్దాం - స్పార్క్ (3.0.0) యొక్క కొత్త వెర్షన్ ఇటీవల విడుదల చేయబడింది, ఇది కుబెర్నెట్స్‌లో స్పార్క్ పనిలో గణనీయమైన మార్పులను తీసుకువచ్చింది, అయితే ఈ రిసోర్స్ మేనేజర్‌కు మద్దతు యొక్క ప్రయోగాత్మక స్థితిని నిలుపుకుంది. బహుశా తదుపరి నవీకరణలు మీ సిస్టమ్ యొక్క భద్రతకు భయపడకుండా మరియు స్వతంత్రంగా ఫంక్షనల్ భాగాలను సవరించాల్సిన అవసరం లేకుండానే YARNని వదలివేయమని మరియు కుబెర్నెట్స్‌లో స్పార్క్ టాస్క్‌లను అమలు చేయమని పూర్తిగా సిఫార్సు చేయడం సాధ్యపడుతుంది.

ఫిన్.

మూలం: www.habr.com

ఒక వ్యాఖ్యను జోడించండి