Уявіть гіперноду хмари. Гіпернода — це фізичний сервер із запущеним гіпервізором, на якому працюють віртуальні машини клієнтів. Під дисками цих машин лежить програмно визначуване сховище (SDS) Ceph: розподілена система, де дані розподілені по багатьох серверах із копіями, без окремого дискового масиву. Змінюємо на ноді одну змінну — операційну систему. Віртуальні машини не перезбираємо, кластер зберігання не чіпаємо, диски та мережа ті самі. Жодного нового заліза, жодного рядка нового коду в застосунку. Після перемикання дискова підсистема ВМ поводиться відчутно інакше.
Під які вимоги заміна ОС критична, окрім ІТ
Частина обов’язкових заходів ІБ закривається на рівні ОС: захист від несанкціонованого доступу, розмежування прав, реєстрація подій. Для додаткових вимог є сертифікована редакція РЕД ОС, яка дає їх вбудованими, а сертифікований хмарний контур додає атестацію всієї інфраструктури в купі.
Короткі вступні та загадка продуктивності стека
Повернемося до гіперноди хмари. Поміняли одну змінну — ОС на гіперноді, а дискова підсистема віртуальних машин видає помітно більше операцій вводу-виводу на змішаному навантаженні. Застосунок і сховище не чіпали. Звідки взялася дельта?
Перша реакція інженера правильна: це підозріло. Відповідь лежить не в застосунку і не в залізі, а в шарі між ними — у системних пакетах і бібліотеках, які оновлюються разом з операційною системою.

Але спершу про головну пастку, у яку потрапляють при апгрейді легасі.
Ядро — це не вся ОС
Типова спроба оживити старий CentOS виглядає так: ядро застаріло, накочуємо свіже ядро окремим репозиторієм, решту не чіпаємо. Після цього система формально на новому ядрі та здається сучасною. На оновленій ноді це перевіряється однією командою:
uname -rЯдро справді нове. А тепер дивимось, що під ним:
rpm -q qemu-kvm libvirtВиявляється, що емулятор і керівний демон залишилися від старого дистрибутива. Ядро вміє сучасні механізми вводу-виводу, емулятор про них не знає і не викликає. Свіжий мотор прикрутили, коробка передач залишилася від попередньої моделі. Половину можливостей ядра гіпервізор просто не використовує.
Конкретний приклад — двигун io_uring. Це інтерфейс ядра Linux для асинхронного вводу-виводу, який Jens Axboe додав у 2019 році (ядро 5.1) як швидку заміну старому механізму AIO. Викликати його емулятор QEMU навчився з версії 5.0. Потрібні обидві половини одночасно. Якщо ядро 5.10, а емулятор залишився старим, диск ВМ ходить через старі механізми — потокову модель або legacy native — і io_uring не залучається в принципі. Підміна одного ядра цей розрив не лікує.
РЕД ОС 7.3 під кодовою назвою МУРОМ зібрана на пакетній базі RPM-формату та архітектурно близька сімейству RHEL, тож переїзд з CentOS не ламає звичок. Ядро Linux 5.10 на старті, в актуальних релізах РЕД ОС 7.3 за замовчуванням іде LTS-ядро 6.1. LTS (long-term support) — ядро з довгим терміном підтримки та оновлень безпеки. Головне: разом із ядром оновлюється і користувацьке середовище. Дистрибутив — це узгоджений набір пакетів і ядра, зібраний і протестований разом. Коли переходиш на РЕД ОС, змінюєш весь набір разом, а не одну деталь. Звідси й ефект.
ABI та динамічне лінкування
Чому прискорився код, який ніхто не переписував? Це найбільш контринтуїтивне місце, і його варто проговорити — саме без нього приріст виглядає якоюсь магією.
Почнемо з того, як програма бере чужий код. Емулятору потрібні типові операції: робота з пам’яттю, мережею, шифруванням, звернення до сховища. Він не носить цей код у собі, а бере з системних бібліотек. Дві з них зараз важливі: glibc відповідає за пам’ять, потоки та блокування, librbd — за роботу зі сховищем Ceph.
Зв’язати програму з бібліотекою можна двома способами:
При статичному лінкуванні код бібліотеки вшивається в програму при збірці, і оновити його можна лише перезбіркою. Так майже нічого в системі не працює.
При динамічному лінкуванні програма зберігає лише посилання, а сам код підтягує із системи в момент запуску — файли виду
libc.soтаlibrbd.so. Так лінкується майже весь системний стек, включно з емулятором.
Висновок прямий: емулятор не носить бібліотеки всередині, він бере їх із системи. Оновили систему — емулятор узяв нові бібліотеки, сам ні на байт не змінившись.
Ось і відповідь на загадку. Між версіями бібліотек переписують нутрощі: прибирають зайві блокування, додають векторні інструкції процесора, змінюють алгоритми кешування. Ззовні виклик залишається тим самим, усередині код став швидшим. Це і є сумісність за ABI (Application Binary Interface): старий виклик працює з новою, швидшою реалізацією. Застосунок у ВМ не змінювався, виклики ті самі, але під ними тепер новий код glibc і librbd. Прискорення прийшло без жодного рядка правок у самому застосунку. Підміною лише ядра цього не отримати: бібліотеки живуть у користувацькому середовищі, а не в ядрі.
Що приїхало з дистрибутивом
Пройдімося по кожному шару окремо: що це за модуль, де була проблема на старому стеку та що змінилося. Версії наведу як поріг технології, перевіряти склад потрібно на своїй системі.
Шар 1. io_uring в емуляторі
Що це. Емулятор (QEMU) — програма на гіперноді, яка зображає для віртуальної машини справжній комп’ютер, включно з диском. Кожне звернення ВМ до диска він перетворює на запит до ядра хоста. io_uring — це спосіб, яким емулятор віддає ці операції ядру Linux. Від нього залежить, скільки запитів ВМ встигає обробити і з якою затримкою.
Де була проблема. Емулятор попереднього покоління вмів лише синхронні двигуни: на кожну операцію з диском — окремий потік і блокування на системному виклику. Тисячі операцій на секунду, і перемикання між користувацьким простором та режимом ядра самі починають з’їдати час. Гальмував не диск — гальмували нескінченні звернення до ядра.

