DIY: Створіть власну хмару з Kubernetes (Частина 2)

Продовжуємо нашу серію публікацій про те, як побудувати власну хмару, використовуючи лише екосистему Kubernetes. У попередній статті ми пояснили, як підготувати базовий дистрибутив Kubernetes на основі Talos Linux та Flux CD. У цій статті ми покажемо вам кілька різних технологій віртуалізації в Kubernetes та підготуємо все необхідне для запуску віртуальних машин у Kubernetes, зокрема сховища і мережі.

Ми будемо говорити про такі технології, як KubeVirt, LINSTOR і Kube-OVN.

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

З іншого боку, Kubernetes спочатку не був призначений для багатокористувацької системи, тобто базовий шаблон використання передбачає створення окремого кластера Kubernetes для кожного незалежного проєкту та команди розробників.

Віртуальні машини є основним засобом ізоляції орендарів один від одного в хмарному середовищі. У віртуальних машинах користувачі можуть виконувати код і програми з адміністративними привілеями, але це не впливає на інших орендарів або саму інфраструктуру. Іншими словами, віртуальні машини дозволяють досягти жорсткої ізоляції орендарів та запуску в середовищах, де орендарі не довіряють один одному.

Технології віртуалізації в Kubernetes

Існує кілька різних технологій, які приносять віртуалізацію у світ Kubernetes: KubeVirt та Kata Containers є найпопулярнішими з них. Але варто знати, що вони працюють по-різному.

Kata Containers реалізує CRI (Container Runtime Interface) та забезпечує додатковий рівень ізоляції для стандартних контейнерів, запускаючи їх у віртуальних машинах. Але вони працюють в одному кластері Kubernetes.

Схема, що показує, як забезпечується ізоляція контейнерів шляхом запуску контейнерів у віртуальних машинах за допомогою Kata Containers

Схема, що показує, як забезпечується ізоляція контейнерів шляхом запуску контейнерів у віртуальних машинах за допомогою Kata Containers

KubeVirt дозволяє запускати традиційні віртуальні машини за допомогою API Kubernetes. Віртуальні машини KubeVirt запускаються як звичайні процеси Linux у контейнерах. Іншими словами, у KubeVirt контейнер використовується як середовище для запуску процесів віртуальної машини (QEMU). Це чітко видно на малюнку нижче, якщо подивитися, як реалізовано живу міграцію віртуальних машин у KubeVirt. Коли міграція потрібна, віртуальна машина переміщується з одного контейнера до іншого.

Схема, що показує живу міграцію віртуальної машини з одного контейнера до іншого у KubeVirt

Схема, що показує живу міграцію віртуальної машини з одного контейнера до іншого у KubeVirt

Існує також альтернативний проєкт — Virtink, який реалізує легку віртуалізацію за допомогою Cloud-Hypervisor і спочатку орієнтований на запуск віртуальних кластерів Kubernetes за допомогою Cluster API.

Враховуючи наші цілі, ми вирішили використати KubeVirt як найпопулярніший проєкт у цій галузі. Крім того, ми маємо великий досвід і вже зробили чималий внесок у KubeVirt.

KubeVirt легко встановлюється і дозволяє запускати віртуальні машини безпосередньо з коробки, використовуючи containerDisk — ця функція дозволяє зберігати та розповсюджувати образи VM безпосередньо як образи OCI з реєстру образів контейнерів. Віртуальні машини з containerDisk добре підходять для створення робочих вузлів Kubernetes та інших віртуальних машин, які не потребують збереження стану.

Для управління постійними даними KubeVirt пропонує окремий інструмент, Containerized Data Importer (CDI). Він дозволяє клонувати PVC і наповнювати їх даними з базових образів. CDI необхідний, якщо ви хочете автоматично виділяти постійні томи для ваших віртуальних машин, і він також потрібен для драйвера KubeVirt CSI, який використовується для обробки запитів на постійні томи з кластерів Kubernetes орендарів.

Але спочатку вам потрібно вирішити, де і як ви будете зберігати ці дані.

Сховище для VM в Kubernetes

З впровадженням CSI (Container Storage Interface) став доступний широкий спектр технологій, які інтегруються з Kubernetes. Насправді KubeVirt повністю використовує інтерфейс CSI, узгоджуючи вибір сховища для віртуалізації з вибором сховища для самого Kubernetes. Однак є нюанси, які вам потрібно врахувати. На відміну від контейнерів, які зазвичай використовують стандартну файлову систему, блокові пристрої є більш ефективними для віртуальних машин.

Хоча інтерфейс CSI в Kubernetes дозволяє запитувати обидва типи томів: файлові системи та блокові пристрої, важливо перевірити, чи підтримує це ваш бекенд сховища.

