Πρόσθετα τόμου για αποθήκευση Kubernetes: από το Flexvolume στο CSI

Πρόσθετα τόμου για αποθήκευση Kubernetes: από το Flexvolume στο CSI

Όταν το Kubernetes ήταν ακόμα έκδοση 1.0.0, υπήρχαν πρόσθετα τόμου. Χρειάζονταν για τη σύνδεση συστημάτων με το Kubernetes για την αποθήκευση μόνιμων (μόνιμων) δεδομένων κοντέινερ. Ο αριθμός τους ήταν μικρός και μεταξύ των πρώτων ήταν παρόχοι αποθήκευσης όπως GCE PD, Ceph, AWS EBS και άλλοι.

Τα πρόσθετα παραδόθηκαν μαζί με το Kubernetes, γι' αυτό και πήραν το όνομά τους - in-tree. Ωστόσο, για πολλούς, το υπάρχον σύνολο τέτοιων προσθηκών αποδείχθηκε ανεπαρκές. Οι τεχνίτες πρόσθεσαν απλά πρόσθετα στον πυρήνα του Kubernetes χρησιμοποιώντας patches, μετά τα οποία συναρμολόγησαν τα δικά τους Kubernetes και τα εγκατέστησαν στους διακομιστές τους. Αλλά με την πάροδο του χρόνου, οι προγραμματιστές της Kubernetes το συνειδητοποίησαν ψάρι το πρόβλημα δεν μπορεί να λυθεί. Οι άνθρωποι χρειάζονται καλάμι ψαρέματος. Και στην κυκλοφορία του Kubernetes v1.2.0 εμφανίστηκε...

Πρόσθετο Flexvolume: ελάχιστο καλάμι ψαρέματος

Οι προγραμματιστές της Kubernetes δημιούργησαν το πρόσθετο FlexVolume, το οποίο ήταν ένα λογικό πλαίσιο μεταβλητών και μεθόδων εργασίας με προγράμματα οδήγησης Flexvolume που εφαρμόστηκαν από τρίτους προγραμματιστές.

Ας σταματήσουμε και ας δούμε πιο προσεκτικά τι είναι το πρόγραμμα οδήγησης FlexVolume. Αυτό είναι βέβαιο εκτελέσιμο αρχείο (δυαδικό αρχείο, σενάριο Python, σενάριο Bash, κ.λπ.), το οποίο, όταν εκτελείται, λαμβάνει ορίσματα γραμμής εντολών ως είσοδο και επιστρέφει ένα μήνυμα με γνωστά πεδία σε μορφή JSON. Κατά σύμβαση, το πρώτο όρισμα της γραμμής εντολών είναι πάντα μια μέθοδος και τα υπόλοιπα ορίσματα είναι οι παράμετροί του.

Πρόσθετα τόμου για αποθήκευση Kubernetes: από το Flexvolume στο CSI
Διάγραμμα σύνδεσης για Μετοχές CIFS στο OpenShift. Πρόγραμμα οδήγησης Flexvolume - Ακριβώς στο κέντρο

Ελάχιστο σύνολο μεθόδων μοιάζει με αυτό:

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

Χρήση Μεθόδων attach и detach θα καθορίσει το σενάριο στο οποίο θα ενεργήσει το kubelet στο μέλλον όταν καλεί τον οδηγό. Υπάρχουν και ειδικές μέθοδοι expandvolume и expandfs, τα οποία είναι υπεύθυνα για τη δυναμική αλλαγή του μεγέθους της έντασης.

Ως παράδειγμα των αλλαγών που προσθέτει η μέθοδος expandvolume, και με τη δυνατότητα αλλαγής μεγέθους τόμων σε πραγματικό χρόνο, μπορείτε να εξοικειωθείτε το αίτημα έλξης μας στο Rook Ceph Operator.

Και εδώ είναι ένα παράδειγμα εφαρμογής του προγράμματος οδήγησης Flexvolume για εργασία με 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

Έτσι, αφού προετοιμάσετε το πραγματικό εκτελέσιμο αρχείο, πρέπει ανεβάστε το πρόγραμμα οδήγησης στο σύμπλεγμα Kubernetes. Το πρόγραμμα οδήγησης πρέπει να βρίσκεται σε κάθε κόμβο συμπλέγματος σύμφωνα με μια προκαθορισμένη διαδρομή. Από προεπιλογή επιλέχθηκε:

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