Що зробили. io_uring заводить між програмою та ядром два спільні списки просто в пам’яті: чергу заявок і чергу готових відповідей. Заявки складаються пачкою, відповіді забираються пачкою, перемикань контексту стає в рази менше. На рівні libvirt двигун вмикається в описі диска ВМ:
xml
<iothreads>4</iothreads>
...
<disk type='network' device='disk'>
<driver name='qemu' type='raw' cache='none' io='io_uring' iothread='1' queues='4'/>
<source protocol='rbd' name='pool/vm-disk'/>
</disk>Перевірка на ноді. rpm -q qemu-kvm та uname -r. Якщо емулятор 5.0 і новіше, а ядро 5.1 і новіше — io_uring доступний. За публічною доповіддю щодо io_uring в KVM, це дає приблизно дворазове зростання кількості операцій і вдвічі меншу затримку відносно старого шляху, з виходом на 80–90% продуктивності bare metal.

Чому так швидше. Знімаються блокування на системних викликах і падає затримка на змішаному вводі-виводі, особливо на RBD-дисках Ceph. Механізм вимагає одночасно сучасного ядра й актуального емулятора — на застарілому середовищі його просто немає.
Шар 2. IOThreads та multi-queue
Що це. Модель потоків, що обслуговують диски віртуальної машини. Вона визначає, чи йде ввід-вивід паралельно, чи через одне вузьке горлечко. Virtio-blk — віртуальний дисковий контролер, який ВМ бачить замість фізичного. У нього є черги запитів, і важливо, скільки їх.
Де була проблема. У керівному шарі попереднього покоління всі диски ВМ обслуговував один потік емулятора, а черги virtio-blk не паралелилися. Усі ядра віртуалки штовхалися за один внутрішній замок: додаєш ВМ ядер, а швидшою вона не стає, вільні ядра сервера простоюють.

Що зробили. Сучасний керівний шар із коробки призначає окремий IOThread на кожен диск, а virtio-blk multi-queue розкидає черги за кількістю віртуальних процесорів. Вмикається парою <iothreads> на домені та параметрами queues і iothread в описі диска (фрагмент вище).

Чому швидше. Ввід-вивід різних дисків і черг іде одночасно та масштабується по ядрах. На багатоядерних ВМ це прибирає вузьке горлечко, яке не лікується ні швидким диском, ні io_uring наодинці.
Шар 3. Клієнт Ceph
Що це. Клієнт Ceph (librbd) — бібліотека, через яку віртуальна машина звертається до блочних пристроїв сховища. RBD (RADOS Block Device) — віртуальний диск поверх розподіленого сховища, фізично розподілений по багатьох OSD (object storage daemon, по одному на фізичний диск) на різних серверах, із копіями. Покоління клієнта безпосередньо впливає на кількість операцій на секунду.
Де була проблема. Кожна операція з диском іде по мережі одразу на кілька вузлів сховища. Застарілий клієнт спілкувався по мережі менш економно та примітивніше кешував.

