ปลั๊กอินโวลุ่มสำหรับพื้นที่เก็บข้อมูล Kubernetes: จาก Flexvolume ไปจนถึง CSI

ปลั๊กอินโวลุ่มสำหรับพื้นที่เก็บข้อมูล Kubernetes: จาก Flexvolume ไปจนถึง CSI

ย้อนกลับไปเมื่อ Kubernetes ยังคงเป็น v1.0.0 มีปลั๊กอินวอลลุ่ม จำเป็นสำหรับการเชื่อมต่อระบบกับ Kubernetes เพื่อจัดเก็บข้อมูลคอนเทนเนอร์ถาวร (ถาวร) มีจำนวนไม่มากนัก และผู้ให้บริการพื้นที่จัดเก็บข้อมูลรายแรกๆ เช่น GCE PD, Ceph, AWS EBS และอื่นๆ

ปลั๊กอินถูกส่งไปพร้อมกับ Kubernetes ซึ่งเป็นเหตุผลว่าทำไมพวกเขาถึงได้รับชื่อ - ในแผนผัง อย่างไรก็ตาม สำหรับหลาย ๆ คน ชุดปลั๊กอินดังกล่าวที่มีอยู่กลับไม่เพียงพอ ช่างฝีมือเพิ่มปลั๊กอินง่ายๆ ให้กับแกน Kubernetes โดยใช้แพตช์ หลังจากนั้นพวกเขาก็รวบรวม Kubernetes ของตัวเองและติดตั้งบนเซิร์ฟเวอร์ของพวกเขา แต่เมื่อเวลาผ่านไป นักพัฒนา Kubernetes ก็ตระหนักเรื่องนั้น ปลา ปัญหาไม่สามารถแก้ไขได้ คนต้องการ เบ็ดตกปลา. และในการเปิดตัว Kubernetes v1.2.0 ปรากฏว่า...

ปลั๊กอิน Flexvolume: คันเบ็ดขั้นต่ำ

นักพัฒนา Kubernetes ได้สร้างปลั๊กอิน FlexVolume ซึ่งเป็นเฟรมเวิร์กเชิงตรรกะของตัวแปรและวิธีการทำงานกับไดรเวอร์ Flexvolume ที่นักพัฒนาบุคคลที่สามนำมาใช้

เรามาหยุดดูกันดีกว่าว่าไดรเวอร์ FlexVolume คืออะไร นี่เป็นเรื่องแน่นอน ไฟล์ปฏิบัติการ (ไฟล์ไบนารี, สคริปต์ Python, สคริปต์ Bash ฯลฯ) ซึ่งเมื่อดำเนินการแล้ว จะใช้อาร์กิวเมนต์บรรทัดคำสั่งเป็นอินพุต และส่งคืนข้อความที่มีฟิลด์ที่รู้จักล่วงหน้าในรูปแบบ JSON ตามแบบแผน อาร์กิวเมนต์บรรทัดคำสั่งแรกจะเป็นวิธีการเสมอ และอาร์กิวเมนต์ที่เหลือจะเป็นพารามิเตอร์

ปลั๊กอินโวลุ่มสำหรับพื้นที่เก็บข้อมูล Kubernetes: จาก Flexvolume ไปจนถึง CSI
แผนภาพการเชื่อมต่อสำหรับ CIFS Shares ใน 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

และนี่คือตัวอย่างการใช้งานไดรเวอร์ 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. เมื่อโหนดใหม่ปรากฏในคลัสเตอร์ โหนดนั้นจะมีพ็อดจาก 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

สิ่งสำคัญคือต้องไม่ลืมว่าการดำเนินการคัดลอก ไม่ใช่อะตอม. มีโอกาสสูงที่ kubelet จะเริ่มใช้ไดรเวอร์ก่อนที่กระบวนการจัดเตรียมจะเสร็จสิ้น ส่งผลให้ระบบขัดข้อง วิธีการที่ถูกต้องคือการคัดลอกไฟล์ไดรเวอร์ภายใต้ชื่ออื่นก่อน จากนั้นจึงใช้การดำเนินการเปลี่ยนชื่อแบบอะตอมมิก

ปลั๊กอินโวลุ่มสำหรับพื้นที่เก็บข้อมูล Kubernetes: จาก Flexvolume ไปจนถึง CSI
ไดอะแกรมของการทำงานร่วมกับ Ceph ในตัวดำเนินการ Rook: ไดรเวอร์ Flexvolume ในไดอะแกรมนั้นอยู่ภายในตัวแทน Rook

ปัญหาถัดไปเมื่อใช้ไดรเวอร์ Flexvolume คือสำหรับพื้นที่เก็บข้อมูลส่วนใหญ่บนโหนดคลัสเตอร์ ต้องติดตั้งซอฟต์แวร์ที่จำเป็นสำหรับสิ่งนี้ (เช่น แพ็คเกจ ceph-common สำหรับ Ceph) เริ่มแรกปลั๊กอิน Flexvolume ไม่ได้ออกแบบมาเพื่อใช้งานระบบที่ซับซ้อนดังกล่าว

