
Në kohët kur Kubernetes ishte akoma v1.0.0, ekzistonin plug-ins për volumet (volume plugins). Këto ishin të nevojshme për të lidhur sistemet e ruajtjes për të dhënat e qëndrueshme (persistent) të kontejnerëve në Kubernetes. Numri i tyre ishte i vogël, dhe ndër provajderët e parë të ruajtjes ishin GCE PD, Ceph, AWS EBS dhe të tjerë.
Plug-inet erdhën me Kubernetes, për këtë morën emrin in-tree. Megjithatë, shumëkush ndjeu se seti ekzistues i plug-inëve ishte i pamjaftueshëm. Artisanët shtonin plug-in të thjeshtë në bërthamën e Kubernetes me ndihmën e patch-eve, duke ndërtuar kështu Kubernetes të tyre dhe duke e instaluar atë në serverët e tyre. Megjithatë, me kalimin e kohës, zhvilluesit e Kubernetes kuptuan se peshku nuk është zgjidhja e problemit. Njerëzit kanë nevojë për fije peshkimi. Dhe në lëshimin e Kubernetes v1.2.0 ajo u shfaq...
Plug-in Flexvolume: fija e peshkimit në minimume
Zhvilluesit e Kubernetes krijuan plug-inin FlexVolume, i cili ishte një mbështetje logjike e variablave dhe metodave për të punuar me drejtuesit e Flexvolume të implementuar nga zhvillues të tjerë.
Le të ndalemi dhe të shohim më në detaje se çfarë përfaqëson drejtuesi FlexVolume. Ky është një lloj skedari ekzekutiv (skedar binar, skript Python, skript Bash, etj.), i cili gjatë ekzekutimit pranon argumente të linjës së komandës dhe kthen një mesazh me fusha të njohura paraprakisht në formatin JSON. Argumenti i parë i linjës së komandës sipas marrëveshjes është gjithmonë metoda, ndërsa argumentet e tjera janë parametrat e saj.

Skema e lidhjes së CIFS Shares në OpenShift. Drejtuesi Flexvolume – saktësisht në qendër
Grupi minimal i metodave duhet të duket kështu:
flexvolume_driver mount # përgjegjës për bashkimin e volumit me pod-in
# Formati i mesazhit të kthyer:
{
"status": "Sukses"/"Dështim"/"Nuk mbështetet",
"message": "Përse iu kthye ky status",
}
flexvolume_driver unmount # përgjegjës për shkëputjen e volumit nga pod-i
# Formati i mesazhit të kthyer:
{
"status": "Sukses"/"Dështim"/"Nuk mbështetet",
"message": "Përse iu kthye ky status",
}
flexvolume_driver init # përgjegjës për inicializimin e plug-init
# Formati i mesazhit të kthyer:
{
"status": "Sukses"/"Dështim"/"Nuk mbështetet",
"message": "Përse iu kthye ky status",
// Përcakton nëse drejtuesi përdor metodat attach/detach
"capabilities":{"attach": True/False}
} Përdorimi i metodave attach dhe detach do të përcaktojë skenarin sipas të cilit në të ardhmen kubelet do të veprojë kur të thirret drejtuesi. Po ashtu ekzistojnë metoda speciale expandvolume dhe expandfs, që përgjigjen për ndryshimin dinamik të madhësisë së volumeve.
Si një shembull i ndryshimeve që sjell metoda expandvolume, dhe kështu mundësinë për të realizuar ndryshimin e madhësisë së volumin në kohë reale, mund të njihni me në Rook Ceph Operator.
Ja një shembull i implementimit të drejtorit Flexvolume për të punuar me NFS:
usage() {
err "Përdorim të pavlefshëm. Përdorimi: "
err "t$0 init"
err "t$0 mount <direktori mount> <parametra json>"
err "t$0 unmount <direktori mount>"
exit 1
}
err() {
echo -ne $* 1>&2
}
log() {
echo -ne $* >&1
}
ismounted() {
MOUNT=`findmnt -n ${MNTPATH} 2>\/dev\/null | cut -d' ' -f1`
if [ "${MOUNT}" == "${MNTPATH}" ]; then
echo "1"
else
echo "0"
fi
}
domount() {
MNTPATH=$1
NFS_SERVER=$(echo $2 | jq -r '.server')
SHARE=$(echo $2 | jq -r '.share')
if [ $(ismounted) -eq 1 ] ; then
log '{"status": "Sukses"}'
exit 0
fi
mkdir -p ${MNTPATH} &> \/dev\/null
mount -t nfs ${NFS_SERVER}:\/ ${SHARE} ${MNTPATH} &> \/dev\/null
if [ $? -ne 0 ]; then
err "{ "status": "Dështim", "mesazh": "Dështoi të montojë ${NFS_SERVER}:${SHARE} në ${MNTPATH}"}"
exit 1
fi
log '{"status": "Sukses"}'
exit 0
}
unmount() {
MNTPATH=$1
if [ $(ismounted) -eq 0 ] ; then
log '{"status": "Sukses"}'
exit 0
fi
umount ${MNTPATH} &> \/dev\/null
if [ $? -ne 0 ]; then
err "{ "status": "Dështim", "mesazh": "Dështoi të shqiptojë volumin në ${MNTPATH}"}"
exit 1
fi
log '{"status": "Sukses"}'
exit 0
}
op=$1
if [ "$op" = "init" ]; then
log '{"status": "Sukses", "kapacitetet": {"attach": false}}'
exit 0
fi
if [ $# -lt 2 ]; then
usage
fi
shift
case "$op" in
mount)
domount $*
;;
unmount)
unmount $*
;;
*)
log '{"status": "Nuk mbështetet"}'
exit 0
esac
exit 1Pra, pas përgatitjes së skedarit ekzekutiv, është e nevojshme të ngarkohet drejtori në klasterin Kubernetes. Drejtori duhet të jetë në çdo nyje të klasterit sipas një rruge të caktuar më parë. Si parazgjedhje është zgjedhur:
/usr/libexec/kubernetes/kubelet-plugins/volume/exec/имя_поставщика_хранилища~имя_драйвера/
… por me përdorimin e distribuimeve të ndryshme Kubernetes (OpenShift, Rancher…) rruga mund të jetë ndryshe.
Problemet e Flexvolume: si të hedhim ndihmën në mënyrë të duhur?
Ngarko drejtuesin Flexvolume në nyjat e klasterit është bërë një detyrë e komplikuar. Pas kryerjes së operacionit një herë manualisht, është e lehtë të përballesh me situatën kur ndodhin nyje të reja në klaster: për shkak të shtimit të një nyje të re, shkallëzimit të automatik, apo — çfarë është më e keqe — zëvendësimit të një nyje për shkak të dështimit. Në këtë rast, punët me magazinimin në këto nyje duhen nuk është i mundur, derisa gjithashtu të shtoni manualisht drejtuesin Flexvolume në to.
Zgjidhja për këtë problem është një nga primitive të Kubernetes — DaemonSetKur në një grup shfaqet një nyje e re, një pod nga DaemonSet-i ynë automatikisht vendoset aty, duke u lidhur me një vëllim lokal për të gjetur shoferët e Flexvolume. Pas krijimit të suksesshëm të pod-it, ai kopjon skedarët e nevojshëm për funksionimin e shoferit në disk.
Ja një shembull i tillë DaemonSet-i për vendosjen e plugin-it Flexvolume:
apiVersion: extensions/v1beta1
kind: DaemonSet
metadata:
name: flex-set
spec:
template:
metadata:
name: flex-deploy
labels:
app: flex-deploy
spec:
containers:
- image:
name: flex-deploy
securityContext:
privileged: true
volumeMounts:
- mountPath: /flexmnt
name: flexvolume-mount
volumes:
- name: flexvolume-mount
hostPath:
path:… dhe një shembull i skriptit Bash për vendosjen e shoferit Flexvolume:
#!/bin/sh
set -o errexit
set -o pipefail
VENDOR=k8s.io
DRIVER=nfs
driver_dir=$VENDOR${VENDOR:+"~"}${DRIVER}
if [ ! -d "/flexmnt/$driver_dir" ]; then
mkdir "/flexmnt/$driver_dir"
fi
cp "/$DRIVER" "/flexmnt/$driver_dir/.$DRIVER"
mv -f "/flexmnt/$driver_dir/.$DRIVER" "/flexmnt/$driver_dir/$DRIVER"
while : ; do
sleep 3600
doneËshtë e rëndësishme të mos harrosh se operacioni i kopjimit nuk është atomar.Ka një probabilitet të lartë që kubelet të fillojë të përdorë shoferin para se procesi i përgatitjes të përfundojë, çka do të shkaktojë një gabim në funksionimin e sistemit. Qasja e duhur do të ishte të kopjoje skedarët e shoferit me një emër tjetër, dhe pastaj të përdorësh një operacion atomar të rinovimit.

Skema e punës me Ceph në operatorin Rook: shoferi Flexvolume në skemë ndodhet brenda agjentit Rook.
Problemi tjetër me përdorimin e shoferëve Flexvolume është se për shumicën e ruajtjeve në nyjën e grupit duhet të jetë instaluar softi i nevojshëm për këtë (për shembull, paketa ceph-common për Ceph). Fillimisht, plugin-i Flexvolume nuk ishte konceptuar për realizimin e sistemeve kaq të ndërlikuara.
Zgjidhja origjinale për këtë problem mund të shihet në zbatimin e shoferit Flexvolume të operatorit Rook:
Shoferi vetë është realizuar si një klient RPC. IPC-soketi për komunikim gjendet në të njëjtin katalog si vetë shoferi. Ne e dimë se për të kopjuar skedarët e shoferit, është mirë të përdorim DaemonSet, i cili lidh direktorinë me shoferin si një vëllim. Pas kopjimit të skedarëve të nevojshëm të shoferit, ky pod nuk vdes, por lidhet me IPC-soketin përmes vëllimit të lidhur si një RPC-server i plotë. Paketa ceph-common është tashmë e instaluar brenda konteinerit të pod-it. IPC-soketi siguron që kubelet do të komunikojë pikërisht me pod-in që ndodhet me të në të njëjtën nyje. E gjithë gjenialiteti është i thjeshtë!..
Mirupafshim, pluginët tanë të dashur… in-tree!
Zhvilluesit e Kubernetes zbuluan se numri i plugjineve për magazinat brenda bërthamës është njëzet. Dhe çdo ndryshim në secilin prej tyre kalon si ndodhi përmes ciklit të plotë të lëshimit të Kubernetes.
Duket se për të përdorur versionin e ri të pluginit të magazinës, duhet të azhurnoni të gjithë klusterin. Përveç kësaj, mund të çuditeni se si versioni i ri i Kubernetes papritmas do të bëhet jo i përputhshëm me bërthamën e përdorur të Linux… Prandaj, fshihni lotët dhe duke e shtrydhur dhëmbin e dakordoni me menaxhmentin dhe përdoruesit kohën e azhurnimit të bërthamës së Linux dhe klasterit të Kubernetes. Me mundësinë e anullimit të shërbimeve.
Situata është më shumë se komike, a nuk e mendoni? E gjithë bashkësia e kuptoi se ky qasje nuk po funksionon. Me një vendim të fuqishëm, zhvilluesit e Kubernetes shpallin se plugjinat e reja për të punuar me magazinat nuk do të pranohen më në bërthamë. Për më tepër, siç e dimë, në implementimin e pluginit të Flexvolume u zbuluan disa mangësi…
Për të mbyllur njëherë e përgjithmonë çështjen e magazinave zakonore të dhënash, plugini i fundit i shtuar për volume në Kubernetes - CSI. Versionin e tij alfa, më plotësisht të quajtur si Out-of-Tree CSI Volume Plugins, e shpallën në lëshimin .
Container Storage Interface, ose spinning CSI 3000!
E para që do të theksoj është se CSI nuk është thjesht një plug-in volume, por një gjithëpërfshirës për krijimin e komponenteve të përdoruesve për të punuar me magazinat e të dhënave. Ishte paraparë që sistemet e orkestrimit të kontejnerëve, si Kubernetes dhe Mesos, duhet "të mësojnë" të punojnë me komponentët e implementuar sipas këtij standardi. Dhe kështu Kubernetes tashmë ka mësuar.
Cili është mekanizmi i pluginit CSI në Kubernetes? Plugini CSI punon me shoferë të veçantë (shoferë CSI), të shkruar nga zhvillues të jashtëm. Shoferi CSI në Kubernetes minimalisht duhet të përbëhet nga dy komponentë (pod’ë):
- Controller — menaxhon magazinat e jashtme të vazhdueshme. Publikohet në formën e një serveri gRPC, për të cilin përdoret primi
StatefulSet. - Nyja — përgjigjet për montimin e magazinave të vazhdueshme në nyjet e klasterit. Kjo gjithashtu realizohet në formën e një serveri gRPC, por për të përdoret primi
DaemonSet.

Schema e punës së pluginit CSI në Kubernetes
Për disa detaje të tjera të funksionimit të CSI mund të mësoni, për shembull, nga artikulli "», ne e publikuan një vit më parë.
Përfitimet e një realizimi të tillë
- Për gjëra baza — si për shembull, regjistrimin e një driveri për nodin — zhvilluesit e Kubernetes zbatuan një grup kontejnerësh. Nuk është më e nevojshme të formoni vetë përgjigjen JSON me capabilities, siç bëhej për plugin-in Flexvolume.
- Në vend të "potencimit" të skedarëve të ekzekutueshëm në nodet, tani i publikojmë pod-et në klasër. Këtë e presim fillimisht nga Kubernetes: të gjithë proceset ndodhin brenda kontejnerëve, të shpërndarë përmes primitiveve të Kubernetes.
- Për zbatimin e driverëve më të komplikuar nuk është më e nevojshme të zhvilloni një server RPC dhe një klient RPC. Klienti është zbatuar për ne nga zhvilluesit e Kubernetes.
- Kalon argumentet për të punuar me protokollin gRPC është shumë më e përshtatshme, më fleksibile dhe më e besueshme se kalimi i tyre përmes argumenteve të komandës. Për të kuptuar se si të shtoni në CSI mbështetje për metrike të përdorimit të volumit përmes shtimit të një metode standardizuese gRPC, mund të konsultoheni me për driverin vsphere-csi.
- Komunikimi ndodh përmes IPC-sockets, kështu që të mos konfuzoheni, te cilit pod-i kubelet i dërgoi kërkesën.
A ju kujton kjo lista? Avantazhet e CSI janë zgjidhjet e atyre problemeve, që nuk u morën parasysh gjatë zhvillimit të plugin-in Flexvolume.
Përfundimet
CSI si standard i realizimit të plugin-eve të përdoruesve për ndërveprimin me depozitat e të dhënave u pranuar shumë ngrohtësisht nga komuniteti. Më shumë, falë avantazheve dhe universalitetit të tij, driverat CSI janë krijuar edhe për depozita si Ceph ose AWS EBS, plugin-et për të cilat u shtuan që në versionin e parë të Kubernetes.
Në fillim të vitit 2019, plugin-et in-tree . Është planifikuar të vazhdojë mbështetja e plugin-it Flexvolume, por nuk do të ketë zhvillim të funksionaliteteve të reja për të.
Ne vetë kemi përvojë në përdorimin e ceph-csi, vsphere-csi dhe jemi të gatshëm të plotësojmë këtë listë! Deri më tani, CSI është duke përmbushur detyrat e ngarkuara me sukses, dhe më vonë do të shohim.
Mos harroni se gjithçka e re është një e vjetër e menduar mirë!
P.S.
Lexoni gjithashtu në blogun tonë:
- «»;
- «»;
- «».
Burimi: habr.com
