
V čase, keď Kubernetes bol ešte vo verzii v1.0.0, existovali pluginy pre objemy (volume plugins). Potrebné boli na pripojenie systémov úložísk pre Kubernetes na ukladanie perzistentných (trvalých) údajov kontajnerov. Ich počet bol malý, pričom medzi prvými boli poskytovatelia úložísk ako GCE PD, Ceph, AWS EBS a iní.
Pluginy sa dodávali spolu s Kubernetes, a preto dostali názov — in-tree. Avšak mnohým tohto existujúceho súboru pluginov nestačilo. Rukodělníci pridávali jednoduché pluginy do jadra Kubernetes pomocou patchov, po ktorých si zostavili svoj vlastný Kubernetes a nainštalovali ho na svoje servery. Ale s časom vývojári Kubernetes pochopili, že rybárství problém sa nedá vyriešiť. Ľuďom je potrebná rybárska udica. A v verzii Kubernetes v1.2.0 sa objavila…
Plugin Flexvolume: udica v minimalizme
Vývojári Kubernetes vytvorili plugin FlexVolume, ktorý bol logickým obalom z premenných a metód pre prácu s implementovanými externými Flexvolume ovládačmi.
Zastavme sa a podrobnejšie sa pozrime, čo predstavuje ovládač FlexVolume. Ide o akýsi spustiteľný súbor (binárny súbor, Python skript, Bash skript atď.), ktorý pri vykonaní prijíma príkazy z príkazového riadku a vracia správu s vopred známymi poliami vo formáte JSON. Prvým argumentom príkazového riadku podľa dohody vždy býva metóda, ostatné argumenty sú jej parametre.

Schéma pripojenia CIFS Shares v OpenShift. Ovládač Flexvolume — práve v centre
Minimálny súbor metód vyzerá takto:
flexvolume_driver mount # zodpovedá za pripojenie objemu k podu
# Formát vracanej správy:
{
"status": "Success"/"Failure"/"Not supported",
"message": "Z akého dôvodu bola vrátená presne takáto status",
}
flexvolume_driver unmount # zodpovedá za odpojenie objemu od podu
# Formát vracanej správy:
{
"status": "Success"/"Failure"/"Not supported",
"message": "Z akého dôvodu bola vrátená presne takáto status",
}
flexvolume_driver init # zodpovedá za inicializáciu pluginu
# Formát vracanej správy:
{
"status": "Success"/"Failure"/"Not supported",
"message": "Z akého dôvodu bola vrátená presne takáto status",
// Určuje, či ovládač používa metódy attach/detach
"capabilities":{"attach": True/False}
} Použitie metód attach a detach určí scenár, podľa ktorého v budúcnosti kubelet vykoná akciu pri volaní ovládača. Existujú tiež špeciálne metódy expandvolume a expandfs, ktoré zodpovedajú za dynamickú zmenu veľkosti zväzku.
Ako príklad zmien, ktoré pridáva metóda expandvolume, a spolu s ňou — aj možnosť vykonávať zmenu veľkosti zväzkov v reálnom čase, sa môžete oboznámiť s v Rook Ceph Operator.
Tu je príklad implementácie Flexvolume ovládača pre prácu s NFS:
usage() {
err "Neplatné použitie. Použitie: "
err "t$0 init"
err "t$0 mount <mount dir> <json params>"
err "t$0 unmount <mount dir>"
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": "Úspech"}'
exit 0
fi
mkdir -p ${MNTPATH} &> \/dev\/null
mount -t nfs ${NFS_SERVER}:\/(${SHARE} ${MNTPATH} &> \/dev\/null
if [ $? -ne 0 ]; then
err "{ "status": "Zlyhanie", "message": "Zlyhalo pripojenie ${NFS_SERVER}:${SHARE} na ${MNTPATH}"}"
exit 1
fi
log '{"status": "Úspech"}'
exit 0
}
unmount() {
MNTPATH=$1
if [ $(ismounted) -eq 0 ] ; then
log '{"status": "Úspech"}'
exit 0
fi
umount ${MNTPATH} &> \/dev\/null
if [ $? -ne 0 ]; then
err "{ "status": "Zlyhanie", "message": "Zlyhalo odpojenie zväzku na ${MNTPATH}"}"
exit 1
fi
log '{"status": "Úspech"}'
exit 0
}
op=$1
if [ "$op" = "init" ]; then
log '{"status": "Úspech", "capabilities": {"attach": false}}'
exit 0
fi
if [ $# -lt 2 ]; then
usage
fi
shift
case "$op" in
mount)
domount $*
;;
unmount)
unmount $*
;;
*)
log '{"status": "Nepodporované"}'
exit 0
esac
exit 1Takže po príprave samotného spustiteľného súboru je potrebné nahradiť ovládač do Kubernetes klastra. Ovládač by mal byť na každom uzle klastra podľa vopred dohodnutej cesty. Predvolene bola zvolená:
/usr/libexec/kubernetes/kubelet-plugins/volume/exec/имя_поставщика_хранилища~имя_драйвера/
… ale pri používaní rôznych distribúcií Kubernetes (OpenShift, Rancher…) môže byť cesta iná.
Problémy Flexvolume: ako správne nahadzovať udicu?
Nahrávanie Flexvolume ovládača na uzly klastra sa ukázalo ako nelehká úloha. Akonáhle vykonáte operáciu raz ručne, ľahko sa môžete stretnúť so situáciou, kedy v klasteri pribudnú nové uzly: kvôli pridaniu nového uzla, automatickému horizontálnemu škálovaniu alebo — čo je horšie — výmene uzla kvôli poruche. V tomto prípade sa práca s úložiskom na týchto uzloch bude nedá vykonať, kým ručne na ne nepridáte Flexvolume ovládač.
Riešením tohto problému bol jeden z primitívov Kubernetes — DaemonSetPri objavení nového uzla v klastri sa na ňom automaticky umiestni pod z nášho DaemonSetu, ku ktorému sa pripojí lokálny objem podľa cesty na nájdenie Flexvolume ovládačov. Pri úspešnom vytvorení podu skopíruje potrebné súbory na disk pre prácu ovládača.
Tu je príklad takého DaemonSetu na nasadenie Flexvolume pluginu:
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:… a príklad Bash skriptu na nasadenie Flexvolume ovládača:
#!/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
doneDôležité je nezabudnúť, že operácia kopírovania nie je atomárna. Je vysoká pravdepodobnosť, že kubelet začne používať ovládač skôr, ako sa proces jeho prípravy dokončí, čo vyvolá chybu v prevádzke systému. Správny prístup by bol najprv skopírovať súbory ovládača pod iným menom a potom použiť atomárnu operáciu premenovania.

