Вступ для контейнерів, віртуальних машин та Docker

Якщо ви програміст або фахівець, швидше за все, ви, принаймні, чули про Docker: корисний інструмент для упаковки, доставки та запуску програм у “контейнерах”. Важко було б цього не зробити, з усією увагою, яку він отримує в наші дні - як розробників, так і адміністраторів системи. Навіть такі великі собаки, як Google, VMware та Amazon, будують сервіси для його підтримки.

Незалежно від того, чи маєте ви на увазі безпосередній випадок використання Docker, я все одно вважаю важливим зрозуміти деякі фундаментальні поняття, що таке "контейнер" і як він порівнюється з віртуальною машиною (VM). Хоча Інтернет наповнений чудовими посібниками з використання Docker, я не зміг знайти багато концептуальних посібників, зручних для початківців, особливо щодо того, з чого складається контейнер. Тож, сподіваємось, ця публікація вирішить цю проблему :)

Почнемо з розуміння того, що взагалі бувають віртуальні машини та контейнери.

Що таке «контейнери» та «віртуальні машини»?

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

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

Основна різниця між контейнерами та віртуальними машинами полягає в їх архітектурному підході. Давайте розглянемо уважніше.

Віртуальні машини

Віртуальна машина, по суті, є емуляцією реального комп’ютера, який виконує такі програми, як справжній комп’ютер. Віртуальні машини працюють поверх фізичної машини за допомогою «гіпервізора» . Гіпервізор, у свою чергу, працює або на головній машині, або на “голому металі” .

Розпакуємо жаргон:

Гипервизор є частиною програмного забезпечення, вбудованого програмного забезпечення або апаратних засобів, віртуальні машини працюють на вершині. Самі гіпервізори працюють на фізичних комп'ютерах, що називається "хост-машиною" . Хост-машина надає віртуальним машинам ресурси, включаючи оперативну пам'ять і центральний процесор. Ці ресурси розподілені між віртуальними машинами і можуть бути розподілені як вам зручно. Отже, якщо на одній віртуальній машині працює більш ресурсна програма, ви можете виділити їй більше ресурсів, ніж інші віртуальні машини, що працюють на тій самій машині.

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

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

По-перше, розміщений гіпервізор віртуалізації працює в операційній системі хост-машини. Наприклад, на комп’ютері під управлінням OSX поверх цієї ОС може бути встановлена ​​віртуальна машина (наприклад, VirtualBox або VMware Workstation 8). Віртуальна машина не має прямого доступу до апаратного забезпечення, тому вона повинна проходити через основну операційну систему (у нашому випадку, OSX Mac).

Перевага розміщеного гіпервізора полягає в тому, що базове обладнання є менш важливим. Операційна система хоста відповідає за драйвери обладнання замість самого гіпервізора, і тому вважається, що вона має більше «апаратної сумісності». З іншого боку, цей додатковий рівень між апаратним забезпеченням та гіпервізором створює більше накладних витрат на ресурси, що знижує продуктивність віртуальної машини.

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

Після всієї цієї розмови про гіпервізори, ви можете задатися питанням, навіщо нам взагалі потрібен цей додатковий шар "гіпервізора" між ВМ і хост-машиною.

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

Як ви можете бачити на схемі, віртуальні машини пакують віртуальне обладнання, ядро ​​(тобто ОС) та користувацький простір для кожної нової віртуальної машини.

Контейнер

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

За будь-яких цілей та цілей контейнери виглядають як віртуальна машина. Наприклад, вони мають приватний простір для обробки, можуть виконувати команди як root, мають приватний мережевий інтерфейс та IP-адресу, дозволяють користувацькі маршрути та iptable правила, можуть монтувати файлові системи тощо.

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

Ця діаграма показує, що контейнери пакують лише користувальницький простір, а не ядро ​​або віртуальне обладнання, як це робить віртуальна машина. Кожен контейнер отримує власний ізольований користувацький простір, щоб дозволити декілька контейнерів працювати на одній хост-машині. Ми бачимо, що вся архітектура рівня операційної системи спільно використовується між контейнерами. Єдині деталі, які створюються з нуля, - це контейнери та кришки. Саме це робить контейнери такими легкими.

Куди заходить Docker?

Docker - це проект з відкритим кодом, заснований на контейнерах Linux. Він використовує функції ядра Linux, такі як простори імен та групи керування, щоб створювати контейнери поверх операційної системи.

Контейнери далеко не нові; Google використовує власну технологію контейнерів роками. Інші технології контейнерів Linux включають зони Solaris, тюрми BSD та LXC, які існують вже багато років.

То чому Докер раптом набирає пари?

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

2. Швидкість: контейнери Docker дуже легкі та швидкі. Оскільки контейнери - це просто середовища із захищеною середовищем, що працюють на ядрі, вони займають менше ресурсів. Ви можете створити та запустити контейнер Docker за лічені секунди, порівняно з віртуальними машинами, що може зайняти більше часу, оскільки їм щоразу доводиться завантажувати повну віртуальну операційну систему.