Використання блокових пристроїв для віртуальних машин усуває необхідність в додатковому шарі абстракції, такому як файлова система, що робить його більш продуктивним і в більшості випадків дозволяє використовувати режим ReadWriteMany. Цей режим дозволяє одночасно звертатися до тому з декількох вузлів, що є критично важливою функцією для забезпечення живої міграції віртуальних машин у KubeVirt.

Система зберігання може бути зовнішньою або внутрішньою (у випадку гіперконвергованої інфраструктури). Використання зовнішнього сховища в багатьох випадках робить всю систему більш стабільною, оскільки ваші дані зберігаються окремо від обчислювальних вузлів.

Схема, що показує взаємодію зовнішнього сховища даних з обчислювальними вузлами

Схема, що показує взаємодію зовнішнього сховища даних з обчислювальними вузлами

Зовнішні рішення для зберігання даних часто є популярними в корпоративних системах, оскільки таке сховище часто надається зовнішнім постачальником, який займається його експлуатацією. Інтеграція з Kubernetes включає лише невеликий компонент, встановлений у кластері — драйвер CSI. Цей драйвер відповідає за виділення томів у цьому сховищі та підключення їх до podʼів, які запускає Kubernetes. Втім, подібні рішення для зберігання даних можуть бути реалізовані й з використанням технологій з відкритим вихідним кодом. Одним з популярних рішень є TrueNAS на основі драйвера democratic-csi.

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

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

З іншого боку, гіперконвергентні системи часто реалізуються з використанням локального сховища (коли не потрібна реплікація) та програмно визначених сховищ, які часто встановлюються безпосередньо в Kubernetes, таких як Rook/Ceph, OpenEBS, Longhorn, LINSTOR та інші.

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

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

Гіперконвергентна система має свої переваги. Наприклад, локальність даних: коли ваші дані зберігаються локально, доступ до таких даних є швидшим. Але є і недоліки, оскільки така система зазвичай складніша в управлінні та обслуговуванні.

В Ænix ми прагнули надати готове до використання рішення, яке можна було б використовувати без необхідності купувати та налаштовувати додаткове зовнішнє сховище, і яке було б оптимальним з погляду швидкості та використання ресурсів. LINSTOR став цим рішенням. Перевірені часом та популярні в промисловості технології, такі як LVM і ZFS, як бекенд, дають упевненість у тому, що дані надійно зберігаються. Реплікація на основі DRBD неймовірно швидка і споживає невелику кількість обчислювальних ресурсів.

Для встановлення LINSTOR в Kubernetes існує проєкт Piraeus, який вже надає готове блокове сховище для використання з KubeVirt.

Мережа для віртуальних машин Kubernetes

Попри схожий інтерфейс — CNI, мережева архітектура в Kubernetes насправді є набагато складнішою та зазвичай складається з багатьох незалежних компонентів, які не повʼязані безпосередньо один з одним. Насправді ви можете розділити мережу Kubernetes на чотири рівні, які описані нижче.

Мережева інфраструктура вузлів (мережа дата-центру)

Мережа, якою вузли зʼєднуються один з одним. Ця мережа зазвичай не управляється Kubernetes, але є важливою, оскільки без неї нічого не працюватиме. На практиці фізична інфраструктура зазвичай має більше ніж одну таку мережу, наприклад, одну для комунікації між вузлами, другу для реплікації сховища, третю для зовнішнього доступу тощо.

Діаграма, що показує роль мережі вузлів (мережі дата-центру) у схемі мережі Kubernetes

Діаграма, що показує роль мережі вузлів (мережі дата-центру) у схемі мережі Kubernetes

Налаштування фізичної мережевої взаємодії між вузлами виходить за межі цієї статті, оскільки в більшості ситуацій Kubernetes використовує вже наявну мережеву інфраструктуру.

Мережа Podʼів

Це мережа, яку забезпечує ваш CNI-втулок. Завдання CNI-втулка полягає в забезпеченні прозорого зʼєднання між усіма контейнерами та вузлами в кластері. Більшість CNI-втулків реалізують пласку мережу, з якої окремі блоки IP-адрес виділяються для використання на кожному вузлі.

Діаграма, що показує роль мережі контейнерів (CNI-втулок) у схемі мережі Kubernetes

Діаграма, що показує роль мережі контейнерів (CNI-втулок) у схемі мережі Kubernetes

На практиці ваш кластер може мати кілька CNI-втулків, керованих Multus. Цей підхід часто використовується у рішеннях віртуалізації на основі KubeVirt — Rancher та OpenShift. Основний CNI-втулок використовується для інтеграції з сервісами Kubernetes, тоді як додаткові CNI-втулки використовуються для реалізації приватних мереж (VPC) та інтеграції з фізичними мережами вашого дата-центру.

