- PVSM.RU - https://www.pvsm.ru -
Прим. перев.: о так называемых плагинах хранилищ «вне дерева» Kubernetes (Out-of-Tree CSI Volume Plugins) мы впервые рассказывали в своём обзоре релиза K8s 1.9 [1], где эта фича появилась в статусе альфа-версии. Автор нового материала — Anoop Vijayan Maniankara (ведущий DevOps-инженер финской компании Tuxera) — собрал ключевые сведения об идеях и устройстве CSI, что помогает быстро познакомиться с новой концепцией, которая, как утверждают некоторые наши сотрудники, «будет the next big thing». Для более подробного и технического изучения CSI в конце статьи приведены полезные ссылки, среди которых я особенно выделю презентацию одного из авторов этой спецификации (Jie Yu). Но начать всё равно стоит с «общей картины»…

Container Storage Interface (CSI) — инициатива, призванная унифицировать интерфейс хранилищ, таких как Ceph, Portworx, NetApp и т.п., в системах оркестровки контейнеров: Kubernetes, Mesos, Docker Swarm, Cloud Foundry и других. Идея в том, чтобы реализация одного CSI производителем хранилища гарантированно работала со всеми этими системами.

Источник изображения: доклад про CSI от Jie Yu на CloudNativeCon EU 2018 [2]
Обратите внимание: в этой статье будет рассказано только о динамическом provisioning'е. Предварительно настроенные тома и flex-тома выходят за её рамки. Если хотите лучше разобраться, о чём пойдёт речь, стоит предварительно прочитать документацию Kubernetes [3]. Кроме того, в статье не будет глубокого погружения в детали реализации CSI. Я представлю высокоуровневый обзор CSI и заложу основу для создания CSI-тома. И последнее: для примеров и ссылок на подробности используется информация для Kubernetes.
До того, как погрузиться в тему, важно также знать, что такое sidecar-контейнеры в Kubernetes. Они расширяют возможности основного контейнера (main), существуя в том же поде, разделяя хранилище и сеть.
На момент написания статьи (13 августа 2018 г.) компоненты CSI имели следующие версии:

Первый релиз CSI — v0.1 — состоялся в декабре 2017 года. Конечно, сделать provisioning для внешнего хранилища в системах оркестровки можно было и до его появления. В случае Kubernetes за потребности в хранилищах отвечали плагины томов — volume plugins:

Как видно из картинки выше, такие плагины являются частью ядра системы оркестровки. Из-за этого возникали следующие проблемы, упомянутые в документе с архитектурой CSI [4]:
Представляя CSI, команда Kubernetes выпустила внешние компоненты, не являющиеся частью ядра и предназначенные для взаимодействия с другими внешними компонентами, реализуемыми производителями. Между собой они общаются через сокеты домена (UNIX domain sockets — прим. перев.) с помощью gRPC [5].

Они полностью реализуются и поддерживаются командой Kubernetes и расширяют действия Kubernetes вне Kubernetes. Производителям можно совсем не волноваться об особенностях их реализации. Состоят из трёх частей:
NodeId драйвера в лейбл объекта узла в Kubernetes API. Для этого взаимодействует с сервисом CSI-драйвера Identity (подробнее о нём см. ниже — прим. перев.) и вызывает GetNodeId у CSI;CreateVolume и DeleteVolume для endpoint'а драйвера;ControllerPublish и ControllerUnpublish для endpoint'а драйвера.Специфичная для вендора реализация. Каждый производитель реализует необходимые API в рамках функций gRPC-сервиса. Например, реализация GCE PD [6] или Ceph [7] и т.п. Они тоже состоят из трёх компонентов:
service Identity {
// вернуть версию и название плагина
rpc GetPluginInfo(GetPluginInfoRequest)
returns (GetPluginInfoResponse) {}
// сообщить, в состоянии ли плагин обслуживать интерфейс Controller
rpc GetPluginCapabilities(GetPluginCapabilitiesRequest)
returns (GetPluginCapabilitiesResponse) {}
// вызывается системой оркестровки, чтобы проверить, запущен ли плагин
rpc Probe (ProbeRequest)
returns (ProbeResponse) {}
}
service Controller {
// выполнить provisioning тома
rpc CreateVolume (CreateVolumeRequest)
returns (CreateVolumeResponse) {}
// удалить выделенный ранее том
rpc DeleteVolume (DeleteVolumeRequest)
returns (DeleteVolumeResponse) {}
// сделать том доступным на требуемом узле
rpc ControllerPublishVolume (ControllerPublishVolumeRequest)
returns (ControllerPublishVolumeResponse) {}
// сделать том недоступным на требуемом узле
rpc ControllerUnpublishVolume (ControllerUnpublishVolumeRequest)
returns (ControllerUnpublishVolumeResponse) {}
// например, может использоваться для одновременного чтения/записи с нескольких узлов
rpc ValidateVolumeCapabilities (ValidateVolumeCapabilitiesRequest)
returns (ValidateVolumeCapabilitiesResponse) {}
// вернуть все доступные тома
rpc ListVolumes (ListVolumesRequest)
returns (ListVolumesResponse) {}
// полная емкость доступного пространства в пуле
rpc GetCapacity (GetCapacityRequest)
returns (GetCapacityResponse) {}
// например, плагины могут не иметь реализации GetCapacity и Snapshotting
rpc ControllerGetCapabilities (ControllerGetCapabilitiesRequest)
returns (ControllerGetCapabilitiesResponse) {}
// сделать снапшот
rpc CreateSnapshot (CreateSnapshotRequest)
returns (CreateSnapshotResponse) {}
// удалить снапшот
rpc DeleteSnapshot (DeleteSnapshotRequest)
returns (DeleteSnapshotResponse) {}
// вывести список снапшотов
rpc ListSnapshots (ListSnapshotsRequest)
returns (ListSnapshotsResponse) {}
}
service Node {
// временно примонтировать том к staging-пути
rpc NodeStageVolume (NodeStageVolumeRequest)
returns (NodeStageVolumeResponse) {}
// отмонтировать том от staging-пути
rpc NodeUnstageVolume (NodeUnstageVolumeRequest)
returns (NodeUnstageVolumeResponse) {}
// примонтировать том из staging к целевому пути
rpc NodePublishVolume (NodePublishVolumeRequest)
returns (NodePublishVolumeResponse) {}
// отмонтировать том от целевого пути
rpc NodeUnpublishVolume (NodeUnpublishVolumeRequest)
returns (NodeUnpublishVolumeResponse) {}
// статистика по тому
rpc NodeGetVolumeStats (NodeGetVolumeStatsRequest)
returns (NodeGetVolumeStatsResponse) {}
// вернуть уникальный ID узла
rpc NodeGetId (NodeGetIdRequest)
returns (NodeGetIdResponse) {
option deprecated = true;
}
// вернуть возможности (capabilities) узла
rpc NodeGetCapabilities (NodeGetCapabilitiesRequest)
returns (NodeGetCapabilitiesResponse) {}
// схоже с NodeGetId
rpc NodeGetInfo (NodeGetInfoRequest)
returns (NodeGetInfoResponse) {}
}
(kubernetes-csi-node.proto [10])
Появление CSI принесло очевидный плюс системам оркестровки и производителям хранилищ. К тому же, хорошо определённые интерфейсы помогают простой реализации и тестированию CSI как разработчикам, так и будущим системам оркестровки. Если вы решите начать реализацию своего CSI после прочтения этого материала, хорошей стартовой точкой станет статья «How to write a Container Storage Interface (CSI) plugin [11]» от Fatih Arslan.
Читайте также в нашем блоге:
Автор: Дмитрий Шурупов
Источник [23]
Сайт-источник PVSM.RU: https://www.pvsm.ru
Путь до страницы источника: https://www.pvsm.ru/sistemnoe-administrirovanie/293822
Ссылки в тексте:
[1] обзоре релиза K8s 1.9: https://habr.com/company/flant/blog/344220/
[2] доклад про CSI от Jie Yu на CloudNativeCon EU 2018: https://schd.ws/hosted_files/kccnceu18/fb/CloudNativeCon%20EU%202018%20CSI%20Jie%20Yu.pdf
[3] документацию Kubernetes: https://kubernetes.io/docs/concepts/storage/dynamic-provisioning/
[4] документе с архитектурой CSI: https://github.com/kubernetes/community/blob/master/contributors/design-proposals/storage/container-storage-interface.md
[5] gRPC: https://grpc.io/
[6] GCE PD: https://github.com/kubernetes-sigs/gcp-compute-persistent-disk-csi-driver
[7] Ceph: https://github.com/ceph/ceph-csi
[8] kubernetes-csi-identity.proto: https://gist.github.com/maniankara/3759539f8c134840943938e3f42b892f#file-kubernetes-csi-identity-proto
[9] kubernetes-csi-controller.proto: https://gist.github.com/maniankara/bca26abc23afa406d589e7f6e2887e5e#file-kubernetes-csi-controller-proto
[10] kubernetes-csi-node.proto: https://gist.github.com/maniankara/5f72eb94b8da3ae4161726edc037107f#file-kubernetes-csi-node-proto
[11] How to write a Container Storage Interface (CSI) plugin: https://arslan.io/2018/06/21/how-to-write-a-container-storage-interface-csi-plugin/
[12] Спецификация CSI: https://github.com/container-storage-interface/spec/blob/master/spec.md
[13] Sidecar-контейнеры в Kubernetes: https://kubernetes.io/blog/2015/06/the-distributed-system-toolkit-patterns/
[14] вот здесь: https://www.youtube.com/watch?v=ktwY1anKN58
[15] Актуальная документация по CSI от Kubernetes: https://kubernetes-csi.github.io/docs/
[16] Устаревшая документация по CSI от Kubernetes: https://github.com/kubernetes-csi/docs/wiki/Usage
[17] Понимаем RBAC в Kubernetes: https://habr.com/company/flant/blog/422801/
[18] Что происходит в Kubernetes при запуске kubectl run? Часть 1: https://habr.com/company/flant/blog/417905/
[19] Как на самом деле работает планировщик Kubernetes?: https://habr.com/company/flant/blog/335552/
[20] За кулисами сети в Kubernetes: https://habr.com/company/flant/blog/420813/
[21] Rook — „самообслуживаемое“ хранилище данных для Kubernetes: https://habr.com/company/flant/blog/348044/
[22] Наш опыт с Kubernetes в небольших проектах: https://habr.com/company/flant/blog/331188/
[23] Источник: https://habr.com/post/424211/?utm_source=habrahabr&utm_medium=rss&utm_campaign=424211
Нажмите здесь для печати.