Особливості тестування технології C/R-Linux



У 2012 році Ендрю Мортон був песимістично налаштований щодо майбутнього проекту CRIU (Checkpoint and Restore In Userspace), коли приймав перші зміни в Linux ядро для підтримки C/R (Checkpoint/Restore). Ідея реалізувати функціональність збереження і відновлення запущених процесів у просторі користувача виглядала сумасшедшей, а через 4 роки проект не тільки живий, а все більше викликає інтерес до себе. До старту проекту CRIU робилися спроби реалізувати C/R-Linux (DMTCP, BLCR, OpenVZ, CKPT і т. д.), але і всі вони з різних причин були приречені на провал у той час як CRIU став життєздатним проектом. Нажаль від цього завдання C/R-Linux не стала простіше. У цій статті я розповім про особливості тестування CRIU.

Про користь юніт-тестування, застосування систем безперервної інтеграції вже написані книги і сотні статей. Ці прийоми відомі кожному досвідченому розробнику і є абсолютним стандартом для будь-якого програмного проекту. Тому ми не будемо тут описувати переваги використання цих технік, а замість цього розповімо тільки про нюанси, які відрізняють CRIU від інших проектів.

Сам по собі процес розробки CRIU нічим не відрізняється від розробки ядра Linux: кожне нове зміна це одна закінчена думка. Всі патчі приходять на розсилку criu@, де піддаються рев'ю. Патчі минулі рев'ю додаються в репозиторій ментейнером проекту. Хоча на стадії рев'ю і виявляється частина проблем в коді, але звести їх до нуля не вийде із-за кількості сценаріїв і конфігурацій. Тому для виявлення деградаций ми запускаємо тести для кожного нового зміни. Гарант постійного запуску тестів це автоматичні робочі тести.

На ранніх етапах розробки ми почали використовувати функціональні тести з тестового набору ZDTM (Zero DownTime Migration), якими вже успішно тестували in-kernel реалізацію C/R в OpenVZ. Зараз кожен тест з цього набору запускається окремо і проходить 3 стадії: підготовка оточення, «демонізація» і очікування сигналу (який сигналізує йому про те, що пора перевіряти свій стан), перевірка результату. Тести умовно розділені на дві групи. Перша група — це статичні тести, які готують якесь постійне оточення або стан і «засинають» в очікуванні сигналу. Друга група — динамічні тести, які постійно змінюють свій стан і/або оточення (наприклад пересилають дані через з'єднання TCP). Якщо в 2012 році система юніт-тестування CRIU налічувала близько 70 окремих тестових програм, то на сьогоднішній день їх кількість збільшилася до 200. Але справді жахає кількість комбінацій, яке потрібно запустити для повноцінного тестування CRIU.

Основна конфігурація — запуск всього набору тестів на хості, при якому кожна тестова програма сідає в певну позу, процес тесту зберігають і відновлюють і потім просять перевірити в тій же позі він залишився чи ні. Наступною за важливістю конфігурацією є перевірка, що C/R не тільки працює, але і після C основний процес не поламався. Тому кожен тест потрібно прогнати ще й у варіанті коли виконана тільки перша частина (без відновлення) і перевірити, що поза дотримана. Це безресторный тест. Відновлений процес може опинитися в тій же позі, але не придатний до повторного C/R. Так з'являється ще одна конфігурація — повторний C/R. Потім з'являються конфігурації з снапшоти, C/R в оточенні просторів імен, C/R з правами звичайного користувача, C/R з перевіркою зворотної сумісності, перевірка успішного відновлення на BTRFS і NFS (тому що ці ФС мають свої «особливості»). Але крім C/R для окремих процесів, можна робити групові C/R — збереження групи процесів, коли всі процеси знаходяться в одній позі і коли кожен процес перебуває у своїй позі.

CRIU підтримує декілька апаратних архітектур, зараз це x86_64, ARM, AArch64, PPC64le і на підході i386. Сувора реальність змушує нас тестувати ще й кілька версій ядер: останній офіційний реліз ванільного ядра, ядро RHEL7 (яке базується на 3.11) і гілку linux-next. Тривалість тестів невелика (2-10 хв), але якщо врахувати кількість комбінацій існуючих сценаріїв і можливих конфігурацій, то виходить чимала цифра.

Як я вже писав, тести приносять користь тільки тоді, коли ними регулярно користуються. До деяких пір ми запускали тести вручну, але в якийсь момент зрозуміли що локальне тестування забирає багато часу у розробників і налаштували систему безперервного запуску тестів на кожне нове зміна.

Ми використовуємо дві CI системи: Travis CI використовується для перевірки компіляції на всіх підтримуваних апаратних архітектур. Так як Travis CI використовує ядро нижче версії 3.8, в якому відсутня більша частина патчів, необхідних для CRIU, то Travis не підходить для запуску тестів і додатково ми використовуємо широко відомий Jenkins CI.

Висновки

  • складання, тестування та вимірювання покриття коду повинні бути автоматизовані
  • багато тестів не буває, у нас співвідношення корисного коду до тестового коду приблизно 1.6 (48 KLOC vs 30 KLOC) і є куди прагнути
  • якщо кількість конфігурацій для тестування величезна, приоритезируйте
  • робочих рук як завжди не вистачає, приходьте до нас в CRIU?


Проект CRIU було розпочато у 2012 році інженерами компанії Virtuozzo, але пізніше його підтримали і інші компанії, зацікавлені у створенні технології C/R-Linux.

Джерело: Хабрахабр

0 коментарів

Тільки зареєстровані та авторизовані користувачі можуть залишати коментарі.