Що зробили. Актуальний клієнт використовує протокол messenger v2 (перероблений мережевий протокол, з'явився у Ceph Nautilus, вміє шифрувати канал), перероблений writeback-кеш та незмінний кеш об'єктів на стороні клієнта. Шифрування та контрольні суми рахують вбудовані блоки процесора. Сервери сховища не чіпали. Перевірити, що кластер спілкується по v2:
text
ceph mon dumpУ моніторів у виводі мають бути адреси з позначкою v2:

Чому так швидше. На тому ж кластері новіший клієнт знімає більше операцій за секунду на змішаному навантаженні без змін у залізі та без переналаштування кластера. Публічні вимірювання команди Ceph це підтверджують: у конфігурації з 30 OSD librbd видавав понад 122 тисячі операцій за секунду, а стара збірка з CentOS Stream 8 відставала від нової, переробленої на boost::asio. На великому NVMe-кластері реліз Reef показав близько 4,4 мільйона операцій випадкового читання за секунду при затримці меншій за пів мілісекунди.
Шар 4. Системні бібліотеки
Що це. Базові бібліотеки (glibc та суміжні): блокування, робота з пам'яттю, елементарні операції. Через них проходить майже будь-який код на ноді, включаючи гарячий шлях клієнта Ceph — серіалізацію, підрахунок контрольних сум, шифрування.
Де була проблема та що зробили. Бібліотеки попереднього покоління несли старі реалізації блокувань та атомарних операцій, а копіювання пам'яті йшло без сучасних векторних інструкцій процесора. Векторні інструкції — це команди класу SIMD (single instruction, multiple data), що обробляють одразу кілька чисел за одну операцію. Лінія розширень x86 тягнеться з 1997 року (MMX), через SSE (1999) до AVX (Intel, 2011), AVX2 (2013) та AVX-512 для серверних Xeon (2017). Актуальні бібліотеки переробили atomics та використовують AVX2 і AVX-512 в операціях з пам'яттю. Ззовні виклик той самий, усередині код швидший.
Версію бібліотеки видно так:
text
ldd --version | head -1Чому швидше. Прискорення фундаменту саме по собі дає відсотки, але через бібліотеку проходить кожен запит Ceph-клієнта — ці відсотки набігають на всьому навантаженні та складаються з іншими шарами.
Шар 5. Профіль та cgroups
Що це. Системні налаштування, що визначають поведінку планувальника, роботу з пам'яттю та розподіл ресурсів між процесами на гіперноді. cgroups — механізм ядра, який ділить процесорний час і введення-виведення між віртуальними машинами на одній ноді.
Де була проблема та що зробили. Попереднє покоління жило на cgroups першої моделі та універсальному профілі продуктивності, не заточеному під гіперноду з Ceph. ОС підтягує cgroups v2 і через систему tuned (демон, що застосовує готові набори налаштувань ядра під тип навантаження) вмикає профіль гіпервізора з іншими налаштуваннями планувальника, параметрами запису брудних сторінок та вартістю міграції задач між ядрами. Перевірка:
text
tuned-adm active
stat -fc %T /sys/fs/cgroupПерша команда покаже активний профіль, друга видасть cgroup2fs при другому поколінні cgroups.
Чому швидше. Під змішане навантаження з Ceph коректний профіль гіпервізора додає відсотки до затримки та пропускної здатності, cgroups v2 рівніше ділить введення-виведення між ВМ при NUMA. Окремо ефект невеликий, у сумі з іншими шарами — помітний. Сюди ж лягає мережевий стек нового ядра: сучасні алгоритми керування перевантаженням та драйвери знімають стелю на швидкостях 25 і 100 гігабіт, критичну для трафіку сховища.
Стек цілком
Зведу шари в одну таблицю. Зліва попереднє покоління, справа актуальна гілка ОС. Порівнюю поведінку та технологію, а не номери версій пакетів.
Компонент | Попереднє покоління | Актуальний стек ОС |
|---|---|---|
Ядро | застаріле | сучасне LTS |
Емулятор і рушій диска | синхронні механізми, io_uring недоступний | io_uring |
Потоки введення-виведення | один на емулятор | окремий на кожен диск, multi-queue |
Клієнт Ceph | попередній протокол обміну | messenger v2, новий кеш |
Системні бібліотеки | базова реалізація | векторні інструкції |
Профіль і cgroups | дефолти, cgroups v1 | профіль гіпервізора, cgroups v2 |
Кожен рядок — функція актуального стека цілком. Розробник узгоджує версії шарів між собою, тестує їхню зв'язку та супроводжує як один продукт, сертифікований регулятором.
Звідки приріст
Звідки взагалі береться приріст, якщо застосунок і кластер не чіпали? Причин дві:
Вимірювання на змішаному навантаженні, де дрібні операції читання та запису йдуть упереміш: саме на ньому свіжий стек відривається найсильніше, бо вузьке місце там не диск, а шлях запиту через емулятор і клієнт сховища.
Особливість тестової ноди: усі шари оновилися разом, і ефекти склалися. На іншому профілі навантаження або при частковому оновленні розрив буде іншим.
Перевірити у себе нескладно. Зніміть базову лінію на старому стеку, оновіть ноду цілком, повторіть вимірювання. Мінімальний сценарій змішаного навантаження в fio:
bash
fio --name=mixed --ioengine=libaio --rw=randrw --rwmixread=70 \
--bs=4k --iodepth=32 --numjobs=4 --runtime=120 --time_basedНа виході — кількість операцій за секунду та затримка за перцентилями. Два прогони на тій самій ноді, до оновлення та після, дадуть чесну відповідь без перенесення чужих цифр на ваш кластер.
Приріст тримається на переході на сучасний гіпервізорний стек цілком: ядро плюс емулятор плюс клієнт сховища плюс бібліотеки. Це відтворювана інженерія: на будь-якому сучасному дистрибутиві на тій самій конфігурації ви отримаєте порівнянний результат. Вітчизняна ОС додає до цього інше — той самий стек зібрано та сертифіковано для контурів, де зарубіжний дистрибутив не проходить за вимогами, плюс російськомовна техпідтримка та спільнота, яких у зарубіжної збірки в РФ, по суті, немає. Ось тут історія про легасі й набуває сенсу: оновлюючись, ви отримуєте і приріст, і сертифіковану базу разом.
Чим розплачується легасі
Окрім втрачених відсотків продуктивності, застарілий стек коштує ще кількох речей.

Безпека. CentOS Linux 7 пішов у EOL 30 червня 2024 року. Оновлень безпеки для базового сімейства більше немає. Кожна нова вразливість у ядрі, бібліотеках чи системних компонентах залишається незакритою, і лік таких дір тільки зростає. Для контуру під регуляторикою це пряме порушення вимог до захисту інформації.
Стеля продуктивності. Старий userspace фізично не вміє викликати половину можливостей сучасного заліза та ядра, і цю стелю не зрушити тюнінгом. Поки емулятор, клієнт сховища та бібліотеки старі, io_uring, паралельні черги та новий кеш Ceph недоступні.
Ремонт частинами не працює. Спантеличення зрозуміле: оновити лише ядро чи один пакет і жити далі. Але гіпервізор працює через увесь userspace, і точкова заміна дає рівно ту пастку з початку статті — свіжий мотор на старій коробці. Щоб отримати ефект, потрібен узгоджений стек цілком.
Регуляторика. Легасі-дистрибутив, що випав із підтримки, у реєстрі російського ПЗ не з'явиться, а зарубіжний дистрибутив туди й не входив. Для держзамовлення та значущих об'єктів це зачинені двері.
Два рівні в хмарі
У хмарі операційна система живе на двох рівнях.
Рівень каталогу — образ, який замовник бере під свою ВМ. У каталозі хмари лежать сертифіковані збірки для імпортозаміщення поруч з Astra Linux та Альт. Розгорнути серверну ВМ або робоче місце на ОС можна з особистого кабінету за кілька кроків: обрати образ, задати сайзинг, підключити мережу та правила доступу, налаштувати ключі входу, увімкнути снапшоти для відкату.
Рівень платформи — ОС під самим гіпервізором. Хмара працює на стеку ОС 7.3 і вище, і саме сюди лягає весь розбір із першої частини статті: io_uring, IOThreads, новий клієнт сховища. Замовник цей приріст не налаштовує — він його отримує за фактом того, що платформа зібрана на сучасному стеку.
Поверх цього будується сертифікований контур: хмарна платформа в сертифікованій редакції, об'єктне сховище, ОС як ОС, російське обладнання з реєстру та засоби криптографічного захисту інформації. Три якорі, які тримають такий контур: російська юрисдикція всіх правовласників, наявність компонентів у реєстрах із сертифікатами регуляторів та ланцюжок збірки й постачання оновлень цілком усередині РФ.
Що в підсумку
Тримати легасі далі невигідно, а перехід на сучасний стек окупається. Приріст на сховищі — чиста інженерія: свіже ядро, свіжий емулятор, свіжі бібліотеки, узгоджені та оновлені разом. Це працює на будь-якому сучасному дистрибутиві. Вітчизняна ОС додає до продуктивності сертифікацію та реєстр — для контуру під вимогами оновлення окупається двічі: швидкістю та регуляторикою. Коли вибір стоїть між мертвим CentOS, нереєстровим зарубіжним дистрибутивом і сертифікованою вітчизняною ОС із сучасним стеком, завдання давно не про швидкість.

Коментарі