Schéma práce s Ceph v operátore Rook: ovládač Flexvolume sa nachádza vo schéme vo vnútri agenta Rook
Ďalším problémom pri použití Flexvolume ovládačov je, že pre väčšinu úložísk na uzle klastra musí byť nainštalovaný potrebný softvér (napríklad balík ceph-common pre Ceph). Pôvodne nebol plugin Flexvolume navrhnutý pre implementáciu takto zložitých systémov.
Pôvodné riešenie tohto problému je viditeľné v implementácii Flexvolume ovládača operátora Rook:
Sám ovládač je realizovaný ako RPC klient. IPC socket na komunikáciu sa nachádza v tom istom adresári ako samotný ovládač. Pamätáme si, že na kopírovanie súborov ovládača by bolo dobré použiť DaemonSet, ktorý pripojí adresár s ovládačom ako objem. Po skopírovaní potrebných súborov ovládača rook tento pod neumiera, ale pripája sa k IPC socketu cez pripojený objem ako plnohodnotný RPC server. Balík ceph-common je už nainštalovaný vo vnútri kontajnera podu. IPC socket zaručuje, že kubelet bude komunikovať presne s tým podom, ktorý sa nachádza s ním na jednom uzli. Všetko geniálne je jednoduché!..
Zbohom, naši milí… in-tree pluginy!
Vývojári Kubernetes zistili, že počet pluginov pre úložiská v jadre sa rovná dvadsiatim. A zmeny v každom z nich prechádzajú cez celý vydávací cyklus Kubernetes.
Ukazuje sa, že na použitie novej verzie pluginu pre úložisko, je potrebné aktualizovať celý klaster. Okrem toho môžete byť prekvapení, že nová verzia Kubernetes sa náhle stane nekompatibilnou s použitým jadrom Linux… A preto utierate slzy a so skripaním zubov koordinujete s vedením a používateľmi čas aktualizácie jadra Linux a klastru Kubernetes. S možným výpadkom pri poskytovaní služieb.
Situácia je viac než komická, nemyslíte? Celé spoločenstvo si uvedomilo, že tento prístup nefunguje. Rozhodnutím vývojárov Kubernetes bolo oznámiť, že nové pluginy na prácu s úložiskami už nebudú prijímané do jadra. Okrem toho, ako už vieme, pri implementácií pluginu Flexvolume sa zistilo niekoľko nedostatkov...
Navždy uzavrieť otázku s perzistentnými úložiskami dát mal posledne pridaný plugin pre objemy v Kubernetes — CSI. Jeho alfa verzia, presnejšie nazývaná ako Out-of-Tree CSI Volume Plugins, bola oznámená v vydaní .
Container Storage Interface, alebo točíme CSI 3000!
Na začiatku by som chcel zdôrazniť, že CSI nie je len volume plugin, ale skutočný na vytváranie užívateľských komponentov pre prácu s úložiskami dát.Predpokladalo sa, že systémy na orchestráciu kontajnerov, ako Kubernetes a Mesos, sa musia 'naučiť' pracovať s komponentmi implementovanými podľa tejto normy. A Kubernetes sa už naučil.
Ako je konštruovaný CSI plugin v Kubernetes? CSI plugin pracuje so špeciálnymi ovládačmi (CSI-ovládačmi), napísanými externými vývojármi. CSI ovládač v Kubernetes musí minimálne pozostávať z dvoch komponentov (pod’ov):
- Ovládač — riadi vonkajšie perzistentné úložiská. Uvoľňuje sa vo forme gRPC servera, pre ktorý sa používa primitív
StatefulSet. - Node — zodpovedá za montovanie perzistentných úložísk na uzly klastera. Tiež sa implementuje vo forme gRPC servera, ale pre neho sa používa primitív
DaemonSet.

