Objemové doplnky pre úložisko Kubernetes: od Flexvolume po CSI

Objemové doplnky pre úložisko Kubernetes: od Flexvolume po CSI

Keď bol Kubernetes ešte vo verzii 1.0.0, existovali doplnky pre objem. Boli potrebné na pripojenie systémov ku Kubernetes na ukladanie trvalých (trvalých) údajov kontajnera. Ich počet bol malý a medzi prvými boli takí poskytovatelia úložísk ako GCE PD, Ceph, AWS EBS a ďalší.

Pluginy boli dodané spolu s Kubernetes, a preto dostali svoje meno - in-tree. Pre mnohých sa však existujúca sada takýchto doplnkov ukázala ako nedostatočná. Remeselníci pridali do jadra Kubernetes jednoduché doplnky pomocou opráv, po ktorých zostavili svoje vlastné Kubernetes a nainštalovali ich na svoje servery. Ale časom si to vývojári Kubernetes uvedomili ryby problém sa nedá vyriešiť. Ľudia potrebujú rybársky prút. A vo vydaní Kubernetes v1.2.0 sa objavilo...

Flexvolume plugin: minimálna rybárska udica

Vývojári Kubernetes vytvorili doplnok FlexVolume, ktorý bol logickým rámcom premenných a metód na prácu s ovládačmi Flexvolume implementovanými vývojármi tretích strán.

Zastavme sa a pozrime sa bližšie na to, čo je ovládač FlexVolume. Toto je isté spustiteľný súbor (binárny súbor, skript Python, skript Bash atď.), ktorý po spustení prevezme argumenty príkazového riadka ako vstup a vráti správu s vopred známymi poľami vo formáte JSON. Podľa konvencie je prvým argumentom príkazového riadka vždy metóda a zvyšné argumenty sú jej parametre.

Objemové doplnky pre úložisko Kubernetes: od Flexvolume po CSI
Schéma pripojenia pre zdieľané položky CIFS v OpenShift. Ovládač Flexvolume – priamo v centre

Minimálny súbor metód vyzerá takto:

flexvolume_driver mount # отвечает за присоединение тома к pod'у
# Формат возвращаемого сообщения:
{
  "status": "Success"/"Failure"/"Not supported",
  "message": "По какой причине был возвращен именно такой статус",
}

flexvolume_driver unmount # отвечает за отсоединение тома от pod'а
# Формат возвращаемого сообщения:
{
  "status": "Success"/"Failure"/"Not supported",
  "message": "По какой причине был возвращен именно такой статус",
}

flexvolume_driver init # отвечает за инициализацию плагина
# Формат возвращаемого сообщения:
{
  "status": "Success"/"Failure"/"Not supported",
  "message": "По какой причине был возвращен именно такой статус",
  // Определяет, использует ли драйвер методы attach/deatach
  "capabilities":{"attach": True/False}
}

Použitie metód attach и detach bude pri volaní vodiča definovať scenár, v ktorom bude kubelet v budúcnosti konať. Existujú aj špeciálne metódy expandvolume и expandfs, ktoré sú zodpovedné za dynamickú zmenu veľkosti hlasitosti.

Ako príklad zmien, ktoré metóda pridáva expandvolume, as ňou schopnosť meniť veľkosť zväzkov v reálnom čase, môžete sa s nimi zoznámiť naša žiadosť o ťahanie v operátorovi Rook Ceph.

A tu je príklad implementácie ovládača Flexvolume pre prácu s NFS:

usage() {
    err "Invalid usage. Usage: "
    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": "Success"}'
        exit 0
    fi

    mkdir -p ${MNTPATH} &> /dev/null

    mount -t nfs ${NFS_SERVER}:/${SHARE} ${MNTPATH} &> /dev/null
    if [ $? -ne 0 ]; then
        err "{ "status": "Failure", "message": "Failed to mount ${NFS_SERVER}:${SHARE} at ${MNTPATH}"}"
        exit 1
    fi
    log '{"status": "Success"}'
    exit 0
}

unmount() {
    MNTPATH=$1
    if [ $(ismounted) -eq 0 ] ; then
        log '{"status": "Success"}'
        exit 0
    fi

    umount ${MNTPATH} &> /dev/null
    if [ $? -ne 0 ]; then
        err "{ "status": "Failed", "message": "Failed to unmount volume at ${MNTPATH}"}"
        exit 1
    fi

    log '{"status": "Success"}'
    exit 0
}

op=$1

if [ "$op" = "init" ]; then
    log '{"status": "Success", "capabilities": {"attach": false}}'
    exit 0
fi

if [ $# -lt 2 ]; then
    usage
fi

shift

case "$op" in
    mount)
        domount $*
        ;;
    unmount)
        unmount $*
        ;;
    *)
        log '{"status": "Not supported"}'
        exit 0
esac

exit 1

Takže po príprave skutočného spustiteľného súboru musíte nahrajte ovládač do klastra Kubernetes. Ovládač musí byť umiestnený na každom uzle klastra podľa vopred určenej cesty. V predvolenom nastavení bolo vybraté:

/usr/libexec/kubernetes/kubelet-plugins/volume/exec/имя_поставщика_хранилища~имя_драйвера/

... ale pri použití rôznych distribúcií Kubernetes (OpenShift, Rancher...) môže byť cesta odlišná.

Problémy s Flexvolume: ako správne nahodiť rybársky prút?

Nahranie ovládača Flexvolume do uzlov klastra sa ukázalo ako netriviálna úloha. Po manuálnom vykonaní operácie sa ľahko môže stať, že sa v klastri objavia nové uzly: v dôsledku pridania nového uzla, automatického horizontálneho škálovania alebo - čo je horšie - výmeny uzla z dôvodu poruchy. V tomto prípade by sa mala vykonať práca s úložiskom na týchto uzloch je nemožné, kým k nim stále manuálne nepridáte ovládač Flexvolume.

Riešením tohto problému bolo jedno z primitív Kubernetes - DaemonSet. Keď sa v klastri objaví nový uzol, automaticky obsahuje modul z našej DaemonSet, ku ktorému je pozdĺž cesty pripojený lokálny zväzok na nájdenie ovládačov Flexvolume. Po úspešnom vytvorení modul skopíruje potrebné súbory, aby ovládač fungoval, na disk.

Tu je príklad takejto sady DaemonSet na usporiadanie doplnku Flexvolume:

apiVersion: extensions/v1beta1
kind: DaemonSet
metadata:
  name: flex-set
spec:
  template:
    metadata:
      name: flex-deploy
      labels:
        app: flex-deploy
    spec:
      containers:
        - image: <deployment_image>
          name: flex-deploy
          securityContext:
              privileged: true
          volumeMounts:
            - mountPath: /flexmnt
              name: flexvolume-mount
      volumes:
        - name: flexvolume-mount
          hostPath:
            path: <host_driver_directory>

... a príklad Bash skriptu na rozloženie ovládača 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

Je dôležité nezabudnúť na operáciu kopírovania nie je atómová. Existuje vysoká šanca, že kubelet začne používať ovládač pred dokončením procesu poskytovania, čo spôsobí zlyhanie systému. Správny prístup je najprv skopírovať súbory ovládača pod iným názvom a potom použiť operáciu atómového premenovania.

Objemové doplnky pre úložisko Kubernetes: od Flexvolume po CSI
Schéma práce s Ceph v operátorovi Rook: ovládač Flexvolume v diagrame sa nachádza vo vnútri agenta Rook

Ďalším problémom pri používaní ovládačov Flexvolume je problém pre väčšinu úložného priestoru v uzle klastra na to musí byť nainštalovaný potrebný softvér (napríklad balík ceph-common pre Ceph). Zásuvný modul Flexvolume nebol pôvodne navrhnutý na implementáciu takýchto zložitých systémov.

Originálne riešenie tohto problému je možné vidieť v implementácii ovládača Flexvolume operátora Rook:

Samotný ovládač je navrhnutý ako RPC klient. IPC socket pre komunikáciu sa nachádza v rovnakom 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ý spája adresár s ovládačom ako zväzok. Po skopírovaní potrebných súborov ovládača veže tento modul nezomrie, ale pripojí sa k IPC socketu cez pripojený zväzok ako plnohodnotný RPC server. Balík ceph-common je už nainštalovaný v kontajneri pod. IPC zásuvka zaisťuje, že kubelet bude komunikovať presne s modulom, ktorý je umiestnený na rovnakom uzle. Všetko dômyselné je jednoduché!...

Zbohom, naše milé... in-tree pluginy!

Vývojári Kubernetes zistili, že počet pluginov pre ukladanie v jadre je dvadsať. A zmena v každom z nich, tak či onak, prechádza celým cyklom vydania Kubernetes.

Ukazuje sa, že ak chcete použiť novú verziu doplnku úložiska, musíte aktualizovať celý klaster. Okrem toho vás možno prekvapí, že nová verzia Kubernetes sa zrazu stane nekompatibilnou s linuxovým jadrom, ktoré používate... Takže si utierate slzy a so zatínaním zubov koordinujete s vedením a používateľmi čas aktualizovať jadro Linuxu a klaster Kubernetes. S možným výpadkom v poskytovaní služieb.

Situácia je viac než komická, nemyslíte? Celému spoločenstvu bolo jasné, že tento prístup nefunguje. Svojvoľným rozhodnutím vývojári Kubernetes oznamujú, že nové pluginy pre prácu s úložiskom už nebudú akceptované do jadra. Navyše, ako už vieme, pri implementácii doplnku Flexvolume sa zistilo množstvo nedostatkov...

Najnovšie pridaný doplnok pre zväzky v Kubernetes, CSI, bol vyzvaný, aby raz a navždy uzavrel problém s trvalým ukladaním údajov. Jeho alfa verzia, podrobnejšie označovaná ako Out-of-Tree CSI Volume Plugins, bola oznámená vo vydaní Kubernetes 1.9.

Rozhranie na skladovanie kontajnerov alebo prívlač CSI 3000!

V prvom rade by som rád poznamenal, že CSI nie je len objemový plugin, ale skutočný стандарт o vytváraní vlastných komponentov pre prácu s dátovými skladmi. Systémy na orchestráciu kontajnerov ako Kubernetes a Mesos sa mali „naučiť“ pracovať s komponentmi implementovanými podľa tohto štandardu. A teraz som sa už naučil Kubernetes.

Aká je štruktúra doplnku CSI v Kubernetes? CSI plugin pracuje so špeciálnymi ovládačmi (CSI ovládače) napísané vývojármi tretích strán. Ovládač CSI v Kubernetes by mal pozostávať minimálne z dvoch komponentov (podov):

  • kontrolór — spravuje externé trvalé úložiská. Je implementovaný ako server gRPC, pre ktorý sa používa primitív StatefulSet.
  • Uzol — je zodpovedný za pripojenie trvalého úložiska do uzlov klastra. Je tiež implementovaný ako server gRPC, ale používa primitívne DaemonSet.

Objemové doplnky pre úložisko Kubernetes: od Flexvolume po CSI
Ako funguje doplnok CSI v Kubernetes

O niektorých ďalších detailoch práce CSI sa môžete dozvedieť napríklad z článku „Pochopenie C.S.I." preklad ktorých sme zverejnili pred rokom.

Výhody takejto implementácie

  • Pre základné veci, ako je registrácia ovládača pre uzol, vývojári Kubernetes implementovali sadu kontajnerov. Už nemusíte sami generovať odpoveď JSON s funkciami, ako to bolo v prípade doplnku Flexvolume.
  • Namiesto „vkladania“ spustiteľných súborov do uzlov teraz nahrávame moduly do klastra. To je to, čo pôvodne očakávame od Kubernetes: všetky procesy sa vyskytujú vo vnútri kontajnerov nasadených pomocou primitív Kubernetes.
  • Na implementáciu zložitých ovládačov už nemusíte vyvíjať server RPC a klienta RPC. Klienta nám implementovali vývojári Kubernetes.
  • Odovzdávanie argumentov pre prácu cez protokol gRPC je oveľa pohodlnejšie, flexibilnejšie a spoľahlivejšie ako ich odovzdávanie cez argumenty príkazového riadku. Ak chcete pochopiť, ako pridať podporu pre metriky využívania objemu do CSI pridaním štandardizovanej metódy gRPC, môžete si prečítať: naša žiadosť o ťahanie pre ovládač vsphere-csi.
  • Komunikácia prebieha cez IPC zásuvky, aby nedošlo k zámene, či kubelet odoslal požiadavku na správny modul.

Pripomína vám tento zoznam niečo? Výhody CSI sú riešenie tých istých problémov, ktoré neboli zohľadnené pri vývoji doplnku Flexvolume.

Závery

CSI ako štandard pre implementáciu vlastných doplnkov na interakciu s dátovými skladmi bol komunitou veľmi vrelo prijatý. Navyše, vďaka svojim výhodám a všestrannosti sú CSI ovládače vytvorené aj pre úložné systémy ako Ceph alebo AWS EBS, pluginy na prácu s ktorými boli pridané v úplne prvej verzii Kubernetes.

Začiatkom roka 2019 in-tree pluginy boli vyhlásené za zastarané. Plánujeme pokračovať v podpore doplnku Flexvolume, ale nebudeme preň vyvíjať nové funkcie.

My sami už máme skúsenosti s používaním ceph-csi, vsphere-csi a sme pripravení pridať tento zoznam! Zatiaľ sa CSI vyrovnáva s úlohami, ktoré mu boli pridelené, ale počkáme a uvidíme.

Nezabudnite, že všetko nové je dobrým prehodnotením starého!

PS

Prečítajte si aj na našom blogu:

Zdroj: hab.com

Pridať komentár