Найкращі практики Kubernetes. Створення невеликих контейнерів

Найкращі практики Kubernetes. Створення невеликих контейнерів

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

Найкращі практики Kubernetes. Створення невеликих контейнерів

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

Крім того, більшість образів у Docker використовують для базового образу Debian або Ubuntu, і хоча це забезпечує відмінну сумісність та легку адаптацію (файл Docker займає всього два рядки коду), базові образи здатні додати сотні мегабайтів додаткового навантаження у ваш контейнер. Наприклад, простий файл node.js програми Go "hello-world" займають близько 700 мегабайт, при тому, що розмір власне вашої програми складає лише кілька мегабайтів.

Найкращі практики Kubernetes. Створення невеликих контейнерів

Таким чином, все це додаткове навантаження - марна витрата цифрового простору і відмінна схованка для вразливостей і помилок у системі безпеки. Тому розглянемо два способи зменшення розміру образу контейнера.

Перший – це використання базових образів невеликого розміру, другий – використання шаблону проектування Builder Pattern. Використання менших базових зображень, ймовірно, найпростіший спосіб зменшення розміру контейнера. Швидше за все, ваша мова або стек, які ви використовуєте, забезпечує оригінальний образ програми набагато меншого розміру, ніж за замовчуванням. Погляньмо на наш контейнер node.js.

Найкращі практики Kubernetes. Створення невеликих контейнерів

За замовчуванням у Docker розмір базового образу node: 8 дорівнює 670 МБ, а розмір node: 8-alpine складає всього 65 МБ, тобто в 10 разів менше. Використовуючи менший базовий образ Alpine, ви суттєво скоротите розмір вашого контейнера. Alpine це невеликий і легкий дистрибутив Linux, який дуже популярний серед користувачів Docker, тому що він сумісний з багатьма додатками, зберігаючи при цьому невеликий розмір контейнерів. На відміну від стандартного образу Docker "node", "node:alpine" видаляє безліч службових файлів і програм, залишаючи тільки ті, яких достатньо для запуску вашої програми.

Щоб перейти до меншого базового образу, просто оновіть файл Docker для початку роботи з новим базовим зображенням:

Найкращі практики Kubernetes. Створення невеликих контейнерів

Тепер, на відміну від старого образу onbuild, вам потрібно скопіювати свій код у контейнер і встановити будь-які залежності. У новому файлі Docker починається з образу node:alpine, потім створює каталог для коду, встановлює залежності за допомогою менеджера пакетів NPM і, нарешті, запускає server.js.

Найкращі практики Kubernetes. Створення невеликих контейнерів

За допомогою цього поновлення виходить контейнер в 10 разів меншого розміру. Якщо ваша мова програмування або стек не має функції зменшення базового образу, використовуйте Alpine Linux. Він також надасть можливість повністю керувати вмістом контейнера. Використання базових образів маленького розміру - чудовий спосіб швидкого створення невеликих контейнерів. Але можна досягти ще більшого зменшення за допомогою Builder Pattern.

Найкращі практики Kubernetes. Створення невеликих контейнерів

В інтерпретованих мовах вихідний код спочатку передається інтерпретатору, а потім безпосередньо виконується. У компілюваних мовах вихідний код попередньо перетворюється на скомпільований код. При цьому компіляція часто використовує інструменти, які не потрібні для запуску коду. Це означає, що можна повністю видалити ці інструменти з фінального контейнера. Для цього можна використати Builder Pattern.

Найкращі практики Kubernetes. Створення невеликих контейнерів

Код створюється у першому контейнері та компілюється. Потім скомпільований код упаковується в кінцевий контейнер без компіляторів та інструментів, необхідних компіляції цього коду. Давайте пропустимо через цей процес додаток Go. По-перше, ми перейдемо від образу onbuild до Alpine Linux.

Найкращі практики Kubernetes. Створення невеликих контейнерів

У новому файлі Docker контейнер починається з образу golang: alpine. Потім він створює каталог коду, копіює їх у вихідний код, створює цей вихідний код і запускає додаток. Цей контейнер набагато менше, ніж контейнер onbuild, але він все ще містить компілятор та інші інструменти Go, які насправді нам не потрібні. Тому давайте просто вилучимо скомпільовану програму і покладемо її у свій власний контейнер.