3. Docker Hub: Користувачі Docker також отримують вигоду від дедалі багатшої екосистеми Docker Hub, яку ви можете сприймати як «магазин додатків для зображень Docker». Docker Hub має десятки тисяч загальнодоступних зображень, створених спільнотою, які легко доступні для використання. Неймовірно просто шукати зображення, які відповідають вашим потребам, готові до виведення та використання із майже без змін.

4. Модульність та масштабованість: Docker дозволяє легко розбити функціональність вашої програми на окремі контейнери. Наприклад, у вас може бути, що база даних Postgres працює в одному контейнері, а сервер Redis - в іншому, тоді як програма Node.js знаходиться в іншому. За допомогою Docker стало простіше пов’язати ці контейнери разом, щоб створити свою програму, що спростить масштабування або оновлення компонентів самостійно в майбутньому.

І останнє, але не менш важливе: хто не любить кита докера? ;)

Основні концепції Docker

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

Двигун Docker

Механізм Docker - це рівень, на якому працює Docker. Це полегшене середовище виконання та інструментарій, який управляє контейнерами, зображеннями, збірками тощо. Він працює безпосередньо в системах Linux і складається з:

1. Демон Docker, який працює на хост-комп'ютері.

2. Клієнт Docker, який потім зв’язується з Docker Daemon для виконання команд.

3. REST API для віддаленої взаємодії з Docker Daemon.

Клієнт Docker

Клієнт Docker - це те, з чим ви, як кінцевий користувач Docker, спілкуєтесь. Подумайте про це як про інтерфейс користувача для Docker. Наприклад, коли ви робите ...

ви спілкуєтесь із клієнтом Docker, який потім передає ваші інструкції до Docker Daemon.

Docker Daemon

Демон Docker - це те, що насправді виконує команди, надіслані клієнту Docker, - наприклад, створення, запуск та розподіл ваших контейнерів. Docker Daemon працює на хост-машині, але як користувач ви ніколи не спілкуєтеся безпосередньо з Daemon. Клієнт Docker також може працювати на хост-машині, але це не потрібно. Він може працювати на іншій машині та спілкуватися з Docker Daemon, який працює на хост-машині.

Докерфайл

Файл Docker - це місце, де ви пишете інструкції для створення образу Docker. Ці вказівки можуть бути:

  • RUN apt-get y install some-package : для встановлення програмного пакету
  • EXPOSE 8000: виставити порт
  • ENV ANT_HOME / usr / local / apache-ant для передачі змінної середовища

і так далі. Після того, як ви налаштували файл Docker, ви можете використовувати команду docker build, щоб побудувати з нього зображення. Ось приклад файлу Docker:

Зображення Docker

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

Образ Docker будується за допомогою файлу Docker. Кожна інструкція в Dockerfile додає новий "шар" до зображення, шари представляють частину файлової системи зображень, яка або додає шар шарів під ним, або замінює його. Шари є ключем до легкої, але потужної структури Docker. Для цього Docker використовує файлову систему Union:

Файлові системи Union

Docker використовує Union File Systems для створення образу. Ви можете розглядати файлову систему Union як файлову систему, що підлягає накопиченню, тобто файли та каталоги окремих файлових систем (відомих як гілки) можна прозоро накласти, щоб утворити єдину файлову систему.

Вміст каталогів, що мають однаковий шлях у накладених гілках, розглядається як єдиний об’єднаний каталог, що дозволяє уникнути необхідності створювати окремі копії кожного шару. Натомість всі вони можуть отримувати вказівники на один і той же ресурс; коли потрібно змінити певні шари, він створить копію та змінить локальну копію, залишивши оригінал без змін. Ось як файлові системи можуть * виглядати * для запису, фактично не дозволяючи записувати. (Іншими словами, система “copy-on-write”.)

Шаруваті системи пропонують дві основні переваги:

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

2. Сегрегація шарів: Внесення змін відбувається набагато швидше - коли ви змінюєте зображення, Docker розповсюджує оновлення лише до шару, який було змінено.

Томи

Томи - це частина даних контейнера, яка ініціалізується при створенні контейнера. Томи дозволяють зберігати та передавати дані контейнера. Томи даних відокремлені від стандартної файлової системи Union і існують як звичайні каталоги та файли в хост-файловій системі. Отже, навіть якщо ви знищите, оновите або відновите свій контейнер, обсяги даних залишаться недоторканими. Коли ви хочете оновити том, ви вносите зміни до нього безпосередньо. (Як додатковий бонус, обсяги даних можна спільно використовувати та використовувати повторно між кількома контейнерами, що досить акуратно.)

Докерні контейнери

Контейнер Docker, як обговорювалося вище, обертає програмне забезпечення програми у невидиме поле з усім, що потрібно для запуску програми. Сюди входять операційна система, код програми, час виконання, системні інструменти, системні бібліотеки тощо. Контейнери Docker будуються на основі образів Docker. Оскільки зображення доступні лише для читання, Docker додає файлову систему для читання і запису над файловою системою лише для читання зображення, щоб створити контейнер.