Schéma fungovania CSI pluginu v Kubernetes
O niektorých ďalších podrobnostiach fungovania CSI sa môžete dozvedieť napríklad z článku „», sme publikovali pred rokom.
Výhody takejto implementácie
- Pre základné úlohy — ako registrácia ovládača pre uzol — vývojári Kubernetes implementovali sadu kontajnerov. Už nie je potrebné ručne zostavovať JSON odpoveď s capabilities, ako to bolo pri plugine Flexvolume.
- Namiesto „podsúvania“ spustiteľných súborov na uzly teraz nasadzujeme pod’y do klastra. To je to, čo od Kubernetes očakávame: všetky procesy prebiehajú v kontajneroch nasadených pomocou primitív Kubernetes.
- Na implementáciu zložitých ovládačov už nie je potrebné vyvíjať RPC server a RPC klienta. Klienta za nás implementovali vývojári Kubernetes.
- Odovzdávanie argumentov pre prácu podľa protokolu gRPC je oveľa pohodlnejšie, flexibilnejšie a spoľahlivejšie než ich odovzdávanie cez argumenty príkazového riadku. Pre pochopenie, ako pridať v CSI podporu pre metriky využitia zväzku pridaním štandardizovanej gRPC metódy, si môžete prečítať pre ovládač vsphere-csi.
- Komunikácia prebieha cez IPC sokety, aby sa nezamotávalo, ktorému pod’u kubelet poslal požiadavku.
Táto zoznam vám niečo nepripomína? Výhody CSI sú riešením týchto rovnakých problémov, ktoré neboli zohľadnené pri vývoji pluginu Flexvolume.
Zhrnutie
CSI ako štandard pre implementáciu používateľských pluginov na interakciu s úložiskami dát bol komunitou prijatý veľmi pozitívne. Navyše, vďaka svojim výhodám a univerzálnosti, sa CSI ovládače vytvárajú dokonca aj pre také úložiská, ako Ceph alebo AWS EBS, pluginy na prácu s ktorými boli pridané už v prvej verzii Kubernetes.
Na začiatku roku 2019 boli in-tree pluginy Plánuje sa pokračovať v podpore pluginu Flexvolume, ale vývoj nových funkcií preň nebude.
My už máme skúsenosti s používaním ceph-csi, vsphere-csi a sme pripravení tento zoznam rozširovať! Zatiaľ sa CSÍ s zverejnenými úlohami darí skvele, a uvidíme, ako to pôjde ďalej.
Nezabúdajte, že všetko nové je dobre premyslené staré!
P.S.
Prečítajte si tiež na našom blogu:
- «»;
- «»;
- «».
Zdroj: habr.com
