RedOS 7.3 + Deckhouse в продакшне объекта КИИ: что сломалось и как починили
Прошли полный цикл от выбора связки RedOS 7.3 + Deckhouse до первого боевого деплоя на КИИ. Документируем containerd, cgroup v2 и всё, что пошло не по плану.
RedOS 7.3 и Deckhouse Kubernetes Platform образуют жизнеспособную связку для контейнерных платформ на объектах КИИ с требованиями реестра Минцифры
В январе мы разворачивали Deckhouse CE на тестовом стенде и пришли к выводу, что платформа готова к боевому использованию. Теперь у нас есть первый настоящий прод: объект КИИ второй категории, требование реестра Минцифры по ОС, контейнерная нагрузка. Выбор ОС сузился до RedOS - она в реестре, RPM-экосистема, живой вендор. Связка RedOS 7.3 + Deckhouse выглядела логично. То, что произошло дальше, записали честно.
Почему именно эта связка
У заказчика два ограничения, которые сужают пространство выбора до неприличия. Первое - ОС должна быть в реестре российского ПО (требование регулятора). Второе - нужна контейнерная платформа с управляемым стеком: мониторинг, ingress, авторизация. Голый kubeadm не подходит, платить за что-то экзотическое - тоже нет.
RedOS 7.3 - RPM-дистрибутив с собственной кодовой базой - в реестре, поддерживается отечественным вендором РЕД СОФТ, пакетная база достаточно свежая. Astra Linux SE мы уже ставили на рабочие станции этого же заказчика, но для серверной части с Kubernetes она избыточна: мандатный PARSEC создаёт трения с контейнерным рантаймом, которые нам не нужны. RedOS на этом фоне выглядела практичнее.
Deckhouse - выбор по тем же мотивам, что и в январе: батарейки в комплекте, русскоязычная поддержка, сертификация ФСТЭК у Enterprise-редакции на горизонте. На этом объекте пошли с Enterprise именно из-за сертификационных перспектив.
Где споткнулись: containerd и cgroup v2
RedOS 7.3 использует ядро 6.x и по умолчанию включает cgroup v2 (unified hierarchy). Это современный стандарт, но Deckhouse на момент нашей установки ожидал определённой конфигурации containerd, которая с cgroup v2 на RedOS повела себя неожиданно.
Конкретика: после установки Deckhouse ноды уходили в NotReady с ошибкой в kubelet примерно такого вида:
failed to get cgroup stats for "/system.slice/containerd.service":
failed to get cgroup v2 stats: ...
Первая реакция была предсказуемой - попробовать откатиться на cgroup v1. На RedOS это делается через параметр ядра в grub:
systemd.unified_cgroup_hierarchy=0
Помогло частично: kubelet запустился, ноды перешли в Ready, но containerd начал вести себя странно при сборке образов - часть слоёв кешировалась некорректно, crictl ps иногда показывал контейнеры в статусе Unknown. Явно не то, что мы хотим в проде.
Правильное решение оказалось в другом: проблема была в версии containerd из RPM-репозитория RedOS. Там шла 1.6.x, а нужная конфигурация для корректной работы с cgroup v2 требовала явного выставления SystemdCgroup = true в /etc/containerd/config.toml. Deckhouse при установке генерировал этот конфиг, но шаблон не включал этот параметр для RedOS - он включался по умолчанию только для некоторых дистрибутивов.
Фикс в три шага:
- Явно прописать в конфиге containerd
SystemdCgroup = trueв секции[plugins."io.containerd.grpc.v1.cri".containerd.runtimes.runc.options] - Откатить параметр ядра обратно на cgroup v2 (убрать
systemd.unified_cgroup_hierarchy=0) - Перезапустить containerd и kubelet на всех нодах в правильном порядке: сначала containerd, потом kubelet
После этого кластер поднялся стабильно, crictl ps стал вести себя предсказуемо, метрики из kubelet пошли в Prometheus корректно.
Что ещё потребовало внимания
SELinux в enforcing-режиме. RedOS поставляется с SELinux в enforcing, что правильно для КИИ, но containerd и некоторые компоненты Deckhouse первое время генерировали AVC-отказы. Часть закрылась политикой из коробки после restorecon -Rv /var/lib/containerd, часть потребовала написать локальные модули через audit2allow. Это ожидаемо для любого RPM-дистрибутива с SELinux - просто надо закладывать время.
Репозиторий образов в закрытом контуре. Мы это предвидели ещё в январе: Deckhouse тянет образы из registry.deckhouse.io, и для закрытого КИИ нужно зеркало. Подняли Nexus в том же периметре, прописали в конфиге Deckhouse кастомный registryDockerCfg. Процедура описана в документации Deckhouse, но с нюансами: токены для аутентификации надо передавать в base64, и если ошибиться в формате - установщик падает с неочевидным сообщением.
Мониторинговый стек и SELinux. node-exporter, запущенный как DaemonSet, собирает метрики с хоста и ему нужен доступ к /sys, /proc, ряду cgroup-путей. На чистом RedOS с enforcing без предварительной подготовки часть метрик не собирается - видно только по пустым графикам в Grafana, а не по явным ошибкам. Потратили пару часов на диагностику, пока не сравнили наборы метрик с тестовым стендом.
Первый боевой деплой
После двух недель подготовки кластер принял первую нагрузку. Три микросервиса заказчика, Ingress через nginx-ingress-controller Deckhouse, TLS-терминация на ingress с сертификатом от внутреннего CA. Работает.
Что понравилось по итогу: модульная система Deckhouse реально упрощает жизнь. Включить модуль prometheus-pushgateway, выключить cert-manager (внутренний CA, не нужен Let's Encrypt) - это kubectl apply одного манифеста, а не лезть в helm values по трём разным chart-ам.
Что пока вызывает осторожность: обновление самого Deckhouse на живом кластере мы ещё не проходили в этой конфигурации. На тестовом стенде в январе проверяли, здесь специфика RedOS может добавить сюрпризов. Обновление запланировано на следующий квартал - напишем отдельно.
Итог
Связка работает. Не без шероховатостей, но ничего из того, с чем столкнулись, не было принципиально нерешаемым - это инженерные задачи с известными решениями, просто их надо было найти и применить. Главная ловушка - cgroup v2 и containerd конфиг - достаточно типичная для RedOS 7.x и других дистрибутивов на ядре 6+, так что если идёте тем же путём, начните с SystemdCgroup = true, сэкономите время.
Для объектов КИИ, где реестр Минцифры обязателен, а нужна нормальная контейнерная платформа, а не набор YAML - эта связка на сегодня выглядит как один из немногих практических вариантов. В рамках managed-сопровождения мы её теперь знаем изнутри.