Найкращі практики Kubernetes. Створення невеликих контейнерів

Ви можете помітити щось дивне в файлі Docker: він містить два рядки FROM. Перший розділ з 4-х рядків виглядає так само, як і попередній файл Docker, за винятком того, що він використовує ключове слово AS, щоб дати ім'я цьому етапу. У наступному розділі є новий рядок FROM, що дозволяє розпочати новий образ, при цьому замість образу golang:alpine як базовий образ ми будемо використовувати Raw alpine.

Raw Alpine Linux не має жодних встановлених SSL сертифікатів, що призведе до збою більшості викликів API за протоколом HTTPS, тому давайте встановимо кілька кореневих сертифікатів CA.

А тепер найцікавіше: для копіювання скомпільованого коду з першого контейнера до другого можна просто використовувати команду COPY, розташовану в 5-му рядку другого розділу. Вона скопіює лише один файл програми і не торкнеться службових інструментів Go. Новий багатоступінчастий файл Docker міститиме образ контейнера розміром лише 12 мегабайт при тому, що вихідний образ контейнера становив 700 мегабайт, а це велика різниця!
Таким чином, використання невеликих базових зображень і Builder Pattern – відмінні способи створювати контейнери набагато менших розмірів без великого обсягу роботи.
Можливо, що в залежності від стека програми, існують додаткові способи зменшити розмір образу та контейнера, але чи дійсно маленькі контейнери мають вимірну перевагу? Давайте розглянемо два аспекти, де маленькі контейнери надзвичайно ефективні – це продуктивність та безпека.

Щоб оцінити зростання продуктивності, розглянемо тривалість процесу створення контейнера, вставки його в реєстр (push) та подальшого вилучення звідти (pull). Ви можете побачити, що контейнер меншого розміру має незаперечну перевагу в порівнянні з контейнером більшого розміру.

Найкращі практики Kubernetes. Створення невеликих контейнерів

Docker кешуватиме шари, тому наступні зборки будуть виконуватися дуже швидко. Однак у багатьох системах CI, які використовуються для збирання та тестування контейнерів, шари не кешуються, тому тут є значна економія часу. Як видно, час побудови контейнера великого розміру в залежності від потужності машини становить від 34 до 54 секунд, а при використанні контейнера, зменшеного за допомогою Builder Pattern - від 23 до 28 секунд. Для таких операцій приріст продуктивності складе 40-50%. Тому просто подумайте, скільки разів ви створюєте та тестуєте свій код.

Після того, як контейнер збудований, вам потрібно вставити його образ (push container image) в реєстр контейнерів, щоб потім використовувати у своєму кластері Kubernetes. Рекомендую використовувати реєстр контейнерів Google.

Найкращі практики Kubernetes. Створення невеликих контейнерів

Використовуючи Google Container Registry (GCR), ви сплачуєте лише за «сире» сховище та мережу, а додаткова плата за керування контейнерами не стягується. Це конфіденційно, безпечно та дуже швидко. GCR використовує багато трюків, щоб прискорити операцію pull. Як бачите, вставка образу контейнера Docker Container Image при використанні go:onbuild в залежності від продуктивності комп'ютера займе від 15 до 48с, а та ж операція з контейнером меншого розміру - від 14 до 16с, причому для менш продуктивних машин перевага в швидкості операції збільшується в 3 рази. Для великих машин час приблизно однаковий, так як GCR використовує глобальний кеш для загальної бази зображень, тобто взагалі вам не потрібно їх завантажувати. У комп'ютері малої потужності CPU є вузьким місцем, тому перевага використання малих контейнерів тут набагато відчутніша.

Якщо ви використовуєте GCR, я наполегливо рекомендую використовувати Google Container Builder (GCB) як частину вашої системи збирання.

Найкращі практики Kubernetes. Створення невеликих контейнерів

Як бачите, його використання дозволяє досягти набагато кращих результатів у зменшенні тривалості операції Build+Push, ніж навіть у продуктивної машини – у цьому випадку процес побудови та відправлення контейнерів на хост пришвидшується майже вдвічі. Крім того, щодня ви отримуєте 2 хвилин складання безкоштовно, що у більшості випадків задовольняє потреби створення контейнерів.

