Plugin khối lượng cho bộ lưu trữ Kubernetes: từ Flexvolume đến CSI

Plugin khối lượng cho bộ lưu trữ Kubernetes: từ Flexvolume đến CSI

Quay lại khi Kubernetes vẫn còn là v1.0.0, đã có plugin âm lượng. Chúng cần thiết để kết nối các hệ thống với Kubernetes nhằm lưu trữ dữ liệu vùng chứa liên tục (vĩnh viễn). Số lượng của họ rất ít và trong số những nhà cung cấp dịch vụ lưu trữ đầu tiên như GCE PD, Ceph, AWS EBS và những nhà cung cấp khác.

Các plugin được phân phối cùng với Kubernetes, đó là lý do tại sao chúng có tên - in-tree. Tuy nhiên, đối với nhiều người, bộ plugin như vậy hiện có hóa ra là không đủ. Những người thợ thủ công đã thêm các plugin đơn giản vào lõi Kubernetes bằng cách sử dụng các bản vá, sau đó họ tập hợp Kubernetes của riêng mình và cài đặt nó trên máy chủ của họ. Nhưng theo thời gian, các nhà phát triển Kubernetes nhận ra rằng vấn đề không thể được giải quyết. Mọi người cần que. Và trong bản phát hành Kubernetes v1.2.0, nó đã xuất hiện...

Plugin Flexvolume: cần câu tối thiểu

Các nhà phát triển Kubernetes đã tạo plugin FlexVolume, đây là một khung logic gồm các biến và phương thức để làm việc với trình điều khiển Flexvolume do các nhà phát triển bên thứ ba triển khai.

Hãy dừng lại và xem xét kỹ hơn trình điều khiển FlexVolume là gì. Đây là một điều chắc chắn tập tin thực thi (tệp nhị phân, tập lệnh Python, tập lệnh Bash, v.v.), khi được thực thi, sẽ lấy các đối số dòng lệnh làm đầu vào và trả về một thông báo với các trường đã biết trước ở định dạng JSON. Theo quy ước, đối số dòng lệnh đầu tiên luôn là một phương thức và các đối số còn lại là tham số của nó.

Plugin khối lượng cho bộ lưu trữ Kubernetes: từ Flexvolume đến CSI
Sơ đồ kết nối cho CIFS Shares trong OpenShift. Trình điều khiển Flexvolume - Ngay tại Trung tâm

Tập hợp các phương pháp tối thiểu Nó trông giống như thế này:

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

Sử dụng phương pháp attach и detach sẽ xác định kịch bản mà kubelet sẽ hoạt động trong tương lai khi gọi trình điều khiển. Ngoài ra còn có những phương pháp đặc biệt expandvolume и expandfs, chịu trách nhiệm thay đổi kích thước âm lượng một cách linh hoạt.

Như một ví dụ về những thay đổi mà phương thức thêm vào expandvolumevà với khả năng thay đổi kích thước âm lượng theo thời gian thực, bạn có thể tự làm quen với yêu cầu kéo của chúng tôi trong Nhà điều hành Rook Ceph.

Và đây là một ví dụ về việc triển khai trình điều khiển Flexvolume để làm việc với 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

Vì vậy, sau khi chuẩn bị tệp thực thi thực tế, bạn cần phải tải trình điều khiển lên cụm Kubernetes. Trình điều khiển phải được đặt trên mỗi nút cụm theo một đường dẫn được xác định trước. Theo mặc định nó đã được chọn:

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

... nhưng khi sử dụng các bản phân phối Kubernetes khác nhau (OpenShift, Rancher...) thì đường dẫn có thể khác.

Vấn đề về Flexvolume: làm thế nào để đúc cần câu chính xác?

Tải trình điều khiển Flexvolume lên các nút cụm hóa ra là một nhiệm vụ không hề nhỏ. Sau khi thực hiện thao tác thủ công một lần, rất dễ gặp phải tình huống xuất hiện các nút mới trong cụm: do thêm nút mới, tự động chia tỷ lệ theo chiều ngang hoặc - tệ hơn là thay thế nút do trục trặc. Trong trường hợp này, nên thực hiện việc lưu trữ trên các nút này là không thể, cho đến khi bạn vẫn thêm trình điều khiển Flexvolume theo cách thủ công vào chúng.

Giải pháp cho vấn đề này là một trong những giải pháp nguyên thủy của Kubernetes - DaemonSet. Khi một nút mới xuất hiện trong cụm, nó sẽ tự động chứa một nhóm từ DaemonSet của chúng tôi, trong đó một ổ đĩa cục bộ được gắn dọc theo đường dẫn để tìm trình điều khiển Flexvolume. Sau khi tạo thành công, nhóm sẽ sao chép các tệp cần thiết để trình điều khiển hoạt động vào đĩa.

Dưới đây là ví dụ về DaemonSet để bố trí plugin 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>

... và một ví dụ về tập lệnh Bash để bố trí trình điều khiển 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

Điều quan trọng là đừng quên rằng thao tác sao chép không phải là nguyên tử. Có khả năng cao là kubelet sẽ bắt đầu sử dụng trình điều khiển trước khi quá trình cung cấp hoàn tất, khiến hệ thống gặp sự cố. Cách tiếp cận đúng là trước tiên sao chép các tệp trình điều khiển dưới một tên khác, sau đó sử dụng thao tác đổi tên nguyên tử.

Plugin khối lượng cho bộ lưu trữ Kubernetes: từ Flexvolume đến CSI
Sơ đồ làm việc với Ceph trong toán tử Rook: driver Flexvolume trong sơ đồ nằm bên trong Rook Agent

Vấn đề tiếp theo khi sử dụng trình điều khiển Flexvolume là hầu hết dung lượng lưu trữ trên một nút cụm phần mềm cần thiết cho việc này phải được cài đặt (ví dụ: gói ceph-common cho Ceph). Ban đầu, plugin Flexvolume không được thiết kế để triển khai các hệ thống phức tạp như vậy.

Có thể thấy giải pháp ban đầu cho vấn đề này trong quá trình triển khai trình điều khiển Flexvolume của toán tử Rook:

Bản thân trình điều khiển được thiết kế như một máy khách RPC. Ổ cắm IPC để liên lạc nằm trong cùng thư mục với chính trình điều khiển. Chúng tôi nhớ rằng để sao chép các tệp trình điều khiển, tốt nhất nên sử dụng DaemonSet, kết nối thư mục với trình điều khiển dưới dạng ổ đĩa. Sau khi sao chép các tệp trình điều khiển rook cần thiết, nhóm này không chết mà kết nối với ổ cắm IPC thông qua ổ đĩa đính kèm với tư cách là một máy chủ RPC chính thức. Gói ceph-common đã được cài đặt bên trong thùng chứa nhóm. Ổ cắm IPC đảm bảo rằng kubelet sẽ giao tiếp với chính xác nhóm nằm trên cùng một nút. Mọi thứ khéo léo đều đơn giản!..

Tạm biệt, plugin... in-tree tình cảm của chúng tôi!

Các nhà phát triển Kubernetes phát hiện ra rằng số lượng plugin để lưu trữ trong lõi là XNUMX. Và sự thay đổi trong mỗi chúng, bằng cách này hay cách khác, đều trải qua chu kỳ phát hành Kubernetes đầy đủ.

Hóa ra là để sử dụng phiên bản mới của plugin lưu trữ, bạn cần cập nhật toàn bộ cụm. Ngoài ra, bạn có thể ngạc nhiên rằng phiên bản mới của Kubernetes sẽ đột nhiên không tương thích với nhân Linux mà bạn đang sử dụng... Vì vậy, bạn lau nước mắt và nghiến răng, phối hợp với quản lý và người dùng của mình để kịp thời xử lý. cập nhật nhân Linux và cụm Kubernetes. Với thời gian ngừng hoạt động có thể xảy ra trong việc cung cấp dịch vụ.

Tình huống còn hơn cả hài hước, bạn có nghĩ vậy không? Toàn bộ cộng đồng thấy rõ rằng cách tiếp cận này không hiệu quả. Bằng một quyết định có chủ ý, các nhà phát triển Kubernetes thông báo rằng các plugin mới để làm việc với bộ lưu trữ sẽ không còn được chấp nhận vào kernel nữa. Ngoài ra, như chúng ta đã biết, một số thiếu sót đã được xác định trong quá trình triển khai plugin Flexvolume...

Plugin được bổ sung mới nhất cho khối lượng trong Kubernetes, CSI, được yêu cầu giải quyết vấn đề lưu trữ dữ liệu liên tục một lần và mãi mãi. Phiên bản alpha của nó, được gọi đầy đủ hơn là Plugin khối lượng CSI ngoài cây, đã được công bố trong bản phát hành Kubernetes 1.9.

Giao diện lưu trữ container hoặc thanh quay CSI 3000!

Trước hết, tôi muốn lưu ý rằng CSI không chỉ là một plugin âm lượng mà còn là một công cụ thực sự. Стандарт về việc tạo các thành phần tùy chỉnh để làm việc với kho dữ liệu. Các hệ thống điều phối container như Kubernetes và Mesos được cho là sẽ “học” cách làm việc với các thành phần được triển khai theo tiêu chuẩn này. Và bây giờ tôi đã học Kubernetes.

Cấu trúc của plugin CSI trong Kubernetes là gì? Plugin CSI hoạt động với trình điều khiển đặc biệt (Trình điều khiển CSI) được viết bởi các nhà phát triển bên thứ ba. Trình điều khiển CSI trong Kubernetes tối thiểu phải bao gồm hai thành phần (nhóm):

  • Người điều khiển — quản lý các kho lưu trữ liên tục bên ngoài. Nó được triển khai như một máy chủ gRPC, sử dụng nguyên thủy StatefulSet.
  • Node — chịu trách nhiệm gắn bộ lưu trữ liên tục vào các nút cụm. Nó cũng được triển khai như một máy chủ gRPC, nhưng nó sử dụng nguyên thủy DaemonSet.

Plugin khối lượng cho bộ lưu trữ Kubernetes: từ Flexvolume đến CSI
Cách plugin CSI hoạt động trong Kubernetes

Bạn có thể tìm hiểu về một số chi tiết khác về công việc của CSI, chẳng hạn như từ bài viết “Hiểu C.S.I.' bản dịch của nó chúng tôi đã xuất bản một năm trước.

Ưu điểm của việc thực hiện như vậy

  • Đối với những việc cơ bản như đăng ký trình điều khiển cho một nút, các nhà phát triển Kubernetes đã triển khai một bộ vùng chứa. Bạn không cần phải tự mình tạo phản hồi JSON bằng các khả năng như đã làm với plugin Flexvolume nữa.
  • Thay vì “đưa” các tệp thực thi vào các nút, giờ đây chúng tôi tải các nhóm lên cụm. Đây là những gì chúng tôi mong đợi ban đầu từ Kubernetes: tất cả các quy trình diễn ra bên trong các container được triển khai bằng cách sử dụng Kubernetes nguyên thủy.
  • Bạn không cần phải phát triển máy chủ RPC và máy khách RPC để triển khai các trình điều khiển phức tạp nữa. Ứng dụng khách này được các nhà phát triển Kubernetes triển khai cho chúng tôi.
  • Việc truyền các đối số để làm việc qua giao thức gRPC thuận tiện, linh hoạt và đáng tin cậy hơn nhiều so với việc truyền chúng qua các đối số dòng lệnh. Để hiểu cách thêm hỗ trợ cho số liệu sử dụng khối lượng vào CSI bằng cách thêm phương pháp gRPC được tiêu chuẩn hóa, bạn có thể đọc: yêu cầu kéo của chúng tôi cho trình điều khiển vsphere-csi.
  • Giao tiếp diễn ra thông qua các ổ cắm IPC, để không bị nhầm lẫn liệu kubelet có gửi yêu cầu đến đúng nhóm hay không.

Danh sách này có nhắc nhở bạn điều gì không? Ưu điểm của CSI là giải quyết những vấn đề tương tự, điều này không được tính đến khi phát triển plugin Flexvolume.

Những phát hiện

CSI như một tiêu chuẩn để triển khai các plugin tùy chỉnh nhằm tương tác với kho dữ liệu đã được cộng đồng đón nhận rất nồng nhiệt. Hơn nữa, do những ưu điểm và tính linh hoạt của chúng, trình điều khiển CSI thậm chí còn được tạo ra cho các hệ thống lưu trữ như Ceph hoặc AWS EBS, các plugin để làm việc đã được thêm vào trong phiên bản đầu tiên của Kubernetes.

Vào đầu năm 2019, các plugin trong cây đã được tuyên bố là lỗi thời. Chúng tôi dự định tiếp tục hỗ trợ plugin Flexvolume nhưng sẽ không phát triển chức năng mới cho nó.

Bản thân chúng tôi đã có kinh nghiệm sử dụng ceph-csi, vsphere-csi và sẵn sàng bổ sung vào danh sách này! Cho đến nay, CSI đang giải quyết các nhiệm vụ được giao một cách thành công, nhưng chúng ta sẽ chờ xem.

Đừng quên rằng mọi thứ mới đều là sự suy nghĩ lại về cái cũ!

PS

Đọc thêm trên blog của chúng tôi:

Nguồn: www.habr.com

Thêm một lời nhận xét