... αλλά όταν χρησιμοποιείτε διαφορετικές διανομές Kubernetes (OpenShift, Rancher...) η διαδρομή μπορεί να είναι διαφορετική.

Προβλήματα Flexvolume: πώς να πετάξετε σωστά ένα καλάμι ψαρέματος;

Η μεταφόρτωση του προγράμματος οδήγησης Flexvolume σε κόμβους συμπλέγματος αποδείχθηκε ότι ήταν μια μη τετριμμένη εργασία. Έχοντας κάνει τη λειτουργία χειροκίνητα μία φορά, είναι εύκολο να αντιμετωπίσετε μια κατάσταση όπου εμφανίζονται νέοι κόμβοι στο σύμπλεγμα: λόγω της προσθήκης ενός νέου κόμβου, της αυτόματης οριζόντιας κλίμακας ή - το χειρότερο - της αντικατάστασης ενός κόμβου λόγω δυσλειτουργίας. Σε αυτήν την περίπτωση, θα πρέπει να γίνει εργασία με την αποθήκευση σε αυτούς τους κόμβους είναι αδύνατο, μέχρι να προσθέσετε χειροκίνητα το πρόγραμμα οδήγησης Flexvolume σε αυτά.

Η λύση σε αυτό το πρόβλημα ήταν ένας από τους πρωτόγονους Kubernetes - DaemonSet. Όταν εμφανίζεται ένας νέος κόμβος στο σύμπλεγμα, περιέχει αυτόματα ένα pod από το DaemonSet, στο οποίο προσαρτάται ένας τοπικός τόμος κατά μήκος της διαδρομής για την εύρεση προγραμμάτων οδήγησης Flexvolume. Μετά την επιτυχή δημιουργία, το pod αντιγράφει τα απαραίτητα αρχεία για να εργαστεί το πρόγραμμα οδήγησης στο δίσκο.

Ακολουθεί ένα παράδειγμα τέτοιου DaemonSet για τη διάταξη ενός πρόσθετου 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>

... και ένα παράδειγμα σεναρίου Bash για τη διάταξη του προγράμματος οδήγησης 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

Είναι σημαντικό να μην ξεχνάμε ότι η λειτουργία αντιγραφής δεν είναι ατομικό. Υπάρχει μεγάλη πιθανότητα το kubelet να αρχίσει να χρησιμοποιεί το πρόγραμμα οδήγησης πριν ολοκληρωθεί η διαδικασία παροχής του, κάτι που θα προκαλέσει σφάλμα στο σύστημα. Η σωστή προσέγγιση είναι να αντιγράψετε πρώτα τα αρχεία προγραμμάτων οδήγησης με διαφορετικό όνομα και στη συνέχεια να χρησιμοποιήσετε μια λειτουργία ατομικής μετονομασίας.

Πρόσθετα τόμου για αποθήκευση Kubernetes: από το Flexvolume στο CSI
Διάγραμμα εργασίας με τον Ceph στον χειριστή Rook: το πρόγραμμα οδήγησης Flexvolume στο διάγραμμα βρίσκεται μέσα στον πράκτορα Rook

Το επόμενο πρόβλημα κατά τη χρήση προγραμμάτων οδήγησης Flexvolume είναι ότι για την περισσότερη αποθήκευση σε έναν κόμβο συμπλέγματος πρέπει να εγκατασταθεί το απαραίτητο λογισμικό για αυτό (για παράδειγμα, το πακέτο ceph-common για το Ceph). Αρχικά, το πρόσθετο Flexvolume δεν σχεδιάστηκε για την υλοποίηση τόσο πολύπλοκων συστημάτων.

Μια πρωτότυπη λύση σε αυτό το πρόβλημα μπορεί να δει κανείς στην υλοποίηση του προγράμματος οδήγησης Flexvolume του τελεστή Rook:

Το ίδιο το πρόγραμμα οδήγησης έχει σχεδιαστεί ως πελάτης RPC. Η υποδοχή IPC για επικοινωνία βρίσκεται στον ίδιο κατάλογο με το ίδιο το πρόγραμμα οδήγησης. Θυμόμαστε ότι για να αντιγράψετε αρχεία προγραμμάτων οδήγησης καλό θα ήταν να χρησιμοποιήσετε το DaemonSet, το οποίο συνδέει τον κατάλογο με το πρόγραμμα οδήγησης ως τόμο. Μετά την αντιγραφή των απαραίτητων αρχείων προγράμματος οδήγησης rook, αυτό το pod δεν πεθαίνει, αλλά συνδέεται στην υποδοχή IPC μέσω του συνημμένου τόμου ως πλήρης διακομιστής RPC. Το πακέτο ceph-common είναι ήδη εγκατεστημένο μέσα στο κοντέινερ pod. Η υποδοχή IPC διασφαλίζει ότι το kubelet θα επικοινωνεί ακριβώς με το pod που βρίσκεται στον ίδιο κόμβο. Όλα τα έξυπνα είναι απλά!..

