Це багатосторінковий друкований вигляд цього розділу. Натисність щоб друкувати.
Блог
DIY: Створіть власну хмару з Kubernetes (Частина 3)
Наближаючись до найцікавішої фази, ця стаття розглядає запуск Kubernetes всередині Kubernetes. Висвітлюються такі технології, як Kamaji та Cluster API, а також їх інтеграція з KubeVirt.
Попередні обговорення охоплювали підготовку Kubernetes на "голому" обладнанні та як перетворити Kubernetes на систему управління віртуальними машинами. Ця стаття завершує серію, пояснюючи, як, використовуючи все вищезазначене, ви можете створити повноцінний керований Kubernetes і запускати віртуальні кластери Kubernetes одним дотиком.
Почнемо з Cluster API.
Cluster API
Cluster API — це розширення для Kubernetes, яке дозволяє керувати кластерами Kubernetes як власними ресурсами користувача всередині іншого кластеру Kubernetes.
Основна мета Cluster API — забезпечити єдиний інтерфейс для опису основних сутностей кластера Kubernetes і управління їх життєвим циклом. Це дозволяє автоматизувати процеси створення, оновлення та видалення кластерів, спрощуючи масштабування та управління інфраструктурою.
У контексті Cluster API є два терміни: кластер управління та кластери користувачів.
- Кластер управління — це кластер Kubernetes, що використовується для розгортання та управління іншими кластерами. Цей кластер містить всі необхідні компоненти Cluster API та відповідає за опис, створення та оновлення кластерів користувачів. Він часто використовується тільки для цієї мети.
- Кластери користувачів — це кластери користувачів або кластери, що розгортаються за допомогою Cluster API. Вони створюються шляхом опису відповідних ресурсів у кластері управління. Вони використовуються для розгортання застосунків та сервісів кінцевими користувачами.
Важливо розуміти, що фізично кластери користувачів не обовʼязково повинні працювати на тій же інфраструктурі, що і кластер управління; частіше за все вони розгортаються в іншому місці.
Для своєї роботи Cluster API використовує концепцію провайдерів, які є окремими контролерами, що відповідають за конкретні компоненти створюваного кластера. В межах Cluster API існує кілька типів провайдерів. Основні з них:
- Провайдер інфраструктури, який відповідає за надання обчислювальної інфраструктури, такої як віртуальні машини або фізичні сервери.
- Провайдер панелі управління, який надає панель управління Kubernetes, а саме компоненти kube-apiserver, kube-scheduler та kube-controller-manager.
- Провайдер Bootstrapping, який використовується для створення конфігурацій cloud-init для віртуальних машин та серверів, що створюються.
Щоб почати, вам потрібно буде встановити сам Cluster API та одного провайдера кожного типу. Повний список підтримуваних провайдерів можна знайти в документації проєкту Cluster API.
Для встановлення можна використовувати утиліту clusterctl
або Cluster API Operator як більш декларативний метод.
Вибір провайдерів
Провайдер інфраструктури
Для запуску кластерів Kubernetes за допомогою KubeVirt, необхідно встановити Infrastructure Provider KubeVirt. Він дозволяє розгортання віртуальних машин для робочих вузлів у тому ж кластері управління, де працює Cluster API.
Провайдер панелі управління
Проєкт Kamaji пропонує готове рішення для запуску панелі управління Kubernetes для кластерів користувачів як контейнерів у кластері управління. Цей підхід має кілька суттєвих переваг:
- Економічність: Запуск панелі управління в контейнерах запобігає використанню окремих вузлів панелі управління для кожного кластеру, що суттєво знижує витрати на інфраструктуру.
- Стабільність: Спрощення архітектури шляхом усунення складних багатошарових схем розгортання. Замість послідовного запуску віртуальної машини, а потім встановлення компонентів etcd та Kubernetes всередині неї, є проста панель управління, яка розгортається і працює як звичайний застосунок всередині Kubernetes та управляється оператором.
- Безпека: Панель управління кластера прихована від кінцевого користувача, що знижує можливість компрометації її компонентів, а також усуває доступ користувачів до сховища сертифікатів кластера. Такий підхід до організації панелі управління, невидимої для користувача, часто використовують постачальники хмарних послуг.
Провайдер Bootstrapping
Kubeadm як Bootstrapping Provider — стандартний метод підготовки кластерів у Cluster API. Цей провайдер розроблений як частина самого Cluster API. Він вимагає лише підготовленого системного образу з встановленими kubelet і kubeadm і дозволяє генерувати конфігурації у форматах cloud-init та ignition.
Слід зазначити, що Talos Linux також підтримує виділення ресурсів через Cluster API та має провайдерів для цього. Хоча попередні статті обговорювали використання Talos Linux для налаштування кластера управління на вузлах bare-metal, для створення клієнтських кластерів підхід Kamaji+Kubeadm має більше переваг. Він полегшує розгортання панелей управління Kubernetes у контейнерах, усуваючи необхідність окремих віртуальних машин для екземплярів панелі управління. Це спрощує управління та знижує витрати.
Як це працює
Основний обʼєкт у Cluster API — це ресурс Cluster, який виступає як батьківський для всіх інших. Зазвичай цей ресурс посилається на два інші: ресурс, що описує панель управління, та ресурс, що описує інфраструктуру, кожен з яких управляється окремим провайдером.
На відміну від Cluster, ці два ресурси не є стандартизованими, і їх тип залежить від конкретного провайдера, якого ви використовуєте:
У межах Cluster API також існує ресурс з назвою MachineDeployment, який описує групу вузлів, хоч то фізичні сервери, хоч віртуальні машини. Цей ресурс функціонує подібно до стандартних ресурсів Kubernetes, таких як Deployment, ReplicaSet та Pod, надаючи механізм для декларативного опису групи вузлів і автоматичного масштабування.
Іншими словами, ресурс MachineDeployment дозволяє вам декларативно описати вузли для вашого кластера, автоматизуючи їх створення, видалення та оновлення відповідно до заданих параметрів і запитуваної кількості реплік.
Для створення машин MachineDeployment посилається на шаблон для генерації самої машини та шаблон для генерації її конфігурації cloud-init:
Щоб розгорнути новий кластер Kubernetes за допомогою Cluster API, вам потрібно буде підготувати наступний набір ресурсів:
- Загальний ресурс Cluster
- Ресурс KamajiControlPlane, відповідальний за панель управління, що управляється Kamaji
- Ресурс KubevirtCluster, що описує конфігурацію кластера в KubeVirt
- Ресурс KubevirtMachineTemplate, відповідальний за шаблон віртуальної машини
- Ресурс KubeadmConfigTemplate, відповідальний за генерацію токенів і cloud-init
- Щонайменше один MachineDeployment для створення деяких робочих ресурсів (workers)
Шліфування кластера
У більшості випадків цього достатньо, але залежно від використаних провайдерів, вам можуть знадобитися й інші ресурси. Ви можете знайти приклади ресурсів, створених для кожного типу провайдера, в документації проєкту Kamaji.
На цьому етапі ви вже маєте готовий клієнтський кластер Kubernetes, але наразі він містить лише API-робітників і кілька основних втулків, що стандартно включені в установку будь-якого кластера Kubernetes: kube-proxy та CoreDNS. Для повної інтеграції вам потрібно буде встановити ще кілька компонентів:
Щоб встановити додаткові компоненти, ви можете використовувати окремий Cluster API Add-on Provider для Helm, або той же FluxCD, про який згадувалося в попередніх статтях.
При створенні ресурсів у FluxCD, можна вказати цільовий кластер, звертаючись до kubeconfig, згенерованого Cluster API. Тоді установка буде виконана безпосередньо в нього. Таким чином, FluxCD стає універсальним інструментом для управління ресурсами як у кластері управління, так і в клієнтських кластерах.
Які компоненти обговорюються тут? Загалом, набір включає наступні:
Втулок CNI
Щоб забезпечити комунікацію між podʼами в клієнтському кластері Kubernetes, необхідно розгорнути втулок CNI. Цей втулок створює віртуальну мережу, яка дозволяє podʼам взаємодіяти один з одним і традиційно розгортається як Daemonset на робочих вузлах кластера. Ви можете вибрати та встановити будь-який втулок CNI, який вважаєте відповідним.
Cloud Controller Manager
Основне завдання Cloud Controller Manager (CCM) — інтеграція Kubernetes з середовищем провайдера хмари (в вашому випадку це кластер управління Kubernetes, в якому створюються всі робітники клієнтського Kubernetes). Ось деякі з його завдань:
- Коли створюється сервіс типу LoadBalancer, CCM ініціює процес створення хмарного балансувальника навантаження, який направляє трафік до вашого кластера Kubernetes.
- Якщо вузол видаляється з хмарної інфраструктури, CCM забезпечує його видалення з вашого кластера також, підтримуючи поточний стан кластера.
- При використанні CCM вузли додаються до кластера з особливим taint,
node.cloudprovider.kubernetes.io/uninitialized
, який дозволяє обробку додаткової бізнес-логіки, якщо це необхідно. Після успішної ініціалізації цей taint видаляється з вузла.
Залежно від постачальника хмари, CCM може працювати як всередині, так і зовні клієнтського кластера.
Провайдер хмари KubeVirt розроблений для установки у зовнішньому батьківському кластері управління. Таким чином, створення сервісів типу LoadBalancer в клієнтському кластері ініціює створення сервісів LoadBalancer у батьківському кластері, які направляють трафік в клієнтський кластер.
Драйвер CSI
Container Storage Interface (CSI) розділений на дві основні частини для взаємодії зі зберіганням у Kubernetes:
- csi-controller: Цей компонент відповідає за взаємодію з API постачальника хмари для створення, видалення, підключення, відключення та зміни розміру томів.
- csi-node: Цей компонент працює на кожному вузлі та полегшує монтування томів до podʼів на запит kubelet.
У контексті використання CSI драйвера KubeVirt виникає унікальна можливість. Оскільки віртуальні машини в KubeVirt працюють всередині кластеру управління Kubernetes, де доступне повноцінний API Kubernetes, це відкриває шлях для запуску csi-controller ззовні клієнтського кластера. Цей підхід є популярним у спільноті KubeVirt і має кілька ключових переваг:
- Безпека: Цей метод приховує внутрішнє API хмари від кінцевого користувача, надаючи доступ до ресурсів виключно через інтерфейс Kubernetes. Таким чином, зменшується ризик прямого доступу до кластера управління з клієнтських кластерів.
- Простота і зручність: Користувачам не потрібно управляти додатковими контролерами у своїх кластерах, спрощуючи архітектуру і зменшуючи навантаження управління.
Однак, csi-node обовʼязково повинен працювати всередині клієнтського кластера, оскільки він безпосередньо взаємодіє з kubelet на кожному вузлі. Цей компонент відповідає за монтування та демонтування томів у podʼах, вимагаючи тісної інтеграції з процесами, що відбуваються безпосередньо на вузлах кластера.
CSI-драйвер KubeVirt діє як проксі для замовлення томів. Коли PVC створюється всередині клієнтського кластера, PVC створюється в кластері управління, а потім створений PV підключається до віртуальної машини.
Автоматичний масштабувальник кластера
Cluster Autoscaler є універсальним компонентом, який може працювати з різними API хмари, а його інтеграція з Cluster-API є лише однією з доступних функцій. Для правильного налаштування він потребує доступу до двох кластерів: клієнтського кластера, щоб відстежувати podʼи та визначати необхідність додавання нових вузлів, і кластеру управління Kubernetes (кластер управління), де він взаємодіє з ресурсом MachineDeployment та регулює кількість реплік.
Хоча Cluster Autoscaler зазвичай працює всередині кластера Kubernetes клієнта, у цьому випадку рекомендується встановити його зовні з тих же причин, що і раніше. Цей підхід простіший в обслуговуванні та більш безпечний, оскільки запобігає доступу користувачів клієнтських кластерів до API управління кластером.
Konnectivity
Є ще один додатковий компонент, про який я хотів би згадати — Konnectivity. Ймовірно, він вам знадобиться пізніше, щоб налаштувати вебхуки та шар агрегації API в вашому клієнтському кластері Kubernetes. Це питання детально висвітлене в одній з моїх попередніх статей.
На відміну від наведених вище компонентів, Kamaji дозволяє легко увімкнути Konnectivity та управляти ним як одним з основних компонентів вашого клієнтського кластера, поряд з kube-proxy і CoreDNS.
Висновок
Тепер у вас є повністю функціональний кластер Kubernetes з можливістю динамічного масштабування, автоматичного постачання томів та балансувальників навантаження.
Далі ви можете розглянути збір метрик і логів з ваших клієнтських кластерів, але це вже виходить за межі цієї статті.
Звичайно, всі компоненти, необхідні для розгортання кластера Kubernetes, можна упакувати в один Helm chart і розгорнути як єдиний застосунок. Саме так ми організовуємо розгортання керованих кластерів Kubernetes одним натисканням кнопки на нашій відкритій платформі PaaS, Cozystack, де ви можете безкоштовно випробувати всі технології, описані в статті.
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.
KubeVirt дозволяє запускати традиційні віртуальні машини за допомогою API Kubernetes. Віртуальні машини KubeVirt запускаються як звичайні процеси Linux у контейнерах. Іншими словами, у KubeVirt контейнер використовується як середовище для запуску процесів віртуальної машини (QEMU). Це чітко видно на малюнку нижче, якщо подивитися, як реалізовано живу міграцію віртуальних машин у 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.
Примітка:
У випадку, якщо ви використовуєте Talos Linux, як ми описали в попередній статті, вам потрібно буде заздалегідь активувати необхідні модулі ядра і налаштувати piraeus, як описано в інструкції.Мережа для віртуальних машин Kubernetes
Попри схожий інтерфейс — CNI, мережева архітектура в Kubernetes насправді є набагато складнішою та зазвичай складається з багатьох незалежних компонентів, які не повʼязані безпосередньо один з одним. Насправді ви можете розділити мережу Kubernetes на чотири рівні, які описані нижче.
Мережева інфраструктура вузлів (мережа дата-центру)
Мережа, якою вузли зʼєднуються один з одним. Ця мережа зазвичай не управляється Kubernetes, але є важливою, оскільки без неї нічого не працюватиме. На практиці фізична інфраструктура зазвичай має більше ніж одну таку мережу, наприклад, одну для комунікації між вузлами, другу для реплікації сховища, третю для зовнішнього доступу тощо.
Налаштування фізичної мережевої взаємодії між вузлами виходить за межі цієї статті, оскільки в більшості ситуацій Kubernetes використовує вже наявну мережеву інфраструктуру.
Мережа Podʼів
Це мережа, яку забезпечує ваш CNI-втулок. Завдання CNI-втулка полягає в забезпеченні прозорого зʼєднання між усіма контейнерами та вузлами в кластері. Більшість CNI-втулків реалізують пласку мережу, з якої окремі блоки IP-адрес виділяються для використання на кожному вузлі.
На практиці ваш кластер може мати кілька 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 здійснює втулок мережі сервісів. Стандартною реалізацією є kube-proxy, який використовується в більшості кластерів. Але наразі ця функціональність може бути забезпечена як частина CNI-втулка. Найбільш передову реалізацію пропонує проєкт Cilium, який може працювати в режимі заміни kube-proxy.
Cilium базується на технології eBPF, яка дозволяє ефективно розвантажувати мережевий стек Linux, що підвищує продуктивність і безпеку в порівнянні з традиційними методами на основі iptables.
На практиці Cilium і Kube-OVN можуть бути легко інтегровані для забезпечення єдиного рішення, що пропонує безшовну багатокористувацьку мережу для віртуальних машин, а також досконалі мережеві політики та обʼєднану функціональність мережі сервісів.
Зовнішній балансувальник навантаження
На цьому етапі у вас вже є все необхідне для запуску віртуальних машин у Kubernetes. Але насправді є ще одна річ. Вам все ще потрібно отримати доступ до ваших сервісів із зовнішнього середовища, і зовнішній балансувальник навантаження допоможе вам з організацією цього.
Для bare-metal кластерів Kubernetes доступні кілька балансувальників навантаження: MetalLB, kube-vip, LoxiLB, також Cilium та Kube-OVN забезпечують вбудовану реалізацію.
Роль зовнішнього балансувальника навантаження полягає в наданні стабільної адреси, доступної зовні, і спрямуванні зовнішнього трафіку до мережі сервісів. Втулок мережі сервісів направить його до ваших контейнерів та віртуальних машин, як зазвичай.
У більшості випадків налаштування балансувальника навантаження на bare-metal досягається шляхом створення плаваючої IP-адреси на вузлах у кластері та її оголошення назовні за допомогою протоколів ARP/NDP або BGP.
Вивчивши різні варіанти, ми вирішили, що MetalLB є найпростішим і найнадійнішим рішенням, хоча ми не вимагаємо суворого використання лише його.
Ще однією перевагою є те, що в режимі L2 спікери MetalLB постійно перевіряють стан сусідів, виконуючи перевірки на живучість за допомогою протоколу memberlist. Це дозволяє реалізувати автоматичне перемикання у разі відмови, яке працює незалежно від панелі управління Kubernetes.
Висновок
Цим завершується наш огляд віртуалізації, зберігання та мереж в Kubernetes. Усі згадані технології доступні та вже налаштовані на платформі Cozystack, де ви можете їх спробувати без обмежень.
У наступній статті я розповім, як на основі цього ви можете реалізувати створення повнофункціональних кластерів Kubernetes одним дотиком.
DIY: Створіть власну хмару з Kubernetes (Частина 1)
У Ænix ми дуже любимо Kubernetes і мріємо, що всі сучасні технології незабаром почнуть використовувати його чудові патерни.
Чи думали ви коли-небудь про створення власної хмари? Я впевнений, що так. Але чи можливо це зробити, використовуючи лише сучасні технології та підходи, не виходячи за межі затишної екосистеми Kubernetes? Наш досвід у розробці Cozystack змусив нас глибоко заглибитись у це питання.
Ви можете стверджувати, що Kubernetes не призначений для цього, і чому б просто не використовувати OpenStack на "звичайних" серверах та запускати Kubernetes всередині нього, як це задумано. Але в цьому випадку ви просто передаєте відповідальність зі своїх рук у руки адміністраторів OpenStack. Це додасть ще одну велику та складну систему до вашої екосистеми.
Навіщо ускладнювати речі? — адже Kubernetes вже має все необхідне для запуску кластерів орендаря Kubernetes на цьому етапі.
Я хочу поділитися з вами нашим досвідом у розробці хмарної платформи на основі Kubernetes, виділивши відкриті проєкти, які ми використовуємо самі та вважаємо, що вони заслуговують вашої уваги.
У цій серії статей я розповім вам нашу історію про те, як ми готуємо керовані кластери Kubernetes на "голому" залізі, використовуючи лише відкриті технології. Починаючи з базового рівня підготовки дата-центру, запуску віртуальних машин, ізоляції мереж, налаштування відмовостійкого сховища до забезпечення повнофункціональних кластерів Kubernetes з динамічним розподілом томів, балансувальниками навантаження та автомасштабуванням.
Цією статтею я починаю серію, яка складатиметься з кількох частин:
- Частина 1: Підготовка основи для вашої хмари. Виклики, з якими стикаються під час підготовки та експлуатації Kubernetes на "голому" залізі, та готовий рецепт для забезпечення інфраструктури.
- Частина 2: Мережі, сховища та віртуалізація. Як перетворити Kubernetes на інструмент для запуску віртуальних машин і що для цього потрібно.
- Частина 3: Cluster API і як почати розгортання кластерів Kubernetes натисканням однієї кнопки. Як працює автомасштабування, динамічний розподіл томів і балансувальники навантаження.
Я спробую описати різні технології якнайбільше незалежно, але водночас поділюся нашим досвідом і поясню, чому ми прийшли до того чи іншого рішення.
Почнемо з розуміння основної переваги Kubernetes та того, як він змінив підхід до використання хмарних ресурсів.
Важливо розуміти, що використання Kubernetes у хмарі та на "голому" залізі відрізняється.
Kubernetes у хмарі
Коли ви оперуєте Kubernetes у хмарі, ви не хвилюєтеся про постійні томи, хмарні балансувальники навантаження або процес виділення вузлів. Усе це робить ваш хмарний провайдер, який приймає ваші запити у вигляді обʼєктів Kubernetes. Іншими словами, серверна сторона повністю прихована від вас, і вам не дуже цікаво знати, як саме хмарний провайдер реалізує це, оскільки це не ваша зона відповідальності.
Kubernetes пропонує зручні абстракції, які працюють однаково всюди, дозволяючи розгортати ваші застосунки на будь-якому Kubernetes у будь-якій хмарі.
У хмарі дуже часто є кілька окремих сутностей: панель управління Kubernetes, віртуальні машини, постійні томи та балансувальники навантаження як окремі сутності. Використовуючи ці сутності, ви можете створювати дуже динамічні середовища.
Завдяки Kubernetes, віртуальні машини тепер розглядаються лише як інструмент для використання хмарних ресурсів. Ви більше не зберігаєте дані всередині віртуальних машин. Ви можете видалити всі ваші віртуальні машини в будь-який момент і відтворити їх без порушення роботи вашого застосунку. панель управління Kubernetes продовжуватиме зберігати інформацію про те, що має працювати у вашому кластері. Балансувальник навантаження продовжить направляти трафік до вашого робочого навантаження, просто змінюючи точку доступу для передачі трафіку на новий вузол. А ваші дані будуть безпечно зберігатися у зовнішніх постійних томах, наданих хмарою.
Такий підхід є базовим при використанні Kubernetes у хмарах. Причина цього досить очевидна: чим простіша система, тим вона стабільніша, і саме за цю простоту ви купуєте Kubernetes у хмарі.
Kubernetes на "голому" залізі
Використання Kubernetes у хмарах дійсно просте та зручне, чого не можна сказати про установки на "голому" залізі. У світі "голого" заліза Kubernetes, навпаки, стає нестерпно складним. По-перше, тому що вся мережа, сховище даних, балансувальники навантаження тощо зазвичай працюють не зовні, а всередині вашого кластера. У результаті така система набагато складніша для оновлення та підтримки.
Судіть самі: у хмарі, щоб оновити вузол, ви зазвичай видаляєте віртуальну машину (або навіть використовуєте команду kubectl delete node
) і дозволяєте вашому інструменту керування вузлами створити новий на основі незмінного образу. Новий вузол приєднається до кластера і "просто працюватиме" як вузол; дотримуючись дуже простого та поширеного шаблону у світі Kubernetes. Багато кластерів замовляють нові віртуальні машини кожні кілька хвилин, просто тому, що вони можуть використовувати дешевші spot-екземпляри. Однак коли у вас є фізичний сервер, ви не можете просто видалити та відтворити його, по-перше, тому що він часто запускає деякі кластерні служби, зберігає дані, і процес його оновлення значно складніший.
Існують різні підходи до розвʼязання цієї проблеми, починаючи від оновлень на місці, як це роблять kubeadm, kubespray та k3s, до повної автоматизації забезпечення фізичних вузлів за допомогою Cluster API та Metal3.
Мені подобається гібридний підхід, який пропонує Talos Linux, де вся ваша система описується в одному конфігураційному файлі. Більшість параметрів цього файлу можна застосувати без перезавантаження або перестворення вузла, включаючи версію компонентів панелі управління Kubernetes. При цьому зберігається максимальна декларативність Kubernetes. Такий підхід мінімізує непотрібний вплив на кластерні сервіси при оновленні «голих» вузлів. У більшості випадків вам не потрібно буде мігрувати віртуальні машини та перебудовувати файлову систему кластера при незначних оновленнях.
Підготовка бази для майбутньої хмари
Отже, ви вирішили створити власну хмару. Щоб почати, потрібно створити базовий шар. Вам слід подумати не лише про те, як ви встановите Kubernetes на свої сервери, а й про те, як ви будете його оновлювати та підтримувати. Врахуйте, що вам доведеться думати про такі речі, як оновлення ядра, встановлення необхідних модулів, а також пакунків і оновлень безпеки. Тепер вам потрібно подумати про набагато більше, ніж зазвичай при використанні готового Kubernetes у хмарі.
Звісно, ви можете використовувати стандартні дистрибутиви, такі як Ubuntu або Debian, або ж розглянути спеціалізовані, як Flatcar Container Linux, Fedora Core і Talos Linux. Кожен з них має свої переваги та недоліки.
Що стосується нас, в Ænix, ми використовуємо досить специфічні модулі ядра, такі як ZFS, DRBD і OpenvSwitch, тому вирішили піти шляхом створення системного образу з усіма необхідними модулями заздалегідь. У цьому випадку Talos Linux виявився найбільш зручним для нас. Наприклад, достатньо такої конфігурації, щоб створити системний образ з усіма необхідними модулями ядра:
arch: amd64
platform: metal
secureboot: false
version: v1.6.4
input:
kernel:
path: /usr/install/amd64/vmlinuz
initramfs:
path: /usr/install/amd64/initramfs.xz
baseInstaller:
imageRef: ghcr.io/siderolabs/installer:v1.6.4
systemExtensions:
- imageRef: ghcr.io/siderolabs/amd-ucode:20240115
- imageRef: ghcr.io/siderolabs/amdgpu-firmware:20240115
- imageRef: ghcr.io/siderolabs/bnx2-bnx2x:20240115
- imageRef: ghcr.io/siderolabs/i915-ucode:20240115
- imageRef: ghcr.io/siderolabs/intel-ice-firmware:20240115
- imageRef: ghcr.io/siderolabs/intel-ucode:20231114
- imageRef: ghcr.io/siderolabs/qlogic-firmware:20240115
- imageRef: ghcr.io/siderolabs/drbd:9.2.6-v1.6.4
- imageRef: ghcr.io/siderolabs/zfs:2.1.14-v1.6.4
output:
kind: installer
outFormat: raw
Потім ми використовуємо командний рядок docker
для створення образу ОС:
cat config.yaml | docker run --rm -i -v /dev:/dev --privileged "ghcr.io/siderolabs/imager:v1.6.4" -
І в результаті ми отримуємо контейнерний образ Docker з усім необхідним, який можна використовувати для встановлення Talos Linux на наші сервери. Ви можете зробити те саме; цей образ міститиме всі необхідні прошивки та модулі ядра.
Але виникає питання: як доставити свіжостворений образ на ваші вузли?
Я давно розмірковував над ідеєю завантаження через PXE. Наприклад, проєкт Kubefarm, про який я писав в статті два роки тому, був повністю побудований на цьому підході. Але, на жаль, він не допомагає розгорнути ваш перший батьківський кластер, який міститиме інші. Тож зараз у вас є рішення, яке допоможе зробити це саме за допомогою підходу PXE.
По суті, все, що вам потрібно зробити, це запустити тимчасово DHCP і PXE сервери всередині контейнерів. Тоді ваші вузли завантажаться з вашого образу, і ви можете використовувати простий сценарій, схожий на Debian, щоб допомогти вам ініціалізувати вузли.
Вихідний код для цього сценарію talos-bootstrap
доступний на GitHub.
Цей сценарій дозволяє розгорнути Kubernetes на "голому" залізі за п’ять хвилин і отримати kubeconfig
для доступу до нього. Однак попереду ще багато невирішених питань.
Доставка системних компонентів
На цьому етапі у вас вже є кластер Kubernetes, здатний запускати різні робочі навантаження. Однак він ще не повністю функціональний. Іншими словами, вам потрібно налаштувати мережу та зберігання, а також встановити необхідні розширення кластера, такі як KubeVirt для запуску віртуальних машин, а також стек моніторингу та інші системні компоненти.
Традиційно це вирішується шляхом встановлення Helm чартів у ваш кластер. Ви можете зробити це, виконуючи команди helm install
локально, але цей підхід стає незручним, коли ви хочете відстежувати оновлення, і якщо у вас кілька кластерів і ви хочете, щоб вони залишалися однорідними. Насправді існує багато способів зробити це декларативно. Для подолання цієї задачі я рекомендую використовувати найкращі практики GitOps. Я маю на увазі інструменти, такі як ArgoCD та FluxCD.
Хоча ArgoCD зручніший для розробки завдяки графічному інтерфейсу та централізованій панелі управління, FluxCD, з іншого боку, краще підходить для створення дистрибутивів Kubernetes. За допомогою FluxCD ви можете вказати, які чарти з якими параметрами повинні бути запущені, і описати залежності. Після цього FluxCD подбає про все.
Пропонується одноразово встановити FluxCD у ваш новостворений кластер і надати йому конфігурацію. Це дозволить встановити все необхідне, щоб привести кластер до очікуваного стану.
Здійснивши одноразову інсталяцію FluxCD у вашому новому кластері та налаштувавши його відповідним чином, ви дозволяєте йому автоматично розгорнути всі необхідні компоненти. Це дозволить вашому кластеру оновити себе до потрібного стану. Наприклад, після встановлення нашої платформи ви побачите такі попередньо налаштовані Helm чарти з системними компонентами:
NAMESPACE NAME AGE READY STATUS
cozy-cert-manager cert-manager 4m1s True Release reconciliation succeeded
cozy-cert-manager cert-manager-issuers 4m1s True Release reconciliation succeeded
cozy-cilium cilium 4m1s True Release reconciliation succeeded
cozy-cluster-api capi-operator 4m1s True Release reconciliation succeeded
cozy-cluster-api capi-providers 4m1s True Release reconciliation succeeded
cozy-dashboard dashboard 4m1s True Release reconciliation succeeded
cozy-fluxcd cozy-fluxcd 4m1s True Release reconciliation succeeded
cozy-grafana-operator grafana-operator 4m1s True Release reconciliation succeeded
cozy-kamaji kamaji 4m1s True Release reconciliation succeeded
cozy-kubeovn kubeovn 4m1s True Release reconciliation succeeded
cozy-kubevirt-cdi kubevirt-cdi 4m1s True Release reconciliation succeeded
cozy-kubevirt-cdi kubevirt-cdi-operator 4m1s True Release reconciliation succeeded
cozy-kubevirt kubevirt 4m1s True Release reconciliation succeeded
cozy-kubevirt kubevirt-operator 4m1s True Release reconciliation succeeded
cozy-linstor linstor 4m1s True Release reconciliation succeeded
cozy-linstor piraeus-operator 4m1s True Release reconciliation succeeded
cozy-mariadb-operator mariadb-operator 4m1s True Release reconciliation succeeded
cozy-metallb metallb 4m1s True Release reconciliation succeeded
cozy-monitoring monitoring 4m1s True Release reconciliation succeeded
cozy-postgres-operator postgres-operator 4m1s True Release reconciliation succeeded
cozy-rabbitmq-operator rabbitmq-operator 4m1s True Release reconciliation succeeded
cozy-redis-operator redis-operator 4m1s True Release reconciliation succeeded
cozy-telepresence telepresence 4m1s True Release reconciliation succeeded
cozy-victoria-metrics-operator victoria-metrics-operator 4m1s True Release reconciliation succeeded
Висновок
Як результат, ви досягаєте високо відтворюваного середовища, яке можна надати будь-кому, знаючи, що воно працює саме так, як потрібно. Це, власне, і є метою проєкту Cozystack, який ви можете спробувати абсолютно вільно.
У наступних статтях я розповім про те як підготувати Kubernetes для запуску віртуальних машин та як запускати кластери Kubernetes натисканням кнопки.
Залишайтеся з нами, буде цікаво!
Огляд Kubernetes v1.30
Автори: Amit Dsouza, Frederick Kautz, Kristin Martin, Abigail McCarthy, Natali Vlatko
Швидкий огляд: зміни у Kubernetes v1.30
Новий рік, новий реліз Kubernetes. Ми на половині релізного циклу і маємо чимало цікавих та чудових поліпшень у версії v1.30. Від абсолютно нових можливостей у режимі альфа до вже сталих функцій, які переходять у стабільний режим, а також довгоочікуваних поліпшень — цей випуск має щось для усіх, на що варто звернути увагу!
Щоб підготувати вас до офіційного випуску, ось короткий огляд удосконалень, про які ми найбільше хочемо розповісти!
Основні зміни для Kubernetes v1.30
Структуровані параметри для динамічного розподілу ресурсів (KEP-4381)
Динамічний розподіл ресурсів було додано до Kubernetes у версії v1.26 у режимі альфа. Він визначає альтернативу традиційному API пристроїв для запиту доступу до ресурсів сторонніх постачальників. За концепцією, динамічний розподіл ресурсів використовує параметри для ресурсів, що є абсолютно непрозорими для ядра Kubernetes. Цей підхід створює проблему для Cluster Autoscaler (CA) чи будь-якого контролера вищого рівня, який повинен приймати рішення для групи Podʼів (наприклад, планувальник завдань). Він не може симулювати ефект виділення чи звільнення заявок з плином часу. Інформацію для цього можуть надавати лише драйвери DRA сторонніх постачальників.
Структуровані параметри для динамічного розподілу ресурсів — це розширення оригінальної реалізації, яке розвʼязує цю проблему, створюючи фреймворк для підтримки параметрів заявок, що є більш прозорими. Замість обробки семантики всіх параметрів заявок самостійно, драйвери можуть керувати ресурсами та описувати їх, використовуючи конкретну "структуровану модель", заздалегідь визначену Kubernetes. Це дозволить компонентам, які обізнані з цією "структурованою моделлю", приймати рішення щодо цих ресурсів без залучення зовнішнього контролера. Наприклад, планувальник може швидко обробляти заявки без зайвої комунікації з драйверами динамічного розподілу ресурсів. Робота, виконана для цього релізу, зосереджена на визначенні необхідного фреймворку для активації різних "структурованих моделей" та реалізації моделі "пойменованих ресурсів". Ця модель дозволяє перераховувати окремі екземпляри ресурсів та, на відміну від традиційного API пристроїв, додає можливість вибору цих екземплярів індивідуально за атрибутами.
Підтримка своп-памʼяті на вузлах (KEP-2400)
У Kubernetes v1.30 підтримка своп-памʼяті на вузлах Linux отримує значущі зміни в способі її функціонування, з основним акцентом на покращенні стабільності системи. В попередніх версіях Kubernetes функція NodeSwap
була типово вимкненою, а при увімкненні використовувала поведінку UnlimitedSwap
. З метою досягнення кращої стабільності, поведінка UnlimitedSwap
(яка може компрометувати стабільність вузла) буде видалена у версії v1.30.
Оновлена, все ще бета-версія підтримки своп на вузлах Linux буде стандартно доступною. Однак типовою поведінкою буде запуск вузла в режимі NoSwap
(а не UnlimitedSwap
). У режимі NoSwap
kubelet підтримує роботу на вузлі, де активний простір своп, але Podʼи не використовують жодного page-файлу. Для того, щоб kubelet працював на цьому вузлі, вам все ще потрібно встановити --fail-swap-on=false
. Однак велика зміна стосується іншого режиму: LimitedSwap
. У цьому режимі kubelet фактично використовує page-файл на вузлі та дозволяє Podʼам виділяти деяку частину їхньої віртуальної памʼяті. Контейнери (і їхні батьківські Podʼи) не мають доступу до своп поза їхнім обмеженням памʼяті, але система все ще може використовувати простір своп, якщо він доступний.
Група Kubernetes Node (SIG Node) також оновить документацію, щоб допомогти вам зрозуміти, як використовувати оновлену реалізацію, на основі відгуків від кінцевих користувачів, учасників та широкої спільноти Kubernetes.
Для отримання додаткових відомостей про підтримку своп на вузлах Linux в Kubernetes, прочитайте попередній пост блогу чи документацію про своп на вузлах.
Підтримка просторів імен користувачів в Pod (KEP-127)
Простори імен користувачів — це функція лише для Linux, яка краще ізолює Podʼи для запобігання або помʼякшення кількох важливих CVEs із високим/критичним рейтингом, включаючи CVE-2024-21626, опубліковану у січні 2024 року. У Kubernetes 1.30 підтримка просторів імен користувачів переходить у бета-версію і тепер підтримує Podʼи з томами та без них, власні діапазони UID/GID та багато іншого!
Конфігурація структурованої авторизації (KEP-3221)
Підтримка конфігурації структурованої авторизації переходить у бета-версію та буде типово увімкненою. Ця функція дозволяє створювати ланцюги авторизації з кількома вебхуками із чітко визначеними параметрами, які перевіряють запити в певному порядку та надають деталізований контроль — такий, як явна відмова у випадку невдач. Використання конфігураційного файлу навіть дозволяє вказати правила CEL для попередньої фільтрації запитів, перш ніж вони будуть відправлені до вебхуків, допомагаючи вам запобігти непотрібним викликам. Сервер API також автоматично перезавантажує ланцюг авторизатора при зміні конфігураційного файлу.
Вам необхідно вказати шлях до конфігурації авторизації, використовуючи аргумент командного рядка --authorization-config
. Якщо ви хочете продовжувати використовувати аргументи командного рядка замість конфігураційного файлу, вони продовжать працювати як є. Щоб отримати доступ до нових можливостей вебхуків авторизації, таких як кілька вебхуків, політика невдачі та правила попередньої фільтрації, перейдіть до використання параметрів у файлі --authorization-config
. З версії Kubernetes 1.30 формат конфігураційного файлу є бета-рівнем, і потрібно вказувати лише --authorization-config
, оскільки feature gate вже увімкнено. Приклад конфігурації із всіма можливими значеннями наведено в документації з авторизації. Докладніше читайте в документації з авторизації.
Автомасштабування Podʼів на основі ресурсів контейнера (KEP-1610)
Горизонтальне автомасштабування Podʼів на основі метрик ContainerResource
перейде у стабільний стан у версії v1.30. Це нова функціональність для HorizontalPodAutoscaler дозволяє налаштовувати автоматичне масштабування на основі використання ресурсів для окремих контейнерів, а не загального використання ресурсів для всіх контейнерів у Podʼіві. Докладні відомості можна знайти у нашій попередній статті або в метриках ресурсів контейнера.
CEL для керування допуском (KEP-3488)
Інтеграція Common Expression Language (CEL) для керування допуском у Kubernetes вводить більш динамічний та виразний спосіб оцінки запитів на допуск. Ця функція дозволяє визначати та застосовувати складні, деталізовані політики безпосередньо через API Kubernetes, підвищуючи безпеку та здатність до управління без втрати продуктивності чи гнучкості.
Додавання CEL до керування допуском у Kubernetes дає адміністраторам кластерів можливість створювати складні правила, які можуть оцінювати вміст API-запитів на основі бажаного стану та політик кластера, не вдаючись до вебхуків, які використовують контролери доступу. Цей рівень контролю є важливим для забезпечення цілісності, безпеки та ефективності операцій у кластері, роблячи середовища Kubernetes більш надійними та адаптованими до різних сценаріїв використання та вимог. Для отримання докладної інформації щодо використання CEL для керування допуском дивіться документацію API для ValidatingAdmissionPolicy.
Ми сподіваємося, що ви так само нетерпляче чекаєте на цей випуск, як і ми. Стежте за блогом, щоб дізнатись про офіційний випуск через кілька тижнів, де буде представлено ще більше відомостей!