วิธีแก้ไขปัญหาดั้งเดิมสำหรับปัญหานี้สามารถดูได้ในการใช้งานไดรเวอร์ Flexvolume ของตัวดำเนินการ Rook:

ตัวไดร์เวอร์ได้รับการออกแบบให้เป็นไคลเอนต์ RPC ซ็อกเก็ต IPC สำหรับการสื่อสารอยู่ในไดเร็กทอรีเดียวกันกับไดรเวอร์ เราจำไว้ว่าในการคัดลอกไฟล์ไดรเวอร์ จะเป็นการดีถ้าใช้ DaemonSet ซึ่งเชื่อมต่อไดเร็กทอรีกับไดรเวอร์เป็นโวลุ่ม หลังจากคัดลอกไฟล์ไดรเวอร์โกงที่จำเป็น พ็อดนี้จะไม่ตาย แต่จะเชื่อมต่อกับซ็อกเก็ต IPC ผ่านโวลุ่มที่แนบมาเป็นเซิร์ฟเวอร์ RPC ที่มีคุณสมบัติครบถ้วน แพ็กเกจ ceph-common ได้รับการติดตั้งภายในคอนเทนเนอร์พ็อดแล้ว ซ็อกเก็ต IPC ช่วยให้มั่นใจได้ว่า kubelet จะสื่อสารกับพ็อดที่อยู่บนโหนดเดียวกันทุกประการ ทุกสิ่งอันชาญฉลาดนั้นเรียบง่าย!..

ลาก่อน... ปลั๊กอินในแผนผังที่น่ารักของเรา!

นักพัฒนา Kubernetes ค้นพบว่าจำนวนปลั๊กอินสำหรับจัดเก็บข้อมูลภายในคอร์คือยี่สิบ และการเปลี่ยนแปลงในแต่ละอย่างไม่ทางใดก็ทางหนึ่งต้องผ่านวงจรการเปิดตัว Kubernetes เต็มรูปแบบ

ปรากฎว่าการใช้ปลั๊กอินจัดเก็บข้อมูลเวอร์ชันใหม่ คุณต้องอัปเดตคลัสเตอร์ทั้งหมด. นอกจากนี้ คุณอาจแปลกใจที่ Kubernetes เวอร์ชันใหม่เข้ากันไม่ได้กับเคอร์เนล Linux ที่คุณใช้อยู่... ดังนั้น คุณจึงปาดน้ำตาและกัดฟัน ประสานงานกับฝ่ายบริหารและผู้ใช้ของคุณในเวลาที่จะ อัปเดตเคอร์เนล Linux และคลัสเตอร์ Kubernetes ด้วยการหยุดทำงานที่เป็นไปได้ในการให้บริการ

สถานการณ์มันยิ่งกว่าตลกนะคุณว่ามั้ย? เป็นที่ชัดเจนแก่ชุมชนทั้งหมดว่าแนวทางดังกล่าวไม่ได้ผล จากการตัดสินใจโดยเจตนานักพัฒนา Kubernetes ประกาศว่าปลั๊กอินใหม่สำหรับการทำงานกับที่เก็บข้อมูลจะไม่ได้รับการยอมรับในเคอร์เนลอีกต่อไป นอกจากนี้ อย่างที่เราทราบกันดีอยู่แล้ว มีการระบุข้อบกพร่องหลายประการในการใช้งานปลั๊กอิน Flexvolume...

ปลั๊กอินที่เพิ่มล่าสุดสำหรับวอลุ่มใน Kubernetes หรือ CSI ถูกเรียกใช้เพื่อปิดปัญหาด้วยการจัดเก็บข้อมูลแบบถาวรทันทีและตลอดไป เวอร์ชันอัลฟ่าหรือเรียกเต็มๆ ว่า Out-of-Tree CSI Volume Plugins ได้รับการประกาศในเวอร์ชันนี้ คูเบอร์เนเตส 1.9.

อินเตอร์เฟซการจัดเก็บคอนเทนเนอร์หรือคันหมุน CSI 3000!

ก่อนอื่น ฉันอยากจะทราบว่า CSI ไม่ได้เป็นเพียงปลั๊กอินโวลุ่ม แต่เป็นของจริง มาตรฐาน เกี่ยวกับการสร้างส่วนประกอบที่กำหนดเองสำหรับการทำงานกับคลังข้อมูล. ระบบการจัดการคอนเทนเนอร์ เช่น Kubernetes และ Mesos ควรจะ "เรียนรู้" วิธีทำงานกับส่วนประกอบต่างๆ ที่นำมาใช้ตามมาตรฐานนี้ และตอนนี้ฉันได้เรียนรู้ Kubernetes แล้ว

โครงสร้างของปลั๊กอิน CSI ใน Kubernetes คืออะไร? ปลั๊กอิน CSI ทำงานร่วมกับไดรเวอร์พิเศษ (คนขับรถซีเอสไอ) เขียนโดยนักพัฒนาบุคคลที่สาม ไดรเวอร์ CSI ใน Kubernetes ควรประกอบด้วยสององค์ประกอบน้อยที่สุด (พ็อด):

  • ตัวควบคุม — จัดการการจัดเก็บข้อมูลถาวรภายนอก มันถูกนำไปใช้เป็นเซิร์ฟเวอร์ gRPC ซึ่งใช้แบบดั้งเดิม StatefulSet.
  • โหนด — รับผิดชอบในการติดตั้งที่เก็บข้อมูลถาวรไปยังโหนดคลัสเตอร์ นอกจากนี้ยังใช้เป็นเซิร์ฟเวอร์ gRPC แต่ใช้แบบดั้งเดิม DaemonSet.

