Приклучоци за волумен за складирање на Kubernetes: од Flexvolume до CSI

Приклучоци за волумен за складирање на Kubernetes: од Flexvolume до CSI

Кога Кубернетс сè уште беше v1.0.0, имаше приклучоци за волумен. Тие беа потребни за поврзување на системи со Kubernetes за складирање на постојани (постојани) податоци за контејнери. Нивниот број беше мал, а меѓу првите беа даватели на складирање како GCE PD, Ceph, AWS EBS и други.

Приклучоците беа испорачани заедно со Kubernetes, поради што го добија своето име - in-tree. Сепак, за многумина, постојниот сет на такви приклучоци се покажа како недоволен. Занаетчиите додадоа едноставни приклучоци во јадрото на Kubernetes користејќи закрпи, по што тие склопија свои 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 ќе го дефинира сценариото во кое кубелетот ќе дејствува во иднина при повикување на возачот. Постојат и посебни методи 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

Значи, откако ќе ја подготвите вистинската извршна датотека, треба да поставете го драјверот во кластерот Кубернетес. Возачот мора да се наоѓа на секој јазол на кластерот според однапред одредена патека. Стандардно беше избрано:

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

... но кога користите различни распределби на Kubernetes (OpenShift, Rancher...) патеката може да биде различна.

Проблеми со Flexvolume: како правилно да се фрли риболовен стап?

Поставувањето на двигателот Flexvolume во јазлите на кластерот се покажа како нетривијална задача. Откако ќе ја извршите операцијата рачно еднаш, лесно е да се сретнете со ситуација кога се појавуваат нови јазли во кластерот: поради додавање нов јазол, автоматско хоризонтално скалирање или - што е уште полошо - замена на јазол поради дефект. Во овој случај, треба да се работи со складирањето на овие јазли е невозможно, додека сè уште рачно не го додадете двигателот Flexvolume на нив.

Решението за овој проблем беше едно од примитивите на Кубернет - DaemonSet. Кога ќе се појави нов јазол во кластерот, тој автоматски содржи подлога од нашиот DaemonSet, на кој е прикачен локален волумен по патеката за да се најдат двигатели на Flexvolume. По успешното создавање, подлогата ги копира потребните датотеки за двигателот да работи на дискот.

Еве пример за таков 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

Важно е да не се заборави дека операцијата за копирање не е атомски. Има големи шанси кубелетот да почне да го користи двигателот пред да заврши процесот на неговото обезбедување, што ќе предизвика пад на системот. Точниот пристап е прво да ги копирате датотеките на драјверите под друго име, а потоа да користите операција за атомско преименување.

Приклучоци за волумен за складирање на Kubernetes: од Flexvolume до CSI
Дијаграм за работа со Ceph во операторот Rook: двигателот Flexvolume во дијаграмот се наоѓа во агентот Rook

Следниот проблем при користење на двигатели на Flexvolume е тој за повеќето складишта на јазол на кластерот мора да се инсталира потребниот софтвер за ова (на пример, ceph-common пакетот за Ceph). Првично, приклучокот Flexvolume не беше дизајниран да имплементира такви сложени системи.

Оригинално решение за овој проблем може да се види во имплементацијата на двигателот Flexvolume на операторот Rook:

Самиот драјвер е дизајниран како RPC клиент. IPC приклучокот за комуникација се наоѓа во истиот директориум како и самиот драјвер. Се сеќаваме дека за копирање на датотеки со драјвери би било добро да се користи DaemonSet, кој го поврзува директориумот со драјверот како волумен. По копирањето на потребните датотеки за двигател на rook, овој подлог не умира, туку се поврзува со приклучокот IPC преку приложениот волумен како полноправен RPC сервер. Пакетот ceph-common е веќе инсталиран во контејнерот за подлоги. IPC приклучокот осигурува дека кубелетот ќе комуницира токму со подлогата што се наоѓа на истиот јазол. Сè што е генијално е едноставно!..

Збогум, нашите приврзани... приклучоци во дрвото!

Програмерите на Kubernetes открија дека бројот на приклучоци за складирање во јадрото е дваесет. И промената во секоја од нив, на еден или друг начин, поминува низ целиот циклус на издавање на Кубернет.

Излегува дека за да ја користите новата верзија на приклучокот за складирање, треба да го ажурирате целиот кластер. Покрај ова, можеби ќе бидете изненадени што новата верзија на Kubernetes наеднаш ќе стане некомпатибилна со кернелот на Linux што го користите... Така ги бришете солзите и, стегајќи ги забите, се координирате со вашето раководство и корисниците времето да ажурирајте го кернелот Линукс и кластерот Кубернетес. Со можно застој во обезбедувањето на услугите.

Ситуацијата е повеќе од комична, не мислите? На целата заедница и стана јасно дека пристапот не функционира. Со намерна одлука, програмерите на Kubernetes објавуваат дека новите приклучоци за работа со складирање повеќе нема да бидат прифатени во кернелот. Дополнително, како што веќе знаеме, беа идентификувани низа недостатоци при имплементацијата на додатокот Flexvolume...

Најновиот додаден приклучок за тома во Kubernetes, CSI, беше повикан да го затвори проблемот со постојано складирање на податоци еднаш засекогаш. Неговата алфа верзија, поцелосно наречена „CSI Volume Plugins“ надвор од дрвото, беше објавена во изданието Кубернес 1.9.

Интерфејс за складирање на контејнери, или шипка за вртење CSI 3000!

Пред сè, би сакал да забележам дека 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.
  • Наместо да „лизгаме“ извршни датотеки на јазли, сега поставуваме подлоги во кластерот. Ова е она што првично го очекуваме од Kubernetes: сите процеси се случуваат во контејнерите распоредени со помош на примитивите на Kubernetes.
  • Повеќе не треба да развивате RPC сервер и RPC клиент за да имплементирате сложени драјвери. Клиентот беше имплементиран за нас од развивачите на Кубернетес.
  • Предавањето аргументи за работа преку протоколот gRPC е многу поудобно, флексибилно и посигурно отколку нивното пренесување преку аргументите на командната линија. За да разберете како да додадете поддршка за метрика за користење волумен на CSI со додавање стандардизиран метод gRPC, можете да прочитате: нашето барање за повлекување за драјвер за vsphere-csi.
  • Комуникацијата се јавува преку IPC приклучоци, за да не се збуни дали кубелетот го испратил барањето до правилната подлога.

Дали оваа листа ве потсетува на нешто? Предностите на CSI се решавање на истите тие проблеми, кои не беа земени предвид при развивањето на приклучокот Flexvolume.

Наоди

CSI како стандард за имплементирање на сопствени приклучоци за интеракција со складишта на податоци беше многу топло примен од заедницата. Покрај тоа, поради нивните предности и разноврсност, CSI драјверите се создадени дури и за системи за складирање како што се Ceph или AWS EBS, приклучоци за работа со кои беа додадени во првата верзија на Kubernetes.

На почетокот на 2019 година, приклучоци во дрвото се прогласени за застарени. Планираме да продолжиме да го поддржуваме додатокот Flexvolume, но нема да развиваме нова функционалност за него.

Ние самите веќе имаме искуство со користење на ceph-csi, vsphere-csi и сме подготвени да го додадеме на оваа листа! Досега, CSI се справува со задачите што и се доделени, но ќе почекаме и ќе видиме.

Не заборавајте дека сè ново е добро преиспитување на старото!

PS

Прочитајте и на нашиот блог:

Извор: www.habr.com

Додадете коментар