Kubernetes 1.31 beta: проверяем CSI-совместимость в Deckhouse на отечественных серверах
Kubernetes 1.31 beta окончательно убрал in-tree volume-драйверы. Смотрим, что это значит для Deckhouse-кластеров на отечественном железе и как проверить CSI до обновления.
Kubernetes 1.31 beta - нативный AppArmor и финальное удаление in-tree volume plugin-ов, завершающее миграцию на CSI
Kubernetes 1.31 вышел в beta, и среди прочего там два события, которые нас задели напрямую. Первое - AppArmor наконец стал first-class гражданином API: поле appArmorProfile в podSpec вместо аннотаций. Второе - и это важнее - финальное удаление in-tree volume plugin-ов завершено. Не «deprecated», не «планируется», а именно удалено. Для кластеров на managed Kubernetes с отечественным железом это конкретный повод проверить стек хранилища до того, как обновление прилетит само.
Что именно ушло
In-tree volume plugin-ы - это встроенные в ядро Kubernetes драйверы для работы с различными системами хранения. AWS EBS, Azure Disk, GCE PD, Cinder, vSphere - всё это когда-то жило прямо в коде Kubernetes. CSI (Container Storage Interface) появился как абстракция, позволяющая вынести эти драйверы в отдельные плагины, независимые от цикла релизов Kubernetes. Миграция шла несколько лет, в 1.31 она завершена.
На практике это означает: если у вас в кластере PersistentVolume с типом, который раньше обслуживал in-tree драйвер, а внешнего CSI-плагина нет или он не настроен правильно - вы получите проблему с монтированием томов после обновления.
Для кластеров на публичных облаках это обычно не вопрос - провайдеры давно переехали на CSI. Интереснее ситуация у тех, кто разворачивает кластеры на собственном железе с кастомными решениями хранения.
Как это выглядит в Deckhouse на отечественных серверах
Мы работаем с несколькими кластерами на Deckhouse, развёрнутыми на серверах российского производства - часть из стека по итогам пересмотра серверной дорожной карты после санкционных новостей июля. Типичная конфигурация хранилища в таких кластерах: Ceph через rook-ceph с CSI-драйвером, локальные диски через local-path-provisioner, иногда NFS через nfs-subdir-external-provisioner.
На первый взгляд всё выглядит нормально - ни один из этих вариантов не зависит от in-tree плагинов, которые убрали в 1.31. Но дьявол в деталях: мы обнаружили несколько PV, созданных ещё на старых версиях кластера, где в поле spec.storageClassName стояло что-то вроде kubernetes.io/rbd или kubernetes.io/glusterfs - наследие от инсталляций, которые мигрировали через несколько мажорных версий. Эти тома монтировались, потому что in-tree плагин был жив. После 1.31 - не будут.
Что мы проверяем перед обновлением
Минимальный чеклист для кластера, который готовится получить 1.31:
-
Инвентаризация PV по типам.
kubectl get pv -o json | jq '.items[].spec | {name: .storageClassName, source: keys}'- смотрим на всё, где source содержит что-то отличное отcsi. ЛюбойawsElasticBlockStore,azureDisk,gcePersistentDisk,cinder,rbd,glusterfs,flocker,quobyte,storageos,portworxVolume,scaleIO- это потенциальные проблемные зоны. -
Проверка StorageClass-ов.
kubectl get sc -o yaml- смотрим наprovisioner. Если там что-то безcsiв названии и неkubernetes.io/no-provisioner(это local) - разбираемся откуда оно взялось. -
CSI-драйверы в кластере.
kubectl get csidrivers- всё ли необходимое установлено и находится ли в состоянииReady. -
Rook-ceph специфично. Проверяем версию rook-ceph и совместимость с версией Kubernetes. Rook 1.14+ поддерживает Kubernetes до 1.30; поддержка 1.31 появится в следующем релизе rook-ceph, но старые версии имеют ограничения уже сейчас.
У нас нашлось несколько rbd-томов в статусе Released с retain-политикой - живые данные там уже не хранились, но PV существовали. Почистили руками. Ещё один кластер показал NFS-тома через старый плагин kubernetes.io/nfs - заменили на nfs-subdir-external-provisioner с нормальным CSI.
AppArmor: приятная мелочь
Нативный AppArmor в 1.31 - это скорее радость для тех, кто строит безопасность кластера правильно. До 1.31 AppArmor-профили задавались через аннотации вида container.apparmor.security.beta.kubernetes.io/<container_name>: profile. Работало, но выглядело как временный костыль.
В 1.31 появился securityContext.appArmorProfile с двумя вариантами: RuntimeDefault (использовать дефолтный профиль рантайма) и Localhost (профиль с указанием имени, загруженный на ноде). На Astra Linux, которая у ряда наших клиентов из КИИ стоит на хостах, AppArmor присутствует и этот механизм имеет смысл использовать. Аннотации в 1.31 ещё работают для обратной совместимости, но закладываться на них не стоит.
Итог
Основная работа перед обновлением кластера на 1.31 - это аудит хранилища, а не AppArmor. Три часа с kubectl и jq дали нам полную картину по всем кластерам: где CSI-стек чистый, где есть исторический мусор, где нужна миграция. Лучше потратить это время сейчас, чем разбираться с unmountable-томами после автообновления.
Deckhouse в своём цикле релизов обычно идёт за апстримом с небольшим лагом - 1.31 GA ожидается в августе, Deckhouse подтянется примерно к осени. Времени на подготовку достаточно, но начинать инвентаризацию стоит уже сейчас, особенно в кластерах с историей в несколько мажорных версий.