Далі йде найважливіша метрика продуктивності - швидкість вилучення, або завантаження контейнерів Pull. І якщо вас не особливо турбує час, що витрачається на операцію push, тривалість процесу pull серйозно впливає на загальну продуктивність системи. Припустимо, що у вас є кластер із трьох вузлів і з одним із них відбувається збій. Якщо ви використовуєте систему керування, наприклад Google Kubernetes Engine, вона автоматично замінить неробочий вузол новим. Однак цей новий вузол буде порожнім, і вам доведеться перетягнути в нього всі ваші контейнери, щоб він почав працювати. Якщо операція pull буде досить довгою, то весь цей час ваш кластер працюватиме з меншою продуктивністю.

Існує багато випадків, коли може статися подібне: це додавання нового вузла до кластера, оновлення вузлів або навіть перемикання на новий контейнер для розгортання. Таким чином, мінімізація часу отримання pull стає ключовим фактором. Незаперечно те, що невеликий контейнер скачується набагато швидше за великий. Якщо ви використовуєте кілька контейнерів у кластері Kubernetes, економія часу може бути дуже суттєвою.

Найкращі практики Kubernetes. Створення невеликих контейнерів

Погляньте на наведене порівняння: операція pull під час роботи з маленькими контейнерами займає в 4-9 разів менше часу залежно від потужності машини, ніж така сама операція з використанням go:onbuild. Використання загальних базових образів контейнерів малого розміру значно прискорює час та швидкість, з якою нові вузли Kubernetes можуть розгортатися та виходити в інтернет.

Давайте розглянемо питання безпеки. Вважається, що контейнери меншого розміру набагато безпечніші за великі, тому що у них менша поверхня атаки. Чи це так насправді? Одна з корисних функцій Google Container Registry полягає у можливості автоматично сканувати ваші контейнери на наявність уразливостей. Кілька місяців тому я створив як onbuild, так і багатоступінчасті контейнери, так що давайте подивимося, чи є там якісь вразливі місця.

Найкращі практики Kubernetes. Створення невеликих контейнерів

Результат приголомшливий: у невеликому контейнері виявлено всього 3 середні вразливості, а у великому - 16 критичних та 376 інших уразливостей. Якщо розглянути вміст великого контейнера, то видно, що більшість проблем безпеки не мають нічого спільного з нашим додатком, а пов'язані з програмами, які ми навіть не використовуємо. Тому коли люди говорять про велику поверхню для атак, вони мають на увазі саме це.

Найкращі практики Kubernetes. Створення невеликих контейнерів

Висновок очевидний: створюйте маленькі контейнери, тому що вони дають реальні переваги у продуктивності та безпеці вашої системи.

Найкращі практики Kubernetes. Організація Kubernetes з простором імен

Небагато реклами 🙂

Дякую, що залишаєтеся з нами. Вам подобаються наші статті? Бажаєте бачити більше цікавих матеріалів? Підтримайте нас, оформивши замовлення або порекомендувавши знайомим, хмарні VPS для розробників від $4.99, унікальний аналог entry-level серверів, який був винайдений нами для Вас: Вся правда про VPS (KVM) E5-2697 v3 (6 Cores) 10GB DDR4 480GB SSD 1Gbps від $19 чи як правильно ділити сервер? (Доступні варіанти з RAID1 і RAID10, до 24 ядер і до 40GB DDR4).

Dell R730xd вдвічі дешевше в дата-центрі Equinix Tier IV в Амстердамі? Тільки в нас 2 х Intel TetraDeca-Core Xeon 2x E5-2697v3 2.6GHz 14C 64GB DDR4 4x960GB SSD 1Gbps 100 ТБ від $199 у Нідерландах! Dell R420 – 2x E5-2430 2.2Ghz 6C 128GB DDR3 2x960GB SSD 1Gbps 100TB – від $99! Читайте про те Як побудувати інфраструктуру корп. класу із застосуванням серверів Dell R730xd Е5-2650 v4 вартістю 9000 євро за копійки?

Джерело: habr.com

Додати коментар або відгук