Docker-compose в Nomad job без зайвих рухів
Досить часто у роботі розробника виникає необхідність у використанні сторонніх сервісів для виконання задачі. Цим стороннім сервісом може бути як база даних, так і брокер повідомлень. Звісно, можна розгортати необхідні залежності на своїй операційній системі, читати велику кількість документації зі встановлення і налаштування, і дістати таку необхідну для виконання задачі залежність, але ціна за все це — час, витрачений на те, що вже багато разів було зроблено до цього.
Тому хтось придумав нехитру надбудову над операційною системою і назвав її Docker. Але і вона виявилась складною в використанні, бо має дуже велику кількість налаштувань. При навіть невеликій кількості залежностей кількість флагів, необхідних для конфігурації контейнера, росте дуже швидко. Тому з’явився такий інструмент як docker-compose. І життя для девелопера наладилось (так може здатись на перший погляд).
Які складнощі зустрічаються при переході від розробки на локальному сервері до розгортання бойової версії
Розробка розробкою, але те, що було розроблено, має, рано чи пізно, слугувати цілі, яку переслідували ініціатори проекту. І тут постає задача перенесення проекту з робочого оточення девелопера у недружній світ серверів, де якась частина сервісів належить третім особам, що постійно генерує проблеми з оновленням, і docker-compose вже не справляється. Потрібно думати над тим, як керувати всім цим зоопарком сервісів у більш гнучкий спосіб.
Які існують рішення, і чому Kubernetes — не панацея
Усі, хто хоч раз працював з контейнерами, мав чути про системи оркестрації. Kubernetes і його форки — найбільш розповсюджений вибір серед адміністраторів додатків (DevOps спеціалістів). Але в силу значної кількості рухомих частин (налаштувань, політик, специфікацій), Kubernetes ще більше змушує приходити до того, що потрібно читати документацію, і, як наслідок, витрачати час.Крім цього, у підходу з kubernetes є певні особливості, які не дуже помітні при читанні документації.
Як приклад, для кожного сервісу, розгорнутого у kubernetes-кластері, окрім сервісу кластера, створюється ще один контейнер, який виконує нагляд за цим сервісом, що споживає ресурси. Такий стан справ може досить сильно розчарувати при запуску великої кількості маленьких (нересурсоємних) сервісів. Для ілюстрації цього феномену можна посилатися на одну замітку (хоч мова йде не про kubernetes). http://sven.stormbind.net/blog/posts/docker_from_30_to_230/
Nomad — як один з можливих варіантів (для тих, хто вміє рахувати)
Оркестрація з підходом сервіс + сервіс-менеджер — досить неоптимальний підхід у випадку обмежених ресурсів. І варіантів оптимізації рішення — велика кількість, проте один з них заслуговує уваги, в силу того, що з’явилась версія 1.0 не так давно, 8 грудня 2020 року. Nomad — сервіс оркестрації, який вирішує лише частину проблеми (у порівнянні з Kubernetes), але те, як він це вирішує і є головним фактором прийняття його набір інструментів розробника.
Основна відмінність підходу до оркестрації у обов’язковому встановленні обмеження ресурсів на сервіс, який буде запущений оркестратором, якщо мова йде про контенери. А ще відсутність обов’язкового сервіс-менеджера (можна назвати його sidecar). Це сприяє використанню обчислювальних ресурсів з більшим коефіцієнтом корисної дії.
Складнощі при перетворенні compose файлів у nomad і шляхи рішення
Оскільки стабільна версія nomad з’явилась відносно недавно, стан і кількість доробків, які б спрощували перехід з інших систем оркестрації, невеликий. Ще одним фактором є фомат конфігурації HCL, який навмисно адаптований для зручності читання людьми і абсолютно не адаптований для автоматизації написання.
Формат compose файлів простий і складний водночас. Для написання його парсера потрібно враховувавти, що є кілька версій docker-compose, що існує можливість «наслідувати» конфігурацію іншого compose файла і переписувати лише якісь частини. Велика кількість опцій, не всі з яких завжди використовуються. Тому логічним звучить взяти якусь готову бібліотеку для рішення цієї задачі.
Якщо подумати, то можна помітити, що docker-compose дуже однозначно можна відобразити у nomad. Адже задача (job) складається з якоїсь кількості підзадач (task), поділених на групи (group). Одним з варіантів розбиття на групи можна обрати належність сервісу до якоїсь мережі в compose файлі.
Огляд рішень і створення свого з преферансом і дамами
Першою справою при бажанні щось зробити, потрібно перевірити, чи не зроблено це вже в іншому місці. Тому якщо пошукати в інтернеті за ключовими словами «docker-compose to nomad», перший же рядок у видачі дає зрозуміти, що хтось цією думкою вже був інфікований. github.com/jovandeginste/nomad-compose — це один з варіантів рішення цієї задачі, але щось у цьому рішенні немає оптимізму. Біглий огляд з мінімальним знанням синтаксису мови програмування приводять до висновку, що використовуються темплейти для генерування необхідних Nomad-задач. Цей метод універсальний, але не дуже гнучкий.
Більше якихось релевантних видач не підвернулось, а для Kubernetes за схожим принципом можна знайти kompose.io/.
Доведеться зробити рішення для цієї задачі власноруч: пошук бібліотек для читання docker-compose файлів приводить до вибору: Python бібліотеки або Go, тому що Go — рідна мова для Docker. І уважно вивчивши всі за і проти, вибір зупинився на Go-бібліотеці, бо існує специфікація docker-compose файлу і вона доступна як Go-бібліотека. Якщо дослідити інші репозиторії у цій організації, можна помітити docker-compose на мінімалках. Тут на думку приходить позичити частину імплементації, яка читає compose-файли, залишається лише зробити цю річ сумісною з Python, адже знову спіткає проблема мінімального знання синтаксису. І після нетривалих пошуків знаходиться рішення: компілювати Go в shared lib з C заголовками. На щастя, така можливість у Go передбачена, хоч і з певними обмеженнями.
Після того як С бібліотека зібрана, непогано було б її прив’язати до Python. Це можна зробити кількома способами, але простішим здається використати
Тепер потрібно розібратись з написанням задач для Nomad. Після довгих пошуків хоч якогось прикладу синтезування HCL-файлів, здавалось розумним не використовувати nomad-cli, а відразу генерувати запити на nomad-api, але від версії до версії API помалу змінюється, а формат специфікації задач змінюється значно повільніше. Тому ще трохи пошукавши, можна наткнутись на сторінку, що прямо диктує: кожен файл у HCL синтаксисі можна записати у форматі JSON. А цей формат вже легко генерувати програмно. І уважно вивчивши, що nomad приймає у якості файлів задач, можна помітити JSON серед підтримуваних. Тепер і друга частина пазлу вирішена.
Усе, що потрібно зробити, це перетворити структуру даних з compose-виду у nomad-вид. Тут ніяких перепон немає, залишається доповнювати мінімальний набір підтримуваних опцій. На щастя, Python має такі вбудовані структури даних як defaultdict і ChainMap, які в купі дозволяють підставляти значення за замовчуванням у деревовидних структурах даних.
Про те, що з цього вийшло, можна глянути за посиланням.
14 коментарів
Додати коментар Підписатись на коментаріВідписатись від коментарів