Стандартні CNI-втулки можуть бути використані для підключення концентраторів (bridge) або фізичних інтерфейсів. Крім того, існують спеціалізовані втулки, такі як macvtap-cni, які розроблені для забезпечення більшої продуктивності.

Ще одним аспектом, який слід враховувати при запуску віртуальних машин у Kubernetes, є потреба в управлінні IP-адресами (IPAM), особливо для вторинних інтерфейсів, які надає Multus. Це зазвичай керується DHCP-сервером, що працює у вашій інфраструктурі. Додатково, призначення MAC-адрес для віртуальних машин може керуватись за допомогою Kubemacpool.

Проте на нашій платформі ми вирішили піти іншим шляхом і повністю покладаємося на Kube-OVN. Цей CNI-втулок базується на OVN (Open Virtual Network), який спочатку був розроблений для OpenStack і надає повне мережеве рішення для віртуальних машин у Kubernetes, з можливістю управління IP-адресами та MAC-адресами через Custom Resources, підтримує живу міграцію зі збереженням IP-адрес між вузлами, і дозволяє створювати VPC для фізичного розділення мереж між орендарями.

У Kube-OVN ви можете призначати окремі підмережі всьому namespace або підключати їх як додаткові мережеві інтерфейси за допомогою Multus.

Мережа сервісів (Services Network)

Окрім CNI-втулка, Kubernetes також має мережу сервісів, яка в основному потрібна для виявлення сервісів. На відміну від традиційних віртуальних машин, Kubernetes спочатку розроблений для запуску контейнерів із випадковою адресою. І мережа сервісів забезпечує зручну абстракцію (стабільні IP-адреси та DNS-імена), яка завжди буде спрямовувати трафік до правильного контейнера. Такий підхід також часто використовується з віртуальними машинами в хмарах, хоча їх IP-адреси зазвичай є статичними.

Діаграма, що показує роль мережі сервісів (втулок мережі сервісів) у схемі мережі Kubernetes

Діаграма, що показує роль мережі сервісів (втулок мережі сервісів) у схемі мережі Kubernetes

Реалізацію мережі сервісів у Kubernetes здійснює втулок мережі сервісів. Стандартною реалізацією є kube-proxy, який використовується в більшості кластерів. Але наразі ця функціональність може бути забезпечена як частина CNI-втулка. Найбільш передову реалізацію пропонує проєкт Cilium, який може працювати в режимі заміни kube-proxy.

Cilium базується на технології eBPF, яка дозволяє ефективно розвантажувати мережевий стек Linux, що підвищує продуктивність і безпеку в порівнянні з традиційними методами на основі iptables.

На практиці Cilium і Kube-OVN можуть бути легко інтегровані для забезпечення єдиного рішення, що пропонує безшовну багатокористувацьку мережу для віртуальних машин, а також досконалі мережеві політики та обʼєднану функціональність мережі сервісів.

Зовнішній балансувальник навантаження

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

Для bare-metal кластерів Kubernetes доступні кілька балансувальників навантаження: MetalLB, kube-vip, LoxiLB, також Cilium та Kube-OVN забезпечують вбудовану реалізацію.

Роль зовнішнього балансувальника навантаження полягає в наданні стабільної адреси, доступної зовні, і спрямуванні зовнішнього трафіку до мережі сервісів. Втулок мережі сервісів направить його до ваших контейнерів та віртуальних машин, як зазвичай.

Роль зовнішнього балансувальника навантаження у схемі мережі Kubernetes

Діаграма, що показує роль зовнішнього балансувальника навантаження у схемі мережі Kubernetes

У більшості випадків налаштування балансувальника навантаження на bare-metal досягається шляхом створення плаваючої IP-адреси на вузлах у кластері та її оголошення назовні за допомогою протоколів ARP/NDP або BGP.

Вивчивши різні варіанти, ми вирішили, що MetalLB є найпростішим і найнадійнішим рішенням, хоча ми не вимагаємо суворого використання лише його.

Ще однією перевагою є те, що в режимі L2 спікери MetalLB постійно перевіряють стан сусідів, виконуючи перевірки на живучість за допомогою протоколу memberlist. Це дозволяє реалізувати автоматичне перемикання у разі відмови, яке працює незалежно від панелі управління Kubernetes.

Висновок

Цим завершується наш огляд віртуалізації, зберігання та мереж в Kubernetes. Усі згадані технології доступні та вже налаштовані на платформі Cozystack, де ви можете їх спробувати без обмежень.

У наступній статті я розповім, як на основі цього ви можете реалізувати створення повнофункціональних кластерів Kubernetes одним дотиком.