ปลั๊กอินโวลุ่มสำหรับพื้นที่เก็บข้อมูล Kubernetes: จาก Flexvolume ไปจนถึง CSI
ปลั๊กอิน CSI ทำงานอย่างไรใน Kubernetes

คุณสามารถเรียนรู้รายละเอียดอื่นๆ เกี่ยวกับงานของ CSI ได้จากบทความ “ทำความเข้าใจกับ C.S.I.' การแปลซึ่ง เราเผยแพร่เมื่อปีที่แล้ว

ข้อดีของการดำเนินการดังกล่าว

  • สำหรับสิ่งพื้นฐาน เช่น การลงทะเบียนไดรเวอร์สำหรับโหนด นักพัฒนา Kubernetes ได้นำชุดคอนเทนเนอร์มาใช้ คุณไม่จำเป็นต้องสร้างการตอบสนอง JSON ด้วยความสามารถด้วยตนเองอีกต่อไป เช่นเดียวกับที่ทำกับปลั๊กอิน Flexvolume
  • แทนที่จะ "ลื่นไถล" ไฟล์ปฏิบัติการไปยังโหนด ตอนนี้เราจะอัปโหลดพ็อดไปยังคลัสเตอร์ นี่คือสิ่งที่เราคาดหวังในตอนแรกจาก Kubernetes: กระบวนการทั้งหมดเกิดขึ้นภายในคอนเทนเนอร์ที่ใช้งานโดยใช้ Kubernetes ดั้งเดิม
  • คุณไม่จำเป็นต้องพัฒนาเซิร์ฟเวอร์ RPC และไคลเอนต์ RPC เพื่อใช้ไดรเวอร์ที่ซับซ้อนอีกต่อไป ไคลเอ็นต์ถูกนำไปใช้ให้เราโดยนักพัฒนา Kubernetes
  • การส่งผ่านอาร์กิวเมนต์เพื่อทำงานบนโปรโตคอล gRPC นั้นสะดวก ยืดหยุ่น และเชื่อถือได้มากกว่าการส่งผ่านอาร์กิวเมนต์บรรทัดคำสั่ง หากต้องการทำความเข้าใจวิธีเพิ่มการรองรับตัววัดการใช้งานปริมาณให้กับ CSI โดยการเพิ่มวิธี gRPC ที่เป็นมาตรฐาน คุณสามารถอ่านได้: คำขอดึงของเรา สำหรับไดรเวอร์ vssphere-csi
  • การสื่อสารเกิดขึ้นผ่านซ็อกเก็ต IPC เพื่อไม่ให้สับสนว่า kubelet ส่งคำขอไปยังพ็อดที่ถูกต้องหรือไม่

รายการนี้เตือนคุณถึงสิ่งใดหรือไม่? ข้อดีของ CSI คือ แก้ไขปัญหาเดียวกันเหล่านั้นซึ่งไม่ได้นำมาพิจารณาเมื่อพัฒนาปลั๊กอิน Flexvolume

ผลการวิจัย

CSI ที่เป็นมาตรฐานสำหรับการนำปลั๊กอินแบบกำหนดเองไปใช้สำหรับการโต้ตอบกับคลังข้อมูลได้รับการตอบรับอย่างอบอุ่นจากชุมชน นอกจากนี้ เนื่องจากข้อดีและความอเนกประสงค์ ไดรเวอร์ CSI จึงถูกสร้างขึ้นแม้กระทั่งสำหรับระบบจัดเก็บข้อมูลเช่น Ceph หรือ AWS EBS ซึ่งเป็นปลั๊กอินสำหรับการทำงานที่เพิ่มเข้ามาใน Kubernetes เวอร์ชันแรกสุด

เมื่อต้นปี 2019 ปลั๊กอินในแผนผัง ได้รับการประกาศให้ล้าสมัย. เราวางแผนที่จะสนับสนุนปลั๊กอิน Flexvolume ต่อไป แต่จะไม่พัฒนาฟังก์ชันใหม่ๆ สำหรับปลั๊กอินดังกล่าว

เราเองมีประสบการณ์ในการใช้ ceph-csi, vsphere-csi อยู่แล้ว และพร้อมที่จะเพิ่มลงในรายการนี้! จนถึงตอนนี้ CSI กำลังรับมือกับงานที่ได้รับมอบหมายอย่างหนัก แต่เราจะรอดูกันต่อไป

อย่าลืมว่าทุกสิ่งใหม่คือการคิดใหม่ที่ดีจากสิ่งเก่า!

PS

อ่านเพิ่มเติมในบล็อกของเรา:

ที่มา: will.com

เพิ่มความคิดเห็น