Hurmatli o'quvchilar, xayrli kun. Bugun biz Apache Spark va uning rivojlanish istiqbollari haqida bir oz gaplashamiz.
Katta ma'lumotlarning zamonaviy dunyosida Apache Spark ommaviy ma'lumotlarni qayta ishlash vazifalarini ishlab chiqish uchun de-fakto standartdir. Bundan tashqari, u mikro partiya kontseptsiyasida ishlaydigan oqimli ilovalarni yaratish, ma'lumotlarni kichik qismlarda qayta ishlash va jo'natish uchun ham ishlatiladi (Spark Structured Streaming). Va an'anaviy ravishda u YARN (yoki ba'zi hollarda Apache Mesos) dan manba menejeri sifatida foydalangan holda umumiy Hadoop stekining bir qismi bo'lgan. 2020 yilga kelib, uni an'anaviy shaklda qo'llash ko'pchilik kompaniyalar uchun munosib Hadoop taqsimotlarining yo'qligi sababli so'roq ostida - HDP va CDH rivojlanishi to'xtadi, CDH yaxshi rivojlanmagan va yuqori narxga ega, qolgan Hadoop etkazib beruvchilari esa yo mavjud bo'lishni to'xtatdi yoki xira kelajakka ega. Shu sababli, Kubernetes-dan foydalangan holda Apache Spark-ning ishga tushirilishi hamjamiyat va yirik kompaniyalar orasida tobora ortib borayotgan qiziqish uyg'otmoqda - xususiy va ommaviy bulutlarda konteynerlarni boshqarish va resurslarni boshqarishda standart bo'lib, YARN-da Spark vazifalarini noqulay resurslarni rejalashtirish muammosini hal qiladi va taqdim etadi. barcha o'lchamdagi va chiziqlardagi kompaniyalar uchun ko'plab tijorat va ochiq tarqatishlarga ega bo'lgan barqaror rivojlanayotgan platforma. Bundan tashqari, mashhurlikka erishgandan so'ng, ko'pchilik allaqachon o'zlarining bir nechta qurilmalarini sotib olishga muvaffaq bo'lishdi va undan foydalanish bo'yicha tajribalarini oshirdilar, bu esa harakatni soddalashtiradi.
2.3.0 versiyasidan boshlab, Apache Spark Kubernetes klasteridagi vazifalarni bajarish uchun rasmiy yordamga ega bo'ldi va bugun biz ushbu yondashuvning hozirgi etukligi, uni qo'llashning turli xil variantlari va amalga oshirish jarayonida duch keladigan tuzoqlar haqida gaplashamiz.
Avvalo, keling, Apache Spark-ga asoslangan vazifalar va ilovalarni ishlab chiqish jarayonini ko'rib chiqamiz va Kubernetes klasterida vazifani bajarishingiz kerak bo'lgan odatiy holatlarni ajratib ko'rsatamiz. Ushbu postni tayyorlashda OpenShift tarqatish sifatida ishlatiladi va uning buyruq qatori yordam dasturiga (oc) tegishli buyruqlar beriladi. Boshqa Kubernetes tarqatishlari uchun standart Kubernetes buyruq qatori yordam dasturidan (kubectl) yoki ularning analoglaridan (masalan, oc adm siyosati uchun) tegishli buyruqlardan foydalanish mumkin.
Birinchi foydalanish holati - spark-submit
Vazifalar va ilovalarni ishlab chiqish jarayonida ishlab chiquvchi ma'lumotlar transformatsiyasini disk raskadrovka qilish uchun vazifalarni bajarishi kerak. Nazariy jihatdan, bu maqsadlar uchun stublardan foydalanish mumkin, ammo oxirgi tizimlarning haqiqiy (sinov bo'lsa ham) misollari ishtirokida ishlab chiqish ushbu vazifalar sinfida tezroq va yaxshiroq ekanligini isbotladi. Yakuniy tizimlarning haqiqiy misollarida disk raskadrovka qilingan taqdirda, ikkita stsenariy bo'lishi mumkin:
ishlab chiquvchi Spark vazifasini mahalliy sifatida mustaqil rejimda bajaradi;
ishlab chiquvchi sinov siklida Kubernetes klasterida Spark vazifasini bajaradi.
Birinchi variant mavjud bo'lish huquqiga ega, ammo bir qator kamchiliklarni o'z ichiga oladi:
Har bir ishlab chiquvchiga ish joyidan unga kerak bo'lgan oxirgi tizimlarning barcha nusxalariga kirish imkoniyati ta'minlanishi kerak;
ishlab chiqilayotgan vazifani bajarish uchun ishchi mashinada etarli miqdorda resurslar talab qilinadi.
Ikkinchi variantda bunday kamchiliklar mavjud emas, chunki Kubernetes klasteridan foydalanish sizga vazifalarni bajarish uchun kerakli resurs jamg'armasini ajratish va tizimning oxirgi nusxalariga kerakli kirishni ta'minlash imkonini beradi, bu esa Kubernetes rol modelidan foydalangan holda moslashuvchan tarzda unga kirishni ta'minlaydi. rivojlanish guruhining barcha a'zolari. Keling, buni birinchi foydalanish misoli sifatida ta'kidlab o'tamiz - sinov tsiklida Kubernetes klasteridagi mahalliy ishlab chiquvchi mashinasidan Spark vazifalarini ishga tushirish.
Keling, Spark-ni mahalliy sifatida ishga tushirish jarayoni haqida ko'proq gapiraylik. Spark-dan foydalanishni boshlash uchun uni o'rnatishingiz kerak:
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
Biz Kubernetes bilan ishlash uchun kerakli paketlarni yig'amiz:
cd spark-2.4.5/
./build/mvn -Pkubernetes -DskipTests clean package
To'liq qurish juda ko'p vaqtni oladi va Docker tasvirlarini yaratish va ularni Kubernetes klasterida ishga tushirish uchun sizga faqat "assembly/" katalogidagi jar fayllari kerak, shuning uchun siz faqat ushbu kichik loyihani yaratishingiz mumkin:
Kubernetes-da Spark ishlarini bajarish uchun siz asosiy tasvir sifatida foydalanish uchun Docker tasvirini yaratishingiz kerak. Bu erda 2 ta yondashuv mavjud:
Yaratilgan Docker tasviri bajariladigan Spark vazifa kodini o'z ichiga oladi;
Yaratilgan tasvir faqat Spark va kerakli bog'liqliklarni o'z ichiga oladi, bajariladigan kod masofadan turib (masalan, HDFSda) joylashtirilgan.
Birinchidan, Spark topshirig'ining sinov namunasini o'z ichiga olgan Docker tasvirini yarataylik. Docker tasvirlarini yaratish uchun Sparkda "docker-image-tool" deb nomlangan yordamchi dastur mavjud. Keling, bu boradagi yordamni o'rganamiz:
./bin/docker-image-tool.sh --help
Uning yordami bilan siz Docker tasvirlarini yaratishingiz va ularni masofaviy registrlarga yuklashingiz mumkin, ammo sukut bo'yicha uning bir qator kamchiliklari bor:
bir vaqtning o'zida 3 ta Docker tasvirini yaratadi - Spark, PySpark va R uchun;
rasm nomini belgilashga ruxsat bermaydi.
Shuning uchun biz quyida keltirilgan ushbu yordam dasturining o'zgartirilgan versiyasidan foydalanamiz:
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
Uning yordami bilan biz Spark yordamida Pi ni hisoblash uchun test topshirig'ini o'z ichiga olgan asosiy Spark tasvirini yig'amiz (bu yerda {docker-registry-url} Docker tasvirlar registrining URL manzili, {repo} - registr ichidagi ombor nomi, OpenShift-dagi loyihaga mos keladigan, {image-name} - tasvir nomi (agar tasvirlarni uch darajali ajratish ishlatilsa, masalan, Red Hat OpenShift tasvirlarining o'rnatilgan registridagi kabi), {tag} - buning tegi rasmning versiyasi):
Keling, yig'ilgan tasvirning OKD da mavjudligini tekshirib ko'raylik. Buning uchun brauzerda URL-manzilni tegishli loyihaning rasmlari roʻyxati bilan oching (bu yerda {loyiha} - OpenShift klasteridagi loyiha nomi, {OKD-WEBUI-URL} - OpenShift veb-konsolining URL manzili ) - https://{OKD-WEBUI-URL}/console /project/{project}/browse/images/{image-name}.
Vazifalarni bajarish uchun podkalarni ildiz sifatida ishga tushirish imtiyozlari bilan xizmat hisobi yaratilishi kerak (bu nuqtani keyinroq muhokama qilamiz):
—nom — Kubernetes ko‘zalari nomini shakllantirishda ishtirok etadigan vazifaning nomi;
—class — vazifa boshlanganda chaqiriladigan bajariladigan fayl sinfi;
—conf — Spark konfiguratsiya parametrlari;
spark.executor.instances — ishga tushiriladigan Spark ijrochilari soni;
spark.kubernetes.authenticate.driver.serviceAccountName - podlarni ishga tushirishda foydalaniladigan Kubernetes xizmat hisobining nomi (Kubernetes API bilan ishlashda xavfsizlik konteksti va imkoniyatlarini aniqlash uchun);
spark.kubernetes.namespace — Kubernetes nom maydoni, unda haydovchi va ijrochi pods ishga tushiriladi;
spark.submit.deployMode — Sparkni ishga tushirish usuli (standart spark-submit “klaster” uchun, Spark Operator va Spark “mijoz” ning keyingi versiyalari uchun ishlatiladi);
spark.kubernetes.container.image - podkalarni ishga tushirish uchun ishlatiladigan Docker tasviri;
spark.master — Kubernetes API URL manzili (tashqi belgilangan, shuning uchun kirish mahalliy mashinadan amalga oshiriladi);
Biz tegishli OKD loyihasiga o'tamiz va yaratilgan podslarni o'rganamiz - https://{OKD-WEBUI-URL}/console/project/{project}/browse/pods.
Rivojlanish jarayonini soddalashtirish uchun boshqa variantdan foydalanish mumkin, unda Spark-ning umumiy asosiy tasviri yaratiladi, barcha vazifalarni bajarish uchun foydalaniladi va bajariladigan fayllarning oniy tasvirlari tashqi xotiraga (masalan, Hadoop) nashr etiladi va qo'ng'iroq qilishda ko'rsatiladi. havola sifatida spark-submit. Bunday holda, siz Spark vazifalarining turli versiyalarini Docker tasvirlarini qayta tiklamasdan, masalan, WebHDFS yordamida tasvirlarni nashr etishingiz mumkin. Biz fayl yaratish uchun soʻrov yuboramiz (bu yerda {host} — WebHDFS xizmatining xosti, {port} — WebHDFS xizmatining porti, {path-to-file-on-hdfs} — faylga kerakli yoʻl. HDFSda):
curl -i -X PUT "http://{host}:{port}/webhdfs/v1/{path-to-file-on-hdfs}?op=CREATE
Siz shunday javob olasiz (bu yerda {location} faylni yuklab olish uchun ishlatilishi kerak boʻlgan URL manzili):
Spark bajariladigan faylini HDFS-ga yuklang (bu yerda {local-faylga yo'l} joriy xostdagi Spark bajariladigan fayliga yo'l):
curl -i -X PUT -T {path-to-local-file} "{location}"
Shundan so'ng biz HDFS-ga yuklangan Spark fayli yordamida spark-submitni amalga oshirishimiz mumkin (bu erda {sinf nomi} vazifani bajarish uchun ishga tushirilishi kerak bo'lgan sinf nomi):
Shuni ta'kidlash kerakki, HDFS-ga kirish va vazifaning ishlashini ta'minlash uchun siz Dockerfile va entrypoint.sh skriptini o'zgartirishingiz kerak bo'lishi mumkin - Dockerfile-ga bog'liq kutubxonalarni /opt/spark/jars katalogiga nusxalash uchun direktiv qo'shing va HDFS konfiguratsiya faylini kirish nuqtasiga SPARK_CLASSPATH ichiga qo'shing.
Ikkinchi foydalanish holati - Apache Livy
Bundan tashqari, vazifa ishlab chiqilganda va natijani sinab ko'rish kerak bo'lganda, uni CI/CD jarayonining bir qismi sifatida ishga tushirish va uning bajarilishi holatini kuzatish haqida savol tug'iladi. Albatta, siz uni mahalliy spark-submit qo‘ng‘irog‘i yordamida ishga tushirishingiz mumkin, ammo bu CI/CD infratuzilmasini murakkablashtiradi, chunki u CI server agentlari/yuguruvchilarida Spark-ni o‘rnatish va sozlashni va Kubernetes API-ga kirishni sozlashni talab qiladi. Bu holatda, maqsadli dastur Kubernetes klasterida joylashtirilgan Spark vazifalarini bajarish uchun REST API sifatida Apache Livy-dan foydalanishni tanladi. Uning yordami bilan siz Kubernetes klasterida Spark vazifalarini oddiy cURL so'rovlari yordamida bajarishingiz mumkin, bu har qanday CI yechimi asosida osonlik bilan amalga oshiriladi va uning Kubernetes klasteriga joylashtirilishi Kubernetes API bilan o'zaro aloqada autentifikatsiya muammosini hal qiladi.
Keling, buni ikkinchi foydalanish misoli sifatida ta'kidlab o'tamiz - sinov tsiklidagi Kubernetes klasterida CI/CD jarayonining bir qismi sifatida Spark vazifalarini bajarish.
Apache Livy haqida bir oz - u veb-interfeys va RESTful API bilan ta'minlovchi HTTP serveri sifatida ishlaydi, bu sizga kerakli parametrlarni o'tkazish orqali spark-submitni masofadan ishga tushirish imkonini beradi. An'anaga ko'ra, u HDP tarqatishning bir qismi sifatida yuborilgan, ammo tegishli manifest va Docker tasvirlari to'plamidan foydalangan holda OKD yoki boshqa Kubernetes o'rnatishlariga ham joylashtirilishi mumkin, masalan, bu - github.com/ttauveron/k8s-big-data-experiments/tree/master/livy-spark-2.3. Bizning holatlarimiz uchun shunga o'xshash Docker tasviri yaratilgan, jumladan, quyidagi Docker faylidan Spark 2.4.5 versiyasi:
Yaratilgan rasm ichki OKD ombori kabi mavjud Docker omboringizga tuzilishi va yuklanishi mumkin. Uni joylashtirish uchun quyidagi manifestdan foydalaning ({registry-url} - Docker tasvirlar registrining URL manzili, {image-name} - Docker tasvir nomi, {tag} - Docker image yorlig'i, {livy-url} - kerakli URL manzili serverga Livy kirish mumkin; Agar Red Hat OpenShift Kubernetes tarqatish sifatida ishlatilsa, “Marshrut” manifestidan foydalaniladi, aks holda NodePort tipidagi tegishli kirish yoki Xizmat manifestidan foydalaniladi):
Uni qo'llash va podkastni muvaffaqiyatli ishga tushirgandan so'ng, Livy grafik interfeysi havolada mavjud: http://{livy-url}/ui. Livi bilan biz Spark vazifamizni REST so'rovi yordamida nashr qilishimiz mumkin, masalan, Postman. So'rovlar bilan to'plamning namunasi quyida keltirilgan (boshlangan vazifaning ishlashi uchun zarur bo'lgan o'zgaruvchilar bilan konfiguratsiya argumentlari "args" massivida o'tkazilishi mumkin):
To'plamdan birinchi so'rovni bajaramiz, OKD interfeysiga o'tamiz va vazifa muvaffaqiyatli ishga tushirilganligini tekshiramiz - https://{OKD-WEBUI-URL}/console/project/{project}/browse/pods. Shu bilan birga, Livy interfeysida (http://{livy-url}/ui) sessiya paydo bo'ladi, uning ichida Livy API yoki grafik interfeysdan foydalanib, siz vazifaning borishini kuzatishingiz va sessiyani o'rganishingiz mumkin. jurnallar.
Keling, Livi qanday ishlashini ko'rsatamiz. Buning uchun Livy serveri yordamida pod ichidagi Livy konteynerining jurnallarini ko'rib chiqamiz - https://{OKD-WEBUI-URL}/console/project/{project}/browse/pods/{livy-pod-name }?tab=logs. Ulardan biz Livy REST API-ni "livy" nomli konteynerda chaqirganda, yuqorida biz ishlatganga o'xshash spark-submit amalga oshirilishini ko'rishimiz mumkin (bu erda {livy-pod-name} - yaratilgan podning nomi. Livy serveri bilan). To'plam, shuningdek, Livy serveri yordamida Spark bajariladigan faylni masofadan joylashtiradigan vazifalarni bajarishga imkon beruvchi ikkinchi so'rovni taqdim etadi.
Uchinchi foydalanish holati - Spark Operator
Vazifa sinovdan o'tgandan so'ng, uni muntazam ravishda bajarish haqida savol tug'iladi. Kubernetes klasterida vazifalarni muntazam ravishda bajarishning asosiy usuli bu CronJob ob'ektidir va siz undan foydalanishingiz mumkin, ammo hozirda Kubernetes-da ilovalarni boshqarish uchun operatorlardan foydalanish juda mashhur va Spark uchun juda etuk operator mavjud, bu ham Korxona darajasidagi yechimlarda qo'llaniladi (masalan, Lightbend FastData Platformasi). Biz undan foydalanishni tavsiya qilamiz - Spark ning joriy barqaror versiyasi (2.4.5) Kubernetes-da Spark vazifalarini bajarish uchun juda cheklangan konfiguratsiya imkoniyatlariga ega, keyingi asosiy versiya (3.0.0) esa Kubernetes-ni to'liq qo'llab-quvvatlashini e'lon qiladi, ammo uning chiqish sanasi noma'lumligicha qolmoqda. . Spark Operator bu kamchilikni muhim konfiguratsiya opsiyalarini (masalan, Spark podslariga Hadoop kirish konfiguratsiyasi bilan ConfigMapni o‘rnatish) va muntazam ravishda rejalashtirilgan vazifani bajarish qobiliyatini qo‘shish orqali qoplaydi.
Keling, buni uchinchi foydalanish holati sifatida ajratib ko'rsatamiz - ishlab chiqarish tsiklida Kubernetes klasterida Spark vazifalarini muntazam ravishda bajarish.
Rasmiy ombordagi manifestlardan foydalanish (https://github.com/GoogleCloudPlatform/spark-on-k8s-operator/tree/master/manifest). Shuni ta'kidlash kerakki, Cloudflow API v1beta1 versiyasiga ega operatorni o'z ichiga oladi. Agar ushbu turdagi o'rnatish ishlatilsa, Spark ilovasi manifest tavsiflari tegishli API versiyasiga ega Git-dagi misol teglariga asoslangan bo'lishi kerak, masalan, "v1beta1-0.9.0-2.4.0". Operatorning versiyasini "versiyalar" lug'atida operatorga kiritilgan CRD tavsifida topish mumkin:
oc get crd sparkapplications.sparkoperator.k8s.io -o yaml
Agar operator to'g'ri o'rnatilgan bo'lsa, tegishli loyihada Spark operatori bilan faol pod paydo bo'ladi (masalan, Cloudflow o'rnatilishi uchun Cloudflow maydonida cloudflow-fdp-sparkoperator) va tegishli Kubernetes resurs turi "sparkapplications" paydo bo'ladi. . Mavjud Spark ilovalarini quyidagi buyruq bilan o'rganishingiz mumkin:
oc get sparkapplications -n {project}
Spark Operator yordamida vazifalarni bajarish uchun siz 3 ta narsani qilishingiz kerak:
barcha kerakli kutubxonalarni, shuningdek, konfiguratsiya va bajariladigan fayllarni o'z ichiga olgan Docker tasvirini yarating. Maqsadli rasmda bu CI/CD bosqichida yaratilgan va test klasterida sinovdan o'tgan tasvir;
Docker tasvirini Kubernetes klasteridan foydalanish mumkin bo'lgan ro'yxatga olish kitobiga nashr qilish;
"apiVersion" lug'ati operator versiyasiga mos keladigan API versiyasini ko'rsatishi kerak;
"metadata.namespace" lug'atida ilova ishga tushiriladigan nomlar maydoni ko'rsatilishi kerak;
"spec.image" lug'ati mavjud registrda yaratilgan Docker tasvirining manzilini o'z ichiga olishi kerak;
"spec.mainClass" lug'ati jarayon boshlanganda ishga tushirilishi kerak bo'lgan Spark vazifa sinfini o'z ichiga olishi kerak;
"spec.mainApplicationFile" lug'ati bajariladigan jar fayliga yo'lni o'z ichiga olishi kerak;
"spec.sparkVersion" lug'atida Sparkning qo'llanilayotgan versiyasi ko'rsatilishi kerak;
"spec.driver.serviceAccount" lug'ati ilovani ishga tushirish uchun ishlatiladigan tegishli Kubernetes nom maydonidagi xizmat hisobini ko'rsatishi kerak;
"spec.executor" lug'ati ilovaga ajratilgan resurslar sonini ko'rsatishi kerak;
"spec.volumeMounts" lug'ati mahalliy Spark vazifa fayllari yaratiladigan mahalliy katalogni ko'rsatishi kerak.
Manifestni yaratishga misol (bu yerda {spark-service-account} - Spark vazifalarini bajarish uchun Kubernetes klasteridagi xizmat hisobi):
Bu manifest xizmat hisobini belgilaydi, uning uchun manifestni nashr etishdan oldin, Spark ilovasining Kubernetes API bilan oʻzaro ishlashi uchun zarur boʻlgan kirish huquqlarini taʼminlaydigan kerakli rol bogʻlamalarini yaratishingiz kerak (agar kerak boʻlsa). Bizning holatda, dasturga Podlarni yaratish huquqi kerak. Keling, kerakli rolni bog'lashni yaratamiz:
Shuni ham ta'kidlash joizki, ushbu manifest spetsifikatsiyasi "hadoopConfigMap" parametrini o'z ichiga olishi mumkin, bu sizga birinchi navbatda tegishli faylni Docker tasviriga joylashtirmasdan Hadoop konfiguratsiyasi bilan ConfigMapni belgilash imkonini beradi. Vazifalarni muntazam bajarish uchun ham javob beradi - "jadval" parametridan foydalanib, berilgan vazifani bajarish jadvalini belgilash mumkin.
Shundan so'ng biz manifestimizni spark-pi.yaml fayliga saqlaymiz va uni Kubernetes klasterimizga qo'llaymiz:
oc apply -f spark-pi.yaml
Bu "sparkapplications" tipidagi ob'ektni yaratadi:
oc get sparkapplications -n {project}
> NAME AGE
> spark-pi 22h
Bunday holda, ilova bilan podkast yaratiladi, uning holati yaratilgan "sparkapplications" da ko'rsatiladi. Siz uni quyidagi buyruq bilan ko'rishingiz mumkin:
oc get sparkapplications spark-pi -o yaml -n {project}
Vazifani tugatgandan so'ng, POD "Bajarildi" holatiga o'tadi, u "sparkapplications" da yangilanadi. Ilova jurnallarini brauzerda yoki quyidagi buyruq yordamida ko'rish mumkin (bu erda {sparkapplications-pod-name} - bajarilayotgan vazifa podining nomi):
oc logs {sparkapplications-pod-name} -n {project}
Spark vazifalarini ixtisoslashtirilgan sparkctl yordam dasturi yordamida ham boshqarish mumkin. Uni o'rnatish uchun omborni manba kodi bilan klonlang, Go'ni o'rnating va ushbu yordam dasturini yarating:
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
Ishlayotgan Spark vazifalari ro'yxatini ko'rib chiqamiz:
Keling, sparkctl yordamida tasvirlangan vazifani bajaramiz:
sparkctl create spark-app.yaml -n {project}
Ishlayotgan Spark vazifalari ro'yxatini ko'rib chiqamiz:
sparkctl list -n {project}
Keling, ishga tushirilgan Spark topshirig'ining voqealar ro'yxatini ko'rib chiqaylik:
sparkctl event spark-pi -n {project} -f
Ishlayotgan Spark vazifasining holatini ko'rib chiqamiz:
sparkctl status spark-pi -n {project}
Xulosa qilib, Kubernetes-da Spark (2.4.5) ning joriy barqaror versiyasidan foydalanishning aniqlangan kamchiliklarini ko'rib chiqmoqchiman:
Birinchi va, ehtimol, asosiy kamchilik - bu ma'lumotlarning joylashuvi yo'qligi. YARN ning barcha kamchiliklariga qaramay, undan foydalanishning afzalliklari ham mavjud edi, masalan, kodni ma'lumotlarga etkazish printsipi (ma'lumotlardan kodga emas). Uning yordamida hisob-kitoblarga jalb qilingan ma’lumotlar joylashgan tugunlarda Spark vazifalari bajarildi va tarmoq orqali ma’lumotlarni yetkazish vaqti sezilarli darajada qisqardi. Kubernetes-dan foydalanganda, biz tarmoq bo'ylab vazifaga jalb qilingan ma'lumotlarni ko'chirish zarurligiga duch kelamiz. Agar ular etarlicha katta bo'lsa, vazifani bajarish vaqti sezilarli darajada oshishi mumkin, shuningdek ularni vaqtincha saqlash uchun Spark topshiriq namunalariga ajratilgan juda katta hajmdagi disk maydonini talab qiladi. Ushbu kamchilikni Kubernetes-da ma'lumotlarning joylashishini ta'minlaydigan maxsus dasturiy ta'minot yordamida kamaytirish mumkin (masalan, Alluxio), lekin bu aslida Kubernetes klasteri tugunlarida ma'lumotlarning to'liq nusxasini saqlash zarurligini anglatadi.
Ikkinchi muhim kamchilik - bu xavfsizlik. Odatiy bo'lib, Spark vazifalarini bajarish bilan bog'liq xavfsizlik bilan bog'liq xususiyatlar o'chirib qo'yilgan, Kerberosdan foydalanish rasmiy hujjatlarda yoritilgan (garchi tegishli variantlar 3.0.0 versiyasida kiritilgan bo'lsa-da, bu qo'shimcha ishlarni talab qiladi) va xavfsizlik hujjatlari Spark (https://spark.apache.org/docs/2.4.5/security.html) yordamida faqat YARN, Mesos va Standalone Cluster asosiy doʻkonlar sifatida koʻrinadi. Shu bilan birga, Spark vazifalari ishga tushirilgan foydalanuvchini to'g'ridan-to'g'ri ko'rsatib bo'lmaydi - biz faqat u ishlaydigan xizmat hisobini belgilaymiz va foydalanuvchi sozlangan xavfsizlik siyosati asosida tanlanadi. Shu munosabat bilan, samarali muhitda xavfsiz bo'lmagan ildiz foydalanuvchi yoki ma'lumotlarga kirish huquqlarini tarqatishda noqulay bo'lgan tasodifiy UID foydalanuvchi ishlatiladi (buni PodSecurityPolicies yaratish va ularni bog'lash orqali hal qilish mumkin). tegishli xizmat hisoblari). Hozirgi vaqtda yechim barcha kerakli fayllarni to'g'ridan-to'g'ri Docker tasviriga joylashtirish yoki tashkilotingizda qabul qilingan sirlarni saqlash va olish mexanizmidan foydalanish uchun Spark ishga tushirish skriptini o'zgartirishdir.
Kubernetes yordamida Spark ishlarini ishga tushirish rasman hali ham eksperimental rejimda va kelajakda foydalaniladigan artefaktlarda (konfiguratsiya fayllari, Docker asosiy tasvirlari va ishga tushirish skriptlari) sezilarli oʻzgarishlar boʻlishi mumkin. Va haqiqatan ham, materialni tayyorlashda 2.3.0 va 2.4.5 versiyalari sinovdan o'tkazildi, xatti-harakatlar sezilarli darajada farq qildi.
Yangilanishlarni kutamiz - yaqinda Spark (3.0.0) ning yangi versiyasi chiqdi, u Kubernetesdagi Spark ishiga sezilarli o'zgarishlar kiritdi, ammo ushbu resurs menejerini qo'llab-quvvatlashning eksperimental holatini saqlab qoldi. Ehtimol, keyingi yangilanishlar haqiqatan ham YARN-dan voz kechishni va tizimingiz xavfsizligi uchun qo'rqmasdan va funktsional komponentlarni mustaqil ravishda o'zgartirishni talab qilmasdan Kubernetes-da Spark vazifalarini bajarishni to'liq tavsiya qilish imkonini beradi.