Հարգելի ընթերցողներ, բարի կեսօր: Այսօր մենք մի փոքր կխոսենք Apache Spark-ի և դրա զարգացման հեռանկարների մասին:
Big Data-ի ժամանակակից աշխարհում Apache Spark-ը դե ֆակտո ստանդարտ է տվյալների խմբաքանակի մշակման առաջադրանքների մշակման համար: Բացի այդ, այն նաև օգտագործվում է հոսքային հավելվածներ ստեղծելու համար, որոնք աշխատում են միկրո խմբաքանակի հայեցակարգում, մշակում և առաքում են տվյալները փոքր մասերում (Spark Structured Streaming): Եվ ավանդաբար այն եղել է Hadoop-ի ընդհանուր փաթեթի մի մասը՝ օգտագործելով YARN-ը (կամ որոշ դեպքերում Apache Mesos-ը) որպես ռեսուրսների կառավարիչ: Մինչև 2020 թվականը, դրա ավանդական ձևով օգտագործումը հարցականի տակ է ընկերությունների մեծ մասի համար՝ Hadoop-ի պատշաճ բաշխումների բացակայության պատճառով. HDP-ի և CDH-ի զարգացումը կանգ է առել, CDH-ն լավ զարգացած չէ և ունի բարձր արժեք, իսկ մնացած Hadoop մատակարարները կա՛մ դադարել է գոյություն ունենալ, կա՛մ մշուշոտ ապագա է ունեցել: Հետևաբար, Kubernetes-ի միջոցով Apache Spark-ի գործարկումը մեծ հետաքրքրություն է առաջացնում համայնքի և խոշոր ընկերությունների շրջանում. դառնալով ստանդարտ կոնտեյներների կազմակերպման և ռեսուրսների կառավարման մեջ մասնավոր և հանրային ամպերում, այն լուծում է YARN-ում Spark-ի առաջադրանքների ռեսուրսների անհարմար պլանավորման խնդիրը և ապահովում: կայուն զարգացող հարթակ՝ բազմաթիվ առևտրային և բաց բաշխումներով բոլոր չափերի և շերտերի ընկերությունների համար: Բացի այդ, հանրաճանաչության հետևանքով մեծամասնությունն արդեն հասցրել է ձեռք բերել մի քանի սեփական ինստալացիա և մեծացրել է դրանց օգտագործման փորձը, ինչը հեշտացնում է այդ քայլը:
Սկսած 2.3.0 տարբերակից, Apache Spark-ը պաշտոնական աջակցություն ստացավ Kubernetes կլաստերում առաջադրանքների կատարման համար, և այսօր մենք կխոսենք այս մոտեցման ներկայիս հասունության, դրա օգտագործման տարբեր տարբերակների և թակարդների մասին, որոնք կհանդիպեն իրականացման ընթացքում:
Նախ, եկեք նայենք Apache Spark-ի վրա հիմնված առաջադրանքների և հավելվածների մշակման գործընթացին և առանձնացնենք բնորոշ դեպքերը, երբ դուք պետք է առաջադրանք կատարեք Kubernetes կլաստերի վրա: Այս գրառումը պատրաստելիս OpenShift-ն օգտագործվում է որպես բաշխում և տրվելու են հրամանների տողի (oc) ծրագրին համապատասխան հրամաններ: Kubernetes-ի այլ բաշխումների համար կարող են օգտագործվել ստանդարտ Kubernetes հրամանի տողերի համապատասխան հրամանները (kubectl) կամ դրանց անալոգները (օրինակ՝ oc adm քաղաքականության համար):
Առաջին օգտագործման դեպք - կայծ-ներկայացնել
Առաջադրանքների և հավելվածների մշակման ընթացքում մշակողը պետք է առաջադրանքներ գործարկի տվյալների փոխակերպումը վրիպազերծելու համար: Տեսականորեն, կոճղերը կարող են օգտագործվել այս նպատակների համար, սակայն վերջնական համակարգերի իրական (թեև թեստային) օրինակների մասնակցությամբ մշակումն ապացուցվել է, որ ավելի արագ և ավելի լավ է այս դասի առաջադրանքներում: Այն դեպքում, երբ մենք վրիպազերծում ենք վերջնական համակարգերի իրական օրինակների վրա, հնարավոր է երկու սցենար.
մշակողը կատարում է Spark առաջադրանքը տեղում՝ ինքնուրույն ռեժիմով.
մշակողը կատարում է Spark առաջադրանքը Kubernetes կլաստերի վրա՝ թեստային օղակում:
Առաջին տարբերակը գոյության իրավունք ունի, բայց ենթադրում է մի շարք թերություններ.
Յուրաքանչյուր ծրագրավորող պետք է ապահովվի աշխատավայրից իրեն անհրաժեշտ վերջնական համակարգերի բոլոր ատյաններում մուտքի հնարավորություն.
մշակվող առաջադրանքը գործարկելու համար աշխատանքային մեքենայի վրա պահանջվում է բավարար քանակությամբ ռեսուրսներ:
Երկրորդ տարբերակը չունի այս թերությունները, քանի որ Kubernetes կլաստերի օգտագործումը թույլ է տալիս Ձեզ հատկացնել անհրաժեշտ ռեսուրսների լողավազան առաջադրանքների կատարման համար և ապահովել նրան անհրաժեշտ մուտք դեպի վերջնական համակարգի օրինակներ՝ ճկուն կերպով ապահովելով դրան մուտք՝ օգտագործելով Kubernetes դերային մոդելը: զարգացման թիմի բոլոր անդամները: Եկեք ընդգծենք այն որպես առաջին օգտագործման դեպք՝ գործարկել Spark-ի առաջադրանքները տեղական ծրագրավորող մեքենայից Kubernetes կլաստերի վրա փորձարկման օղակում:
Եկեք ավելին խոսենք Spark-ի տեղադրման գործընթացի մասին՝ տեղական գործարկելու համար: Spark-ն օգտագործելու համար անհրաժեշտ է տեղադրել այն.
mkdir /opt/spark
cd /opt/spark
wget http://mirror.linux-ia64.org/apache/spark/spark-2.4.5/spark-2.4.5.tgz
tar zxvf spark-2.4.5.tgz
rm -f spark-2.4.5.tgz
Մենք հավաքում ենք անհրաժեշտ փաթեթները Kubernetes-ի հետ աշխատելու համար.
cd spark-2.4.5/
./build/mvn -Pkubernetes -DskipTests clean package
Ամբողջական կառուցումը շատ ժամանակ է պահանջում, և Docker պատկերներ ստեղծելու և դրանք Kubernetes կլաստերի վրա գործարկելու համար ձեզ իսկապես անհրաժեշտ են միայն jar ֆայլեր «assembly/» գրացուցակից, այնպես որ կարող եք կառուցել միայն այս ենթածրագիրը.
Spark-ի աշխատատեղերը Kubernetes-ում գործարկելու համար դուք պետք է ստեղծեք Docker պատկեր՝ որպես հիմնական պատկեր օգտագործելու համար: Այստեղ 2 հնարավոր մոտեցում կա.
Ստեղծված Docker պատկերը ներառում է գործարկվող Spark առաջադրանքի կոդը;
Ստեղծված պատկերը ներառում է միայն Spark-ը և անհրաժեշտ կախվածությունները, գործարկվող կոդը գտնվում է հեռակա կարգով (օրինակ՝ HDFS-ում):
Նախ, եկեք կառուցենք Docker պատկեր, որը պարունակում է Spark առաջադրանքի փորձնական օրինակ: Docker պատկերներ ստեղծելու համար Spark-ն ունի «docker-image-tool» կոչվող օգտակար ծրագիր: Եկեք ուսումնասիրենք դրա վերաբերյալ օգնությունը.
./bin/docker-image-tool.sh --help
Դրա օգնությամբ դուք կարող եք ստեղծել Docker պատկերներ և դրանք վերբեռնել հեռավոր ռեգիստրներում, բայց լռելյայն այն ունի մի շարք թերություններ.
առանց ձախողման ստեղծում է միանգամից 3 Docker պատկեր՝ Spark-ի, PySpark-ի և R-ի համար;
թույլ չի տալիս նշել պատկերի անունը:
Հետևաբար, մենք կօգտագործենք այս օգտակար ծրագրի փոփոխված տարբերակը, որը տրված է ստորև.
vi bin/docker-image-tool-upd.sh
#!/usr/bin/env bash
function error {
echo "$@" 1>&2
exit 1
}
if [ -z "${SPARK_HOME}" ]; then
SPARK_HOME="$(cd "`dirname "$0"`"/..; pwd)"
fi
. "${SPARK_HOME}/bin/load-spark-env.sh"
function image_ref {
local image="$1"
local add_repo="${2:-1}"
if [ $add_repo = 1 ] && [ -n "$REPO" ]; then
image="$REPO/$image"
fi
if [ -n "$TAG" ]; then
image="$image:$TAG"
fi
echo "$image"
}
function build {
local BUILD_ARGS
local IMG_PATH
if [ ! -f "$SPARK_HOME/RELEASE" ]; then
IMG_PATH=$BASEDOCKERFILE
BUILD_ARGS=(
${BUILD_PARAMS}
--build-arg
img_path=$IMG_PATH
--build-arg
datagram_jars=datagram/runtimelibs
--build-arg
spark_jars=assembly/target/scala-$SPARK_SCALA_VERSION/jars
)
else
IMG_PATH="kubernetes/dockerfiles"
BUILD_ARGS=(${BUILD_PARAMS})
fi
if [ -z "$IMG_PATH" ]; then
error "Cannot find docker image. This script must be run from a runnable distribution of Apache Spark."
fi
if [ -z "$IMAGE_REF" ]; then
error "Cannot find docker image reference. Please add -i arg."
fi
local BINDING_BUILD_ARGS=(
${BUILD_PARAMS}
--build-arg
base_img=$(image_ref $IMAGE_REF)
)
local BASEDOCKERFILE=${BASEDOCKERFILE:-"$IMG_PATH/spark/docker/Dockerfile"}
docker build $NOCACHEARG "${BUILD_ARGS[@]}"
-t $(image_ref $IMAGE_REF)
-f "$BASEDOCKERFILE" .
}
function push {
docker push "$(image_ref $IMAGE_REF)"
}
function usage {
cat <<EOF
Usage: $0 [options] [command]
Builds or pushes the built-in Spark Docker image.
Commands:
build Build image. Requires a repository address to be provided if the image will be
pushed to a different registry.
push Push a pre-built image to a registry. Requires a repository address to be provided.
Options:
-f file Dockerfile to build for JVM based Jobs. By default builds the Dockerfile shipped with Spark.
-p file Dockerfile to build for PySpark Jobs. Builds Python dependencies and ships with Spark.
-R file Dockerfile to build for SparkR Jobs. Builds R dependencies and ships with Spark.
-r repo Repository address.
-i name Image name to apply to the built image, or to identify the image to be pushed.
-t tag Tag to apply to the built image, or to identify the image to be pushed.
-m Use minikube's Docker daemon.
-n Build docker image with --no-cache
-b arg Build arg to build or push the image. For multiple build args, this option needs to
be used separately for each build arg.
Using minikube when building images will do so directly into minikube's Docker daemon.
There is no need to push the images into minikube in that case, they'll be automatically
available when running applications inside the minikube cluster.
Check the following documentation for more information on using the minikube Docker daemon:
https://kubernetes.io/docs/getting-started-guides/minikube/#reusing-the-docker-daemon
Examples:
- Build image in minikube with tag "testing"
$0 -m -t testing build
- Build and push image with tag "v2.3.0" to docker.io/myrepo
$0 -r docker.io/myrepo -t v2.3.0 build
$0 -r docker.io/myrepo -t v2.3.0 push
EOF
}
if [[ "$@" = *--help ]] || [[ "$@" = *-h ]]; then
usage
exit 0
fi
REPO=
TAG=
BASEDOCKERFILE=
NOCACHEARG=
BUILD_PARAMS=
IMAGE_REF=
while getopts f:mr:t:nb:i: option
do
case "${option}"
in
f) BASEDOCKERFILE=${OPTARG};;
r) REPO=${OPTARG};;
t) TAG=${OPTARG};;
n) NOCACHEARG="--no-cache";;
i) IMAGE_REF=${OPTARG};;
b) BUILD_PARAMS=${BUILD_PARAMS}" --build-arg "${OPTARG};;
esac
done
case "${@: -1}" in
build)
build
;;
push)
if [ -z "$REPO" ]; then
usage
exit 1
fi
push
;;
*)
usage
exit 1
;;
esac
Նրա օգնությամբ մենք հավաքում ենք Spark-ի հիմնական պատկերը, որը պարունակում է թեստային առաջադրանք՝ Pi-ն հաշվարկելու համար Spark-ի միջոցով (այստեղ {docker-registry-url}-ը ձեր Docker պատկերի ռեեստրի URL-ն է, {repo}-ը ռեեստրի ներսում գտնվող պահեստի անվանումն է, որը համընկնում է նախագծին OpenShift-ում, {image-name} - պատկերի անվանումը (եթե օգտագործվում է պատկերների եռաստիճան տարանջատում, օրինակ, ինչպես Red Hat OpenShift պատկերների ինտեգրված ռեեստրում), {tag} - այս պիտակը պատկերի տարբերակը):
Եկեք ստուգենք, որ հավաքված պատկերը հասանելի է OKD-ով: Դա անելու համար բրաուզերում բացեք URL-ը համապատասխան նախագծի պատկերների ցանկով (այստեղ {project}-ը նախագծի անվանումն է OpenShift կլաստերի ներսում, {OKD-WEBUI-URL}-ը OpenShift վեբ վահանակի URL-ն է: ) - https://{OKD-WEBUI-URL}/console /project/{project}/browse/images/{image-name}:
Առաջադրանքները գործարկելու համար պետք է ստեղծվի ծառայության հաշիվ՝ pods որպես root գործարկելու արտոնություններով (այս կետը կքննարկենք ավելի ուշ).
spark.kubernetes.authenticate.driver.serviceAccountName - Kubernetes ծառայության հաշվի անվանումը, որն օգտագործվում է pods գործարկելու ժամանակ (անվտանգության համատեքստը և հնարավորությունները սահմանելու համար Kubernetes API-ի հետ շփվելիս);
spark.kubernetes.namespace — Kubernetes-ի անվանատարածք, որտեղ կգործարկվեն վարորդի և կատարողի pods;
spark.submit.deployMode — Spark-ի գործարկման մեթոդ (ստանդարտ spark-submit-ի համար օգտագործվում է «կլաստերը», Spark օպերատորի և Spark «հաճախորդի» հետագա տարբերակների համար);
spark.kubernetes.container.image - Դոկերի պատկեր, որն օգտագործվում է փոդներ գործարկելու համար;
spark.master — Kubernetes API URL (արտաքին նշված է, որպեսզի մուտքը տեղի ունենա տեղական մեքենայից);
local://-ը Docker պատկերի ներսում Spark գործարկվող ուղին է:
Մենք գնում ենք համապատասխան OKD նախագիծ և ուսումնասիրում ենք ստեղծված փոդերը՝ https://{OKD-WEBUI-URL}/console/project/{project}/browse/pods:
Մշակման գործընթացը պարզեցնելու համար կարող է օգտագործվել մեկ այլ տարբերակ, որում ստեղծվում է Spark-ի ընդհանուր բազային պատկերը, որն օգտագործվում է բոլոր առաջադրանքների համար, և գործարկվող ֆայլերի նկարները հրապարակվում են արտաքին պահեստում (օրինակ՝ Hadoop) և նշված է զանգի ժամանակ: կայծ-ներկայացնել որպես հղում: Այս դեպքում դուք կարող եք գործարկել Spark առաջադրանքների տարբեր տարբերակներ՝ առանց Docker պատկերները վերակառուցելու՝ օգտագործելով, օրինակ, WebHDFS-ը՝ պատկերներ հրապարակելու համար: Մենք հարցում ենք ուղարկում ֆայլ ստեղծելու համար (այստեղ {host}-ը WebHDFS ծառայության հոսթն է, {port}-ը WebHDFS ծառայության պորտն է, {path-to-file-on-hdfs}-ը ֆայլի ցանկալի ուղին է։ HDFS-ում):
curl -i -X PUT "http://{host}:{port}/webhdfs/v1/{path-to-file-on-hdfs}?op=CREATE
Դուք կստանաք այսպիսի պատասխան (այստեղ {location} այն URL-ն է, որը պետք է օգտագործվի ֆայլը ներբեռնելու համար).
curl -i -X PUT -T {path-to-local-file} "{location}"
Դրանից հետո մենք կարող ենք կատարել spark-submit՝ օգտագործելով HDFS-ում վերբեռնված Spark ֆայլը (այստեղ {class-name} այն դասի անունն է, որը պետք է գործարկվի՝ առաջադրանքն ավարտելու համար).
Հարկ է նշել, որ HDFS մուտք գործելու և առաջադրանքն ապահովելու համար ձեզ կարող է անհրաժեշտ լինել փոխել Dockerfile-ը և entrypoint.sh սկրիպտը. ավելացնել հրահանգ Dockerfile-ին՝ կախված գրադարանները պատճենելու համար /opt/spark/jars գրացուցակում և ներառել HDFS կազմաձևման ֆայլը SPARK_CLASSPATH-ում մուտքի կետում: sh.
Երկրորդ օգտագործման դեպք - Apache Livy
Ավելին, երբ առաջադրանքը մշակվում է և արդյունքը պետք է փորձարկվի, հարց է առաջանում այն գործարկել որպես CI/CD գործընթացի մաս և հետևել դրա կատարման կարգավիճակին: Իհարկե, դուք կարող եք այն գործարկել՝ օգտագործելով տեղական spark-submit call, բայց դա բարդացնում է CI/CD ենթակառուցվածքը, քանի որ այն պահանջում է տեղադրել և կարգավորել Spark-ը CI սերվերի գործակալների/գործակալների վրա և մուտք գործել Kubernetes API: Այս դեպքում, թիրախային իրականացումը ընտրել է Apache Livy-ն օգտագործել որպես REST API՝ Spark առաջադրանքները գործարկելու համար, որոնք տեղակայված են Kubernetes կլաստերի ներսում: Նրա օգնությամբ դուք կարող եք գործարկել Spark-ի առաջադրանքները Kubernetes կլաստերի վրա՝ օգտագործելով սովորական cURL հարցումներ, որոնք հեշտությամբ իրականացվում են ցանկացած CI լուծման հիման վրա, և դրա տեղադրումը Kubernetes կլաստերի ներսում լուծում է նույնականացման խնդիրը Kubernetes API-ի հետ շփվելիս:
Եկեք ընդգծենք այն որպես երկրորդ օգտագործման դեպք. Spark առաջադրանքների կատարումը որպես CI/CD գործընթացի մաս Kubernetes կլաստերի վրա փորձնական հանգույցում:
Մի փոքր Apache Livy-ի մասին. այն աշխատում է որպես HTTP սերվեր, որն ապահովում է վեբ ինտերֆեյս և RESTful API, որը թույլ է տալիս հեռակա գործարկել spark-submit-ը՝ փոխանցելով անհրաժեշտ պարամետրերը: Ավանդաբար այն առաքվել է որպես HDP բաշխման մաս, բայց կարող է նաև տեղակայվել OKD-ում կամ Kubernetes-ի ցանկացած այլ տեղադրում՝ օգտագործելով համապատասխան մանիֆեստը և Docker պատկերների մի շարք, ինչպիսին է այս մեկը. github.com/ttauveron/k8s-big-data-experiments/tree/master/livy-spark-2.3. Մեր դեպքի համար կառուցվել է նմանատիպ Docker պատկեր, ներառյալ Spark 2.4.5 տարբերակը հետևյալ Dockerfile-ից.
Ստեղծված պատկերը կարող է կառուցվել և վերբեռնվել ձեր գոյություն ունեցող Docker պահոցում, ինչպիսին է ներքին OKD պահոցը: Այն տեղադրելու համար օգտագործեք հետևյալ մանիֆեստը ({registry-url} - Docker պատկերի ռեեստրի URL, {image-name} - Docker պատկերի անունը, {tag} - Docker պատկերի պիտակ, {livy-url} - ցանկալի URL, որտեղ սերվերը հասանելի կլինի Livy-ին, «Route» մանիֆեստն օգտագործվում է, եթե Red Hat OpenShift-ն օգտագործվում է որպես Kubernetes բաշխում, հակառակ դեպքում օգտագործվում է NodePort տիպի համապատասխան Ingress կամ Service մանիֆեստը):
Այն կիրառելուց և pod-ը հաջողությամբ գործարկելուց հետո Livy գրաֆիկական ինտերֆեյսը հասանելի է հետևյալ հղումով՝ http://{livy-url}/ui: Livy-ի հետ մենք կարող ենք հրապարակել մեր Spark առաջադրանքը՝ օգտագործելով REST հարցումը, օրինակ, Փոստատարից: Ստորև ներկայացված է հարցումներով հավաքածուի օրինակ (գործարկված առաջադրանքի գործարկման համար անհրաժեշտ փոփոխականներով կազմաձևման փաստարկները կարող են փոխանցվել «args» զանգվածում).
Եկեք կատարենք հավաքածուի առաջին հարցումը, անցնենք OKD միջերես և ստուգենք, որ առաջադրանքը հաջողությամբ գործարկվել է. https://{OKD-WEBUI-URL}/console/project/{project}/browse/pods: Միևնույն ժամանակ, Livy ինտերֆեյսում (http://{livy-url}/ui) կհայտնվի նիստ, որի շրջանակներում, օգտագործելով Livy API կամ գրաֆիկական ինտերֆեյսը, կարող եք հետևել առաջադրանքի առաջընթացին և ուսումնասիրել նիստը: գերաններ.
Հիմա եկեք ցույց տանք, թե ինչպես է աշխատում Լիվին: Դա անելու համար եկեք ուսումնասիրենք Livy կոնտեյների տեղեկամատյանները պատի ներսում Livy սերվերով - https://{OKD-WEBUI-URL}/console/project/{project}/browse/pods/{livy-pod-name }?tab=logs. Դրանցից մենք կարող ենք տեսնել, որ Livy REST API-ն «livy» անունով կոնտեյներով կանչելիս կատարվում է spark-submit, որը նման է վերևում օգտագործվածին (այստեղ {livy-pod-name} ստեղծված պատի անունն է: Livy սերվերի հետ): Հավաքածուն ներկայացնում է նաև երկրորդ հարցումը, որը թույլ է տալիս գործարկել առաջադրանքներ, որոնք հեռակա կարգով հյուրընկալում են Spark գործարկվող՝ օգտագործելով Livy սերվեր:
Երրորդ օգտագործման դեպք - Spark Operator
Այժմ, երբ առաջադրանքը փորձարկվել է, այն պարբերաբար գործարկելու հարց է առաջանում։ Kubernetes կլաստերում առաջադրանքները կանոնավոր կերպով գործարկելու բնիկ եղանակը CronJob-ն է, և դուք կարող եք օգտագործել այն, բայց այս պահին Kubernetes-ում հավելվածները կառավարելու օպերատորների օգտագործումը շատ տարածված է, և Spark-ի համար կա բավականին հասուն օպերատոր, որը նույնպես օգտագործվում է Enterprise մակարդակի լուծումներում (օրինակ՝ Lightbend FastData Platform): Մենք խորհուրդ ենք տալիս օգտագործել այն. Spark-ի ներկայիս կայուն տարբերակը (2.4.5) ունի բավականին սահմանափակ կազմաձևման տարբերակներ՝ Spark առաջադրանքները Kubernetes-ում գործարկելու համար, մինչդեռ հաջորդ հիմնական տարբերակը (3.0.0) հայտարարում է լիարժեք աջակցություն Kubernetes-ին, սակայն դրա թողարկման ամսաթիվը մնում է անհայտ: . Spark Operator-ը փոխհատուցում է այս թերությունը՝ ավելացնելով կազմաձևման կարևոր ընտրանքներ (օրինակ՝ տեղադրելով ConfigMap Hadoop մուտքի կոնֆիգուրացիայով Spark pods) և կանոնավոր պլանավորված առաջադրանքն իրականացնելու հնարավորությամբ:
Եկեք ընդգծենք այն որպես երրորդ օգտագործման դեպք՝ պարբերաբար կատարելով Spark առաջադրանքները Kubernetes կլաստերի վրա՝ արտադրական օղակում:
Օգտագործելով մանիֆեստներ պաշտոնական պահոցից (https://github.com/GoogleCloudPlatform/spark-on-k8s-operator/tree/master/manifest): Արժե նշել հետևյալը. Cloudflow-ը ներառում է օպերատոր API v1beta1 տարբերակով: Եթե տեղադրման այս տեսակն օգտագործվում է, Spark հավելվածի մանիֆեստի նկարագրությունները պետք է հիմնված լինեն Git-ի պիտակների վրա՝ համապատասխան API տարբերակով, օրինակ՝ «v1beta1-0.9.0-2.4.0»: Օպերատորի տարբերակը կարելի է գտնել «տարբերակներ» բառարանում օպերատորի մեջ ներառված CRD-ի նկարագրության մեջ.
oc get crd sparkapplications.sparkoperator.k8s.io -o yaml
Եթե օպերատորը ճիշտ է տեղադրված, ապա համապատասխան նախագծում կհայտնվի Spark օպերատորի հետ ակտիվ pod (օրինակ՝ cloudflow-fdp-sparkoperator Cloudflow տարածքում՝ Cloudflow տեղադրման համար) և կհայտնվի համապատասխան Kubernetes ռեսուրսի տեսակ՝ «sparkapplications» անունով: . Դուք կարող եք ուսումնասիրել առկա Spark հավելվածները հետևյալ հրամանով.
oc get sparkapplications -n {project}
Spark Operator-ի միջոցով առաջադրանքները կատարելու համար անհրաժեշտ է անել 3 բան.
ստեղծել Docker պատկեր, որը ներառում է բոլոր անհրաժեշտ գրադարանները, ինչպես նաև կազմաձևման և գործարկվող ֆայլերը: Թիրախային նկարում սա պատկեր է, որը ստեղծվել է CI/CD փուլում և փորձարկվել է թեստային կլաստերի վրա.
հրապարակել Docker պատկերը ռեեստրում, որը հասանելի է Kubernetes կլաստերից.
«apiVersion» բառարանը պետք է նշի օպերատորի տարբերակին համապատասխան API տարբերակը.
«metadata.namespace» բառարանը պետք է նշի այն անվանատարածքը, որտեղ կգործարկվի հավելվածը.
«spec.image» բառարանը պետք է պարունակի ստեղծված Docker պատկերի հասցեն հասանելի ռեեստրում.
«spec.mainClass» բառարանը պետք է պարունակի Spark առաջադրանքների դասը, որը պետք է գործարկվի, երբ գործընթացը սկսվի.
«spec.mainApplicationFile» բառարանը պետք է պարունակի գործարկվող jar ֆայլի ուղին.
«spec.sparkVersion» բառարանը պետք է նշի օգտագործվող Spark-ի տարբերակը.
«spec.driver.serviceAccount» բառարանը պետք է նշի ծառայության հաշիվը համապատասխան Kubernetes անվանատարածքում, որը կօգտագործվի հավելվածը գործարկելու համար.
«spec.executor» բառարանը պետք է նշի հավելվածին հատկացված ռեսուրսների քանակը.
«spec.volumeMounts» բառարանը պետք է նշի տեղական գրացուցակը, որտեղ կստեղծվեն տեղական Spark առաջադրանքների ֆայլերը:
Մանիֆեստի ստեղծման օրինակ (այստեղ {spark-service-account}-ը ծառայողական հաշիվ է Kubernetes կլաստերի ներսում Spark առաջադրանքների իրականացման համար).
Այս մանիֆեստը սահմանում է ծառայության հաշիվ, որի համար, նախքան մանիֆեստը հրապարակելը, դուք պետք է ստեղծեք անհրաժեշտ դերային կապեր, որոնք ապահովում են Spark հավելվածի մուտքի անհրաժեշտ իրավունքները Kubernetes API-ի հետ փոխազդելու համար (անհրաժեշտության դեպքում): Մեր դեպքում հավելվածին պետք են իրավունքներ Pods ստեղծելու համար։ Եկեք ստեղծենք անհրաժեշտ դերակատարումը.
Հարկ է նաև նշել, որ այս մանիֆեստի հստակեցումը կարող է ներառել «hadoopConfigMap» պարամետր, որը թույլ է տալիս նշել ConfigMap-ը Hadoop-ի կազմաձևով՝ առանց համապատասխան ֆայլը Docker-ի պատկերում նախապես տեղադրելու: Այն նաև հարմար է առաջադրանքները պարբերաբար կատարելու համար. օգտագործելով «ժամանակացույց» պարամետրը, կարելի է նշել տվյալ առաջադրանքի կատարման ժամանակացույցը:
Դրանից հետո մենք պահում ենք մեր մանիֆեստը spark-pi.yaml ֆայլում և կիրառում այն մեր Kubernetes կլաստերի վրա.
oc apply -f spark-pi.yaml
Սա կստեղծի «sparkapplications» տեսակի օբյեկտ.
oc get sparkapplications -n {project}
> NAME AGE
> spark-pi 22h
Այս դեպքում կստեղծվի հավելվածով պատիճ, որի կարգավիճակը կցուցադրվի ստեղծված «sparkapplications»-ում: Դուք կարող եք դիտել այն հետևյալ հրամանով.
oc get sparkapplications spark-pi -o yaml -n {project}
Առաջադրանքն ավարտելուց հետո POD-ը կանցնի «Ավարտված» կարգավիճակին, որը նույնպես կթարմացվի «sparkapplications»-ում: Հավելվածների տեղեկամատյանները կարելի է դիտել զննարկիչում կամ օգտագործելով հետևյալ հրամանը (այստեղ {sparkapplications-pod-name} գործող առաջադրանքի պատի անունն է).
oc logs {sparkapplications-pod-name} -n {project}
Spark-ի առաջադրանքները կարող են կառավարվել նաև sparkctl-ի մասնագիտացված ծրագրի միջոցով: Այն տեղադրելու համար կլոնավորեք պահեստն իր սկզբնական կոդով, տեղադրեք Go և ստեղծեք այս օգտակար ծրագիրը.
git clone https://github.com/GoogleCloudPlatform/spark-on-k8s-operator.git
cd spark-on-k8s-operator/
wget https://dl.google.com/go/go1.13.3.linux-amd64.tar.gz
tar -xzf go1.13.3.linux-amd64.tar.gz
sudo mv go /usr/local
mkdir $HOME/Projects
export GOROOT=/usr/local/go
export GOPATH=$HOME/Projects
export PATH=$GOPATH/bin:$GOROOT/bin:$PATH
go -version
cd sparkctl
go build -o sparkctl
sudo mv sparkctl /usr/local/bin
Եզրափակելով, ես կցանկանայի դիտարկել Կուբերնետեսում Spark-ի (2.4.5) ներկայիս կայուն տարբերակը օգտագործելու հայտնաբերված թերությունները.
Առաջին և, հավանաբար, գլխավոր թերությունը տվյալների տեղայնության բացակայությունն է։ Չնայած YARN-ի բոլոր թերություններին, կային նաև առավելություններ այն օգտագործելու համար, օրինակ՝ կոդը տվյալներին փոխանցելու սկզբունքը (այլ ոչ թե տվյալների կոդ): Դրա շնորհիվ Spark-ի առաջադրանքները կատարվել են այն հանգույցների վրա, որտեղ տեղակայված են եղել հաշվարկներում ներգրավված տվյալները, և զգալիորեն կրճատվել է ցանցով տվյալների առաքման ժամանակը: Kubernetes-ն օգտագործելիս մենք բախվում ենք առաջադրանքի հետ կապված տվյալները ցանցով տեղափոխելու անհրաժեշտության հետ: Եթե դրանք բավականաչափ մեծ են, առաջադրանքի կատարման ժամանակը կարող է զգալիորեն աճել, ինչպես նաև պահանջել բավականին մեծ քանակությամբ սկավառակի տարածություն, որը հատկացված է Spark առաջադրանքների օրինակներին՝ դրանց ժամանակավոր պահպանման համար: Այս թերությունը կարելի է մեղմել՝ օգտագործելով մասնագիտացված ծրագրակազմ, որն ապահովում է տվյալների տեղայնությունը Kubernetes-ում (օրինակ՝ Alluxio), բայց դա իրականում նշանակում է Kubernetes կլաստերի հանգույցների վրա տվյալների ամբողջական պատճենը պահելու անհրաժեշտություն:
Երկրորդ կարևոր թերությունը անվտանգությունն է։ Լռելյայնորեն, Spark-ի առաջադրանքների հետ կապված անվտանգության հետ կապված գործառույթներն անջատված են, Kerberos-ի օգտագործումը չի ընդգրկված պաշտոնական փաստաթղթերում (չնայած համապատասխան տարբերակները ներդրվել են 3.0.0 տարբերակում, որը կպահանջի լրացուցիչ աշխատանք), և անվտանգության փաստաթղթերը օգտագործելով Spark-ը (https ://spark.apache.org/docs/2.4.5/security.html) միայն YARN-ը, Mesos-ը և Standalone Cluster-ը հայտնվում են որպես հիմնական խանութներ: Միևնույն ժամանակ, այն օգտատերը, որի ներքո գործարկվում են Spark-ի առաջադրանքները, չի կարող ուղղակիորեն նշվել. մենք նշում ենք միայն ծառայության հաշիվը, որի տակ այն կաշխատի, և օգտագործողը ընտրվում է կազմաձևված անվտանգության քաղաքականության հիման վրա: Այս առումով կամ օգտագործվում է արմատային օգտատերը, որն անվտանգ չէ արտադրողական միջավայրում, կամ պատահական UID-ով օգտվող, որը անհարմար է տվյալների մուտքի իրավունքը բաշխելիս (դա կարելի է լուծել՝ ստեղծելով PodSecurityPolicies և կապելով դրանք համապատասխան ծառայությունների հաշիվներ): Ներկայումս լուծումն այն է, որ կա՛մ բոլոր անհրաժեշտ ֆայլերը տեղադրել անմիջապես Docker պատկերի մեջ, կա՛մ փոփոխել Spark-ի գործարկման սցենարը՝ ձեր կազմակերպությունում ընդունված գաղտնիքները պահելու և առբերելու մեխանիզմն օգտագործելու համար:
Kubernetes-ի միջոցով Spark-ի գործարկումը պաշտոնապես դեռ փորձնական ռեժիմում է, և ապագայում կարող են զգալի փոփոխություններ լինել օգտագործվող արտեֆակտներում (կազմաձևման ֆայլեր, Docker բազայի պատկերներ և գործարկման սկրիպտներ): Եվ իսկապես, նյութը պատրաստելիս փորձարկվել են 2.3.0 և 2.4.5 տարբերակները, վարքագիծը զգալիորեն տարբերվել է։
Սպասենք թարմացումներին. վերջերս թողարկվեց Spark-ի նոր տարբերակը (3.0.0), որը զգալի փոփոխություններ բերեց Spark-ի աշխատանքում Kubernetes-ում, բայց պահպանեց այս ռեսուրսների կառավարչի աջակցության փորձնական կարգավիճակը: Հավանաբար, հաջորդ թարմացումները իսկապես հնարավորություն կտան ամբողջությամբ խորհուրդ տալ հրաժարվել YARN-ից և կատարել Spark առաջադրանքները Kubernetes-ում՝ առանց վախենալու ձեր համակարգի անվտանգության համար և առանց ֆունկցիոնալ բաղադրիչները ինքնուրույն փոփոխելու անհրաժեշտության: