Sējuma spraudņi Kubernetes krātuvei: no Flexvolume līdz CSI

Sējuma spraudņi Kubernetes krātuvei: no Flexvolume līdz CSI

Kad Kubernetes vēl bija v1.0.0, bija skaļuma spraudņi. Tie bija nepieciešami, lai savienotu sistēmas ar Kubernetes pastāvīgu (pastāvīgu) konteineru datu glabāšanai. Viņu skaits bija neliels, un starp pirmajiem bija tādi krātuves nodrošinātāji kā GCE PD, Ceph, AWS EBS un citi.

Spraudņi tika piegādāti kopā ar Kubernetes, tāpēc tie ieguva savu nosaukumu - in-tree. Tomēr daudziem esošais šādu spraudņu komplekts izrādījās nepietiekams. Amatnieki pievienoja vienkāršus spraudņus Kubernetes kodolam, izmantojot ielāpus, pēc tam viņi samontēja savu Kubernetes un instalēja to savos serveros. Bet laika gaitā Kubernetes izstrādātāji to saprata zivis problēmu nevar atrisināt. Cilvēkiem vajag makšķere. Un Kubernetes v1.2.0 izlaidumā parādījās...

Flexvolume spraudnis: minimāls makšķere

Kubernetes izstrādātāji izveidoja spraudni FlexVolume, kas bija loģisks mainīgo un metožu ietvars darbam ar Flexvolume draiveriem, ko ieviesuši trešo pušu izstrādātāji.

Apstāsimies un aplūkosim tuvāk, kas ir FlexVolume draiveris. Tas ir zināms izpildāmais fails (binārais fails, Python skripts, Bash skripts utt.), kas, izpildot, kā ievadi izmanto komandrindas argumentus un atgriež ziņojumu ar iepriekš zināmiem laukiem JSON formātā. Pēc vienošanās pirmais komandrindas arguments vienmēr ir metode, bet pārējie argumenti ir tās parametri.

Sējuma spraudņi Kubernetes krātuvei: no Flexvolume līdz CSI
Savienojuma shēma CIFS koplietošanai programmā OpenShift. Flexvolume Driver — pašā centrā

Minimālais metožu kopums izskatās šādi:

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}
}

Metožu izmantošana attach и detach definēs scenāriju, kādā kubelet rīkosies turpmāk, izsaucot draiveri. Ir arī īpašas metodes expandvolume и expandfs, kas ir atbildīgi par skaļuma dinamisku izmēru maiņu.

Kā piemēru izmaiņām, ko metode pievieno expandvolume, un līdz ar to iespēju reāllaikā mainīt apjomu izmērus, varat iepazīties ar mūsu izvilkšanas pieprasījums Rook Ceph Operator.

Un šeit ir piemērs Flexvolume draivera ieviešanai darbam ar 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

Tātad, pēc faktiskā izpildāmā faila sagatavošanas jums tas ir jādara augšupielādējiet draiveri Kubernetes klasterī. Draiveram ir jāatrodas katrā klastera mezglā saskaņā ar iepriekš noteiktu ceļu. Pēc noklusējuma tas tika atlasīts:

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

... bet, izmantojot dažādus Kubernetes izplatījumus (OpenShift, Rancher...), ceļš var atšķirties.

Flexvolume problēmas: kā pareizi iemest makšķeri?

Flexvolume draivera augšupielāde klastera mezglos izrādījās nenozīmīgs uzdevums. Veicot operāciju vienu reizi manuāli, ir viegli saskarties ar situāciju, kad klasterī parādās jauni mezgli: jauna mezgla pievienošanas, automātiskās horizontālās mērogošanas vai - kas vēl ļaunāk - mezgla nomaiņas dēļ darbības traucējumu dēļ. Šajā gadījumā ir jāstrādā ar krātuvi šajos mezglos nav iespējams, līdz joprojām manuāli pievienojat tiem Flexvolume draiveri.

Šīs problēmas risinājums bija viens no Kubernetes primitīviem - DaemonSet. Kad klasterī parādās jauns mezgls, tajā automātiski ir ietverts mūsu DaemonSet pods, kuram tiek pievienots lokālais sējums, lai atrastu Flexvolume draiverus. Pēc veiksmīgas izveides pods iekopē diskā nepieciešamos failus, lai draiveris darbotos.

Šeit ir šāda DaemonSet piemērs Flexvolume spraudņa izkārtošanai:

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>

... un Bash skripta piemērs Flexvolume draivera izkārtošanai:

#!/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

Ir svarīgi neaizmirst, ka kopēšanas darbība nav atomisks. Pastāv liela iespēja, ka kubelet sāks lietot draiveri, pirms būs pabeigts tā nodrošināšanas process, izraisot sistēmas avāriju. Pareizā pieeja ir vispirms kopēt draivera failus ar citu nosaukumu un pēc tam izmantot atomu pārdēvēšanas darbību.

Sējuma spraudņi Kubernetes krātuvei: no Flexvolume līdz CSI
Diagramma darbam ar Ceph Rook operatorā: Flexvolume draiveris diagrammā atrodas Rook aģenta iekšpusē

Nākamā problēma, izmantojot Flexvolume draiverus, ir lielākā daļa krātuves klastera mezglā tam ir jāinstalē nepieciešamā programmatūra (piemēram, Ceph kopējā pakotne). Sākotnēji spraudnis Flexvolume nebija paredzēts tik sarežģītu sistēmu ieviešanai.

Oriģinālu šīs problēmas risinājumu var redzēt Rook operatora Flexvolume draivera implementācijā:

Pats draiveris ir izveidots kā RPC klients. Saziņas IPC ligzda atrodas tajā pašā direktorijā, kurā atrodas pats draiveris. Mēs atceramies, ka draivera failu kopēšanai būtu labi izmantot DaemonSet, kas savieno direktoriju ar draiveri kā sējumu. Pēc nepieciešamo rook draiveru failu nokopēšanas šis pods nemirst, bet caur pievienoto sējumu pieslēdzas IPC ligzdai kā pilnvērtīgs RPC serveris. Ceph-common pakotne jau ir instalēta pod konteinera iekšpusē. IPC ligzda nodrošina, ka kubelet sazināsies tieši ar podziņu, kas atrodas tajā pašā mezglā. Viss ģeniālais ir vienkāršs!...

Ardievu, mūsu sirsnīgie... kokā esošie spraudņi!

Kubernetes izstrādātāji atklāja, ka spraudņu skaits glabāšanai kodolā ir divdesmit. Un izmaiņas katrā no tām vienā vai otrā veidā iziet cauri pilnam Kubernetes izlaišanas ciklam.

Izrādās, ka, lai izmantotu krātuves spraudņa jauno versiju, jums ir jāatjaunina viss klasteris. Turklāt jūs varat būt pārsteigts, ka jaunā Kubernetes versija pēkšņi kļūs nesaderīga ar jūsu izmantoto Linux kodolu... Tāpēc jūs noslaukāt asaras un, zobus sakoduši, saskaņojiet ar savu vadību un lietotājiem laiku, lai atjauniniet Linux kodolu un Kubernetes klasteru. Ar iespējamu dīkstāvi pakalpojumu sniegšanā.

Situācija ir vairāk nekā komiska, vai ne? Visai sabiedrībai kļuva skaidrs, ka pieeja nedarbojas. Ar apzinātu lēmumu Kubernetes izstrādātāji paziņo, ka kodolā vairs netiks pieņemti jauni spraudņi darbam ar krātuvi. Turklāt, kā jau zināms, Flexvolume spraudņa ieviešanā tika konstatētas vairākas nepilnības...

Jaunākais pievienotais spraudnis sējumiem pakalpojumā Kubernetes, CSI, tika aicināts uz visiem laikiem novērst problēmu ar pastāvīgu datu glabāšanu. Laidienā tika paziņota par tās alfa versiju, kas pilnīgāk saukta par Out-of-Tree CSI Volume Plugins Kubernetes 1.9.

Konteineru glabāšanas interfeiss jeb CSI 3000 vērpšanas stienis!

Pirmkārt, es vēlos atzīmēt, ka CSI nav tikai skaļuma spraudnis, bet gan īsts standarta par pielāgotu komponentu izveidi darbam ar datu noliktavām. Konteineru orķestrēšanas sistēmām, piemēram, Kubernetes un Mesos, bija paredzēts “iemācīties” strādāt ar komponentiem, kas ieviesti saskaņā ar šo standartu. Un tagad es jau esmu iemācījies Kubernetes.

Kāda ir CSI spraudņa struktūra Kubernetes? CSI spraudnis darbojas ar īpašiem draiveriem (CSI draiveri), ko rakstījuši trešo pušu izstrādātāji. Kubernetes CSI draiverim jāsastāv no diviem komponentiem (podiem):

  • kontrolieris — pārvalda ārējās pastāvīgās krātuves. Tas tiek realizēts kā gRPC serveris, kuram tiek izmantots primitīvs StatefulSet.
  • mezgls — ir atbildīgs par pastāvīgas krātuves uzstādīšanu klasteru mezglos. Tas ir ieviests arī kā gRPC serveris, taču tas izmanto primitīvu DaemonSet.

Sējuma spraudņi Kubernetes krātuvei: no Flexvolume līdz CSI
Kā CSI spraudnis darbojas Kubernetes

Jūs varat uzzināt par dažām citām CSI darba detaļām, piemēram, no raksta "Izpratne par C.S.I." kuru tulkojums mēs publicējām pirms gada.

Šādas ieviešanas priekšrocības

  • Pamatlietām, piemēram, mezgla draivera reģistrēšanai, Kubernetes izstrādātāji ieviesa konteineru komplektu. Jums vairs nav pašam jāģenerē JSON atbilde ar iespējām, kā tas tika darīts spraudnim Flexvolume.
  • Tā vietā, lai izpildāmos failus “ieslīdētu” mezglos, mēs tagad augšupielādējam pākstis klasterī. Tas ir tas, ko mēs sākotnēji sagaidām no Kubernetes: visi procesi notiek konteineros, kas izvietoti, izmantojot Kubernetes primitīvas.
  • Jums vairs nav jāizstrādā RPC serveris un RPC klients, lai ieviestu sarežģītus draiverus. Klientu mums ieviesa Kubernetes izstrādātāji.
  • Argumentu nodošana darbam, izmantojot gRPC protokolu, ir daudz ērtāka, elastīgāka un uzticamāka nekā to nodošana, izmantojot komandrindas argumentus. Lai saprastu, kā CSI pievienot atbalstu apjoma lietojuma metrikai, pievienojot standartizētu gRPC metodi, varat lasīt: mūsu izvilkšanas pieprasījums vsphere-csi draiverim.
  • Saziņa notiek, izmantojot IPC ligzdas, lai neapjuktu, vai kubelet pieprasījumu nosūtīja uz pareizo podziņu.

Vai šis saraksts jums kaut ko atgādina? CSI priekšrocības ir atrisināt šīs pašas problēmas, kas netika ņemti vērā, izstrādājot spraudni Flexvolume.

Atzinumi

CSI kā standartu pielāgotu spraudņu ieviešanai mijiedarbībai ar datu noliktavām sabiedrība uzņēma ļoti sirsnīgi. Turklāt to priekšrocību un daudzpusības dēļ CSI draiveri tiek izveidoti pat tādām uzglabāšanas sistēmām kā Ceph vai AWS EBS, spraudņi darbam ar kuriem tika pievienoti jau pirmajā Kubernetes versijā.

2019. gada sākumā in-tree spraudņi ir pasludināti par novecojušiem. Mēs plānojam turpināt atbalstīt Flexvolume spraudni, taču neizstrādāsim tam jaunu funkcionalitāti.

Mums pašiem jau ir pieredze ceph-csi, vsphere-csi lietošanā un esam gatavi papildināt šo sarakstu! Pagaidām CSI ar tai uzticētajiem uzdevumiem tiek galā ar uzviju, taču pagaidīsim un redzēsim.

Neaizmirstiet, ka viss jaunais ir laba vecā pārdomāšana!

PS

Lasi arī mūsu emuārā:

Avots: www.habr.com

Pievieno komentāru