Більше того, створюючи контейнер, Docker створює мережевий інтерфейс, щоб контейнер міг розмовляти з локальним хостом, приєднувати доступну IP-адресу до контейнера та виконувати процес, який ви вказали для запуску програми при визначенні зображення.

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

Двічі клацніть на "контейнери"

Фу! Це багато рухомих частин. Мені завжди цікаво було, як насправді реалізується контейнер, тим більше, що навколо контейнера немає жодної абстрактної межі інфраструктури. Після багатого читання все це має сенс, тому ось моя спроба пояснити вам це! :)

Термін "контейнер" насправді є просто абстрактним поняттям, щоб описати, як кілька різних функцій працюють разом, щоб візуалізувати "контейнер". Давайте пройдемося по них дуже швидко:

1) Простори імен

Простіри імен надають контейнерам власний вигляд базової системи Linux, обмежуючи те, що контейнер може бачити та мати до нього доступ. Коли ви запускаєте контейнер, Docker створює простори імен, які буде використовувати конкретний контейнер.

У ядрі є кілька різних типів просторів імен, якими Docker використовує, наприклад:

a. NET: Надає контейнер із власним видом мережевого стека системи (наприклад, власні мережеві пристрої, IP-адреси, таблиці маршрутизації IP, каталог / proc / net, номери портів тощо).

b. PID: PID - це ідентифікатор процесу. Якщо ви коли-небудь запускали ps aux у командному рядку, щоб перевірити, які процеси працюють у вашій системі, ви побачите стовпець з назвою “PID”. Простір імен PID надає контейнерам власний перегляд процесів, з якими вони можуть переглядати та взаємодіяти, включаючи незалежний init (PID 1), який є “родоначальником усіх процесів”.

c. MNT: надає контейнеру власний вигляд “кріплень” в системі. Отже, процеси в різних просторах імен монтування мають різний вигляд ієрархії файлової системи.

d. UTS: UTS розшифровується як UNIX Timesharing System. Це дозволяє процесу ідентифікувати системні ідентифікатори (тобто ім'я хоста, ім'я домену тощо). UTS дозволяє контейнерам мати своє власне ім'я хосту та доменне ім'я NIS, яке не залежить від інших контейнерів та хост-системи.

e. IPC: IPC розшифровується як InterProcess Communication. Простір імен IPC відповідає за ізоляцію ресурсів IPC між процесами, що виконуються всередині кожного контейнера.

f. КОРИСТУВАЧ: Цей простір імен використовується для ізоляції користувачів у кожному контейнері. Він функціонує, дозволяючи контейнерам мати різний вигляд діапазонів uid (ідентифікатор користувача) та gid (ідентифікатор групи), порівняно з основною системою. Як результат, uid і gid процесу можуть бути різними всередині і за межами простору імен користувачів, що також дозволяє процесу мати непривілейованого користувача за межами контейнера, не жертвуючи привілеєм root всередині контейнера.

Docker використовує ці простори імен разом, щоб ізолювати та розпочати створення контейнера. Наступна особливість називається контрольними групами.

2) Контрольні групи

Контрольні групи (також звані cgroups) - це функція ядра Linux, яка виділяє, визначає пріоритети та враховує використання ресурсів (ЦП, пам’ять, дисковий ввід / вивід, мережа тощо) набору процесів. У цьому сенсі cgroup гарантує, що контейнери Docker використовують лише ті ресурси, які їм потрібні, і, якщо потрібно, встановлює обмеження щодо ресурсів, які контейнер * може використовувати *. Групи також гарантують, що один контейнер не вичерпує жодного з цих ресурсів і не збиває всю систему.

Нарешті, об’єднання файлових систем - це ще одна функція, яку використовує Docker:

3) Ізольована файлова система Union:

Описано вище в розділі Docker Images :)

Це насправді все, що є в контейнері Docker (звичайно, диявол в деталях реалізації - наприклад, як керувати взаємодіями між різними компонентами).

Майбутнє Docker: Docker та VM будуть співіснувати разом

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

Наприклад, якщо вам потрібно запустити кілька програм на декількох серверах, можливо, має сенс використовувати віртуальні машини. З іншого боку, якщо вам потрібно запустити багато * копій * однієї програми, Docker пропонує деякі вагомі переваги.

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

Безпека також викликає занепокоєння щодо контейнерів Docker - оскільки контейнери мають одне і те ж ядро, бар’єр між контейнерами стає тоншим. Хоча повна віртуальна машина може надсилати гіпервиклики лише хост-гіпервізору, контейнер Docker може здійснювати системні виклики до ядра хосту, що створює більшу площу поверхні для атаки. Коли безпека особливо важлива, розробники, швидше за все, вибирають віртуальні машини, які ізольовані абстрактним обладнанням, що значно ускладнює втручання один в одного.

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

Висновок

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

Як завжди, напишіть мені рядок у коментарях, якщо я допустив помилки чи можу вам допомогти! :)