Αντίο, τα στοργικά μας... in-tree plugins!

Οι προγραμματιστές της Kubernetes ανακάλυψαν ότι ο αριθμός των προσθηκών για αποθήκευση στον πυρήνα είναι είκοσι. Και μια αλλαγή σε καθένα από αυτά, με τον ένα ή τον άλλο τρόπο, περνάει από τον πλήρη κύκλο κυκλοφορίας του Kubernetes.

Αποδεικνύεται ότι για να χρησιμοποιήσετε τη νέα έκδοση της προσθήκης αποθήκευσης, πρέπει να ενημερώσετε ολόκληρο το σύμπλεγμα. Επιπλέον, μπορεί να εκπλαγείτε που η νέα έκδοση του Kubernetes θα γίνει ξαφνικά ασυμβίβαστη με τον πυρήνα του Linux που χρησιμοποιείτε... Έτσι σκουπίζετε τα δάκρυά σας και, σφίζοντας τα δόντια σας, συντονίζετε με τη διοίκηση και τους χρήστες την ώρα να ενημερώστε τον πυρήνα του Linux και το σύμπλεγμα Kubernetes. Με πιθανή διακοπή στην παροχή υπηρεσιών.

Η κατάσταση είναι κάτι παραπάνω από κωμική, δεν νομίζετε; Έγινε σαφές σε ολόκληρη την κοινότητα ότι η προσέγγιση δεν λειτούργησε. Με μια εσκεμμένη απόφαση, οι προγραμματιστές του Kubernetes ανακοινώνουν ότι οι νέες προσθήκες για εργασία με χώρο αποθήκευσης δεν θα γίνονται πλέον αποδεκτές στον πυρήνα. Επιπλέον, όπως ήδη γνωρίζουμε, εντοπίστηκαν μια σειρά από ελλείψεις στην υλοποίηση του πρόσθετου Flexvolume...

Η πιο πρόσφατη προσθήκη για τόμους στο Kubernetes, CSI, κλήθηκε να κλείσει το ζήτημα με τη μόνιμη αποθήκευση δεδομένων μια για πάντα. Η άλφα έκδοσή του, που αναφέρεται πληρέστερα ως Out-of-Tree CSI Volume Plugins, ανακοινώθηκε στην κυκλοφορία Κουμπερνέτες 1.9.

Container Storage Interface ή CSI 3000 spinning rod!

Πρώτα απ 'όλα, θα ήθελα να σημειώσω ότι το CSI δεν είναι απλώς ένα πρόσθετο όγκου, αλλά ένα πραγματικό πρότυπο σχετικά με τη δημιουργία προσαρμοσμένων στοιχείων για εργασία με αποθήκες δεδομένων. Τα συστήματα ενορχήστρωσης κοντέινερ όπως το Kubernetes και το Mesos υποτίθεται ότι «μάθαιναν» πώς να εργάζονται με εξαρτήματα που υλοποιούνται σύμφωνα με αυτό το πρότυπο. Και τώρα έχω ήδη μάθει Kubernetes.

Ποια είναι η δομή της προσθήκης CSI στο Kubernetes; Το πρόσθετο CSI λειτουργεί με ειδικά προγράμματα οδήγησης (Προγράμματα οδήγησης CSI) γραμμένο από τρίτους προγραμματιστές. Ένα πρόγραμμα οδήγησης CSI στο Kubernetes θα πρέπει να αποτελείται τουλάχιστον από δύο στοιχεία (pods):

  • ελεγκτής — διαχειρίζεται εξωτερικές μόνιμες αποθήκες. Υλοποιείται ως διακομιστής gRPC, για τον οποίο χρησιμοποιείται το πρωτόγονο StatefulSet.
  • Κόμβος — είναι υπεύθυνος για την τοποθέτηση μόνιμης αποθήκευσης σε κόμβους συμπλέγματος. Εφαρμόζεται επίσης ως διακομιστής gRPC, αλλά χρησιμοποιεί το πρωτόγονο DaemonSet.

Πρόσθετα τόμου για αποθήκευση Kubernetes: από το Flexvolume στο CSI
Πώς λειτουργεί η προσθήκη CSI στο Kubernetes

Μπορείτε να μάθετε για κάποιες άλλες λεπτομέρειες της δουλειάς του CSI, για παράδειγμα, από το άρθρο "Κατανόηση του C.S.I.» μετάφραση του οποίου δημοσιεύσαμε πριν από ένα χρόνο.

Τα πλεονεκτήματα μιας τέτοιας υλοποίησης

  • Για βασικά πράγματα όπως η εγγραφή ενός προγράμματος οδήγησης για έναν κόμβο, οι προγραμματιστές του Kubernetes εφάρμοσαν ένα σύνολο κοντέινερ. Δεν χρειάζεται πλέον να δημιουργείτε μόνοι σας μια απάντηση JSON με δυνατότητες, όπως έγινε για την προσθήκη Flexvolume.
  • Αντί να «γλιστρήσουμε» εκτελέσιμα αρχεία σε κόμβους, τώρα ανεβάζουμε pods στο σύμπλεγμα. Αυτό είναι που αρχικά περιμένουμε από το Kubernetes: όλες οι διεργασίες συμβαίνουν μέσα σε κοντέινερ που αναπτύσσονται χρησιμοποιώντας πρωτόγονα Kubernetes.
  • Δεν χρειάζεται πλέον να αναπτύξετε έναν διακομιστή RPC και έναν πελάτη RPC για την υλοποίηση πολύπλοκων προγραμμάτων οδήγησης. Ο πελάτης υλοποιήθηκε για εμάς από προγραμματιστές Kubernetes.
  • Η διαβίβαση ορισμάτων για εργασία μέσω του πρωτοκόλλου gRPC είναι πολύ πιο βολική, ευέλικτη και αξιόπιστη από τη διαβίβασή τους μέσω ορισμάτων γραμμής εντολών. Για να κατανοήσετε πώς μπορείτε να προσθέσετε υποστήριξη για μετρήσεις χρήσης όγκου στο CSI προσθέτοντας μια τυποποιημένη μέθοδο gRPC, μπορείτε να διαβάσετε: το αίτημα έλξης μας για το πρόγραμμα οδήγησης vsphere-csi.
  • Η επικοινωνία πραγματοποιείται μέσω υποδοχών IPC, για να μην μπερδευτείτε εάν το kubelet έστειλε το αίτημα στο σωστό pod.

Σας θυμίζει κάτι αυτή η λίστα; Τα πλεονεκτήματα του CSI είναι επίλυση των ίδιων προβλημάτων, τα οποία δεν ελήφθησαν υπόψη κατά την ανάπτυξη της προσθήκης Flexvolume.

Ευρήματα

Το CSI ως πρότυπο για την εφαρμογή προσαρμοσμένων προσθηκών για αλληλεπίδραση με αποθήκες δεδομένων έγινε δεκτό πολύ θερμά από την κοινότητα. Επιπλέον, λόγω των πλεονεκτημάτων και της ευελιξίας τους, τα προγράμματα οδήγησης CSI δημιουργούνται ακόμη και για συστήματα αποθήκευσης όπως το Ceph ή το AWS EBS, πρόσθετα για εργασία με τα οποία προστέθηκαν στην πρώτη κιόλας έκδοση του Kubernetes.

Στις αρχές του 2019, in-tree plugins έχουν κηρυχθεί απαρχαιωμένες. Σκοπεύουμε να συνεχίσουμε να υποστηρίζουμε το πρόσθετο Flexvolume, αλλά δεν θα αναπτύξουμε νέες λειτουργίες για αυτό.

Εμείς οι ίδιοι έχουμε ήδη εμπειρία χρήσης ceph-csi, vsphere-csi και είμαστε έτοιμοι να προσθέσουμε σε αυτή τη λίστα! Μέχρι στιγμής, η CSI αντιμετωπίζει τις εργασίες που της έχουν ανατεθεί με μεγάλη ταχύτητα, αλλά θα περιμένουμε και θα δούμε.

Μην ξεχνάτε ότι κάθε νέο είναι μια καλή επανεξέταση του παλιού!

PS

Διαβάστε επίσης στο blog μας:

Πηγή: www.habr.com

Προσθέστε ένα σχόλιο