Kubernetes 1.10: CSI в beta - подключаем Ceph RBD без патчей ядра
Обновляемся до Kubernetes 1.10: Container Storage Interface в beta позволяет подключать Ceph RBD через стандартный плагин без патчей ядра и out-of-tree драйверов.
Релиз Kubernetes 1.10 - Container Storage Interface (CSI) переходит в beta, улучшения RBAC и стабилизация Storage API
Kubernetes 1.10 вышел на прошлой неделе, и главное для нас в этом релизе - Container Storage Interface переходит в beta. Это не просто очередная галочка в changelog: CSI меняет то как Kubernetes работает с внешними системами хранения, и для кластеров с Ceph это имеет вполне конкретное практическое значение.
Что такое CSI и зачем он нужен
До CSI все плагины хранилища жили внутри бинарника Kubernetes - код для работы с AWS EBS, GCE PD, Ceph RBD, GlusterFS, iSCSI и ещё двумя десятками систем был встроен в kubelet и kube-controller-manager. Это создавало несколько проблем.
Во-первых, цикл выпуска: если в плагине Ceph RBD нашли баг или нужна новая функция - ждёшь следующего релиза Kubernetes. Во-вторых, для некоторых драйверов требовалась специфичная сборка ядра или дополнительные модули прямо на ноде. Для Ceph RBD это rbd и librados - надо было следить чтобы они были на каждой ноде, и при обновлении ядра иногда что-то разъезжалось.
CSI это стандартный интерфейс - спецификация gRPC, по которой Kubernetes разговаривает с плагином хранилища. Плагин живёт в обычном Pod-е, обновляется независимо от Kubernetes, не требует ничего в ядре кроме минимального набора системных вызовов для маунта. Идея не новая - Docker давно двинулся в ту же сторону с volume plugins - но в Kubernetes эта механика до сих пор была в alpha и на ней никто не строил серьёзного.
В 1.10 CSI становится beta. Это значит: API не будет ломаться без предупреждения, включено по умолчанию, можно начинать использовать в чём-то реальном.
Как это меняет работу с Ceph RBD
У нас несколько кластеров Kubernetes которые работают поверх инфраструктуры под управлением - часть из них использует Ceph как основную систему хранения через PersistentVolume. До 1.10 схема выглядела так: встроенный плагин rbd в kubelet, на каждой ноде нужны пакеты ceph-common с клиентскими инструментами и загруженный модуль ядра rbd.
Это работало, но с нюансами. При обновлении ОС на нодах надо было проверять что модуль ядра есть. При замене нод в кластере - снова ставить пакеты. На дистрибутивах без ceph в стандартных репозиториях - добавлять сторонние источники. Небольшая, но стабильно присутствующая операционная нагрузка.
С CSI-плагином для Ceph картина другая. Плагин запускается как DaemonSet в кластере, всё что ему нужно на ноде - стандартные системные вызовы для block device и монтирования. Подключение к Ceph-кластеру, авторизация через keyring, создание и маппинг RBD-образа - всё это делает процесс внутри контейнера, а не код в kubelet.
Обновить версию плагина - это kubectl set image daemonset/csi-rbdplugin, а не Rolling update всего кластера. Для операционной команды это принципиальная разница.
Что мы попробовали
На тестовом кластере мы поставили Kubernetes 1.10 и развернули CSI-плагин для Ceph RBD - ceph-csi от сообщества. Это не официальный плагин от самого Ceph-проекта, но наиболее активно поддерживаемый на данный момент.
Конфигурация требует создания нескольких объектов: StorageClass с параметрами CSI-драйвера, Secret с keyring и endpoint Ceph-кластера, само развёртывание плагина из трёх компонентов - provisioner, attacher и DaemonSet с node-плагином.
apiVersion: storage.k8s.io/v1
kind: StorageClass
metadata:
name: ceph-rbd-csi
provisioner: rbd.csi.ceph.com
parameters:
monitors: 10.0.0.11:6789,10.0.0.12:6789,10.0.0.13:6789
pool: kubernetes
imageFormat: "2"
imageFeatures: layering
csiProvisionerSecretName: ceph-secret
csiProvisionerSecretNamespace: kube-system
csiNodePublishSecretName: ceph-secret
csiNodePublishSecretNamespace: kube-system
reclaimPolicy: Delete
Создание PVC, монтирование в Pod, запись и чтение - работает. Latency и throughput на синтетических тестах - не хуже чем с встроенным плагином, что логично: транспорт тот же, меняется только кто инициирует подключение.
Что не так гладко
Несколько моментов которые нужно иметь в виду.
Beta - это не production-ready в общем смысле. Спецификация CSI стабилизировалась, но конкретные плагины от вендоров - нет. У ceph-csi есть известные ограничения: не все фичи RBD поддержаны, imageFeatures надо указывать аккуратно - exclusive-lock и object-map вызывали проблемы на ядрах до 4.14.
Отладка стала сложнее. Раньше при проблемах с маунтом смотришь в логи kubelet на ноде. Теперь - в логи CSI node-плагина, attacher, provisioner. Уровней стало больше. Нужны нормальные алерты и агрегация логов - без этого разбирать что пошло не так будет дольше.
RBAC в 1.10 подтянули. В этом же релизе улучшили аудит RBAC и добавили NodeRestriction admission controller. Если вы использовали широкие node-права как workaround для чего-то - стоит пройтись по сервисным аккаунтам. У нас пара аккаунтов требовала пересмотра после обновления.
Где мы сейчас
На тестовом кластере всё выглядит работающим. На production пока не переходим - хотим дать ceph-csi поработать несколько недель под нагрузкой и посмотреть на edge cases: рестарт ноды с примонтированными томами, поведение при временной недоступности Ceph, пересоздание Pod-а с тем же PVC.
Встроенный in-tree плагин Ceph RBD никуда не делся - он продолжает работать в 1.10 так же как в 1.9. Спешить некуда. Но вектор понятен: CSI это тот путь по которому будет двигаться интеграция с хранилищами, и начинать с ним разбираться на тестовых кластерах - сейчас правильный момент.
Если у вас Kubernetes + Ceph и вы хотите поговорить про CSI-миграцию - обращайтесь.