DevOps для новачків: базові знання та практики

Усі статті, обговорення, новини про DevOps — в одному місці. Підписуйтеся на DOU | DevOps!

Усім привіт, мене звати Михайло Хоменко, я DevOps Engineer в P2H, і у цьому матеріалі вирішив поділитися основами про DevOps для тих, хто хоче розібратись в темі та зрозуміти, що це, які основні концепції напряму та чим він може бути корисним.

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

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

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

Що таке DevOps

DevOps — спосіб розробки та впровадження програмного забезпечення, який поєднує розробку (Development) та експлуатацію (Operations). Він охоплює не тільки розробку, але і тестування, розгортання, моніторинг та підтримку програмного забезпечення.

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

Для чого потрібен DevOps

Основна мета DevOps — це поєднання розробки програмного забезпечення та його ефективної і надійної доставки до користувачів. Для досягнення цієї мети DevOps вирішує наступні задачі:

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

З чого почати: контейнери та Docker

Задля практики DevOps рекомендується звернути увагу на застосування контейнерів.

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

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

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

Контейнери VS Віртуальні машини

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

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

Гуглимо далі і натрапляємо на ще більше технічних деталей по Docker:

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

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

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

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

Як приклад, запустімо локальний вебсервер nginx. Для цього нам потрібно описати Docker Desktop, що саме ми хочемо запустити. Ми створюємо папку, наприклад, «nginx», і в ній файл з назвою «compose-dev.yaml» з наступним вмістом:

version: '3'

services:
  nginx:
    image: nginx
    ports:
    - 8080:80

Під директивою services ми перераховуємо контейнери, які ми хочемо запустити. Їхні імена можуть бути будь-якими, але логічно давати сервісам імена згідно з їхнім призначенням. У цьому випадку у нас є тільки один контейнер — nginx. Цей контейнер повинен бути запущений з образу nginx (image: nginx). У загальному випадку, назва образу вказується у вигляді repository/image:tag, де repository — це місце, з якого Docker завантажує образ, а tag — це, іншими словами, версія образу.

Якщо repository і tag пропущені, це означає, що образ буде взятий з останньої версії та завантажений з DockerHub, найпопулярнішого місця зберігання образів. Згадаємо тут ще одну директиву — ports. Вона дозволяє звертатися до портів контейнерів (які запускаються у власній мережі) через порти на локальній машині (localhost). Зліва — порт на локальній машині, справа — порт контейнера. Таким чином, за адресою localhost:8080 відповість процес контейнера, який слухає на порту 80, тобто вебсервер.

Директив у файлі може бути ще багато, з повним списком можна ознайомитися на Compose file version 3 reference.

Такий файл — це все, що нам потрібно, щоб запустити nginx. Відкриваємо Docker Desktop, вибираємо Dev Environments та створюємо нове середовище.

В «Choose source» виберіть «Local directory» та вкажіть директорію, в якій було створено файл «compose-dev.yaml».

Docker Desktop завантажить останній образ nginx з DockerHub (або знайде образ на вашому комп’ютері, якщо він був завантажений раніше) та запустить контейнер на його основі.

Натиснувши на запущений контейнер, можна буде побачити його логи. Вони оновлюються в режимі реального часу, тому якщо ми спробуємо, наприклад, відкрити неіснуючий шлях (localhost:8080/nosuchpath, цей факт одразу буде відображений в лозі nginx:

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

Тепер спробуємо запустити трохи складніший приклад. З метою спрощення поточне Dev Environment видалимо та створимо нове на основі іншого файлу «compose-dev.yaml»:

version: '3'

services:

  wordpress:
    image: wordpress
    restart: always
    depends_on:
      - mysql
    ports:
      - 8080:80
    environment:
      WORDPRESS_DB_HOST: mysql
      WORDPRESS_DB_USER: exampleuser
      WORDPRESS_DB_PASSWORD: examplepass
      WORDPRESS_DB_NAME: exampledb
    volumes:
      - wordpress:/var/www/html

  mysql:
    image: mysql
    restart: always
    environment:
      MYSQL_DATABASE: exampledb
      MYSQL_USER: exampleuser
      MYSQL_PASSWORD: examplepass
      MYSQL_ROOT_PASSWORD: '1'
    volumes:
      - db:/var/lib/mysql

volumes:
  wordpress:
  db:

Цей файл взятий з DockerHub WordPress і трохи змінений: ROOT_PASSWORD = 1 і використовується остання версія MySQL.

Зберігати логіни та паролі у тексті, звичайно, не рекомендується. Зазвичай їх зберігають у спеціальних місцях для зберігання секретів (наприклад, змінні Gitlab CI/CD, Hashicorp Vault тощо) та використовують під час деплою. Принаймні, секрети повинні бути винесені в окремий файл, що ми й покажемо далі, але наразі залишимо так.

Сам файл порівняно з першим має декілька ускладнень:

  • додана директива depends_on, щоб запустити WordPress після MySQL. При цьому Docker не буде чекати, доки MySQL повністю запуститься. Просто спочатку запуститься один контейнер, потім інший;
  • креди MySQL root та ще одного користувача, так само як і база даних, задана у вигляді environment variables. Зрозуміло, що однакові бази даних, імена користувачів та паролі повинні бути задані для обох контейнерів, тільки назви змінних відрізняються. Використовувані змінні описані в DockerHub WordPress;
  • додані volumes. Вони дають можливість зберігати деякі файли поза контейнером, просто мапити їх туди. Без них всі зміни всередині контейнерів будуть зникати. Так влаштовані контейнери — вони за замовчуванням не зберігають зроблені в них зміни. А тут ми кажемо, що все, що змінюється в файлах WordPress та базі MySQL під час роботи контейнерів, буде зберігатися й після їх зупинки/ рестарту.

Важливий момент — шлях до mysql-хосту вказаний як WORDPRESS_DB_HOST=mysql.

mysql — це ім’я сервісу mysql у рамках файлу compose-dev.yaml. Назвали б сервіс db, треба було б і WORDPRESS_DB_HOST, і в depends_on поміняти на db.

Тепер запустимо Dev Environment на основі вже нового файлу, відкриємо у браузері localhost:8080 та побачимо вікно ініціалізації Wordpress:

Проініціалізуємо Wordpress, ввівши потрібні дані, зокрема логін та пароль для адмінки.

Змінивши що-небудь у розділі Pages, і після цього рестартувавши контейнер з Dev Environments, можна переконатися, що внесені зміни зберігаються.

Ще трохи ускладнимо приклад: винесемо всі креди в окремий файл і додамо контейнер з phpMyAdmin. Декілька Dev Environments можуть жити поруч один з одним, проте порт 8080 може бути зайнятий тільки одним з них, для інших потрібно порт localhost змінювати.

Для простоти ми видалимо поточний Environment та створимо новий, використовуючи наступну конфігурацію compose-dev.yaml:

version: '3'

services:

  wordpress:
    image: wordpress
    restart: always
    depends_on:
      - mysql
    ports:
      - 8080:80
    env_file:
      - local.env
    volumes:
      - wordpress:/var/www/html

  mysql:
    image: mysql
    restart: always
    env_file:
      - local.env
    volumes:
      - db:/var/lib/mysql

  phpmyadmin:
    image: phpmyadmin
    restart: always
    depends_on:
      - mysql
    ports:
      - 8081:80
    env_file:
      - local.env

volumes:
  db:
  wordpress:

Бачимо, що додався контейнер phpMyAdmin і змінні оточення читаються з файлу local.env такого змісту:

WORDPRESS_DB_HOST=mysql
WORDPRESS_DB_USER=exampleuser
WORDPRESS_DB_PASSWORD=examplepass
WORDPRESS_DB_NAME=exampledb

MYSQL_DATABASE=exampledb
MYSQL_USER=exampleuser
MYSQL_PASSWORD=examplepass
MYSQL_ROOT_PASSWORD='1'

PMA_HOST=mysql
PMA_USER=root
PMA_PASSWORD='1'

Нагадаємо, що зберігати такий файл у репозиторії не потрібно, його навіть варто додати до .gitignore. Тоді локально він читатиметься, а при деплої, наприклад, буде формуватися автоматично з секретів Gitlab.

Після запуску Dev Environments та ініціалізації Wordpress за адресою localhost:8080, у phpMyAdmin консолі за адресою localhost:8081 можна побачити базу та таблиці Wordpress:

У прикладах вище ми використовували дефолтний Wordpress, доступний з коробки (з образу), але хотілося б мати свій кастомізований, та ще й мати можливість його змінювати.

Завантажимо Wordpress з сайту. Створимо окрему папку, скажімо, demo-wordpress. Розпакуємо в нього архів із Wordpress. Поміняємо щось усередині папки wordpress/, припустимо, з wordpress/wp-content/plugins приберемо дефолтні плагіни та покладемо плагін classic-editor.

compose-dev.yaml будемо використовувати той самий, тільки з двома невеликими змінами:

  1. заберемо використання volumes з wordpress-container, прибравши секцію volumes;
  2. як образ для wordpress вкажемо свій образ, mywordpress:v1.
version: '3'

services:

  wordpress:
    image: mywordpress:v1
    restart: always
    depends_on:
      - mysql
    ports:
      - 8080:80
    env_file:
      - local.env

  mysql:
    image: mysql
…

Чому саме mywordpress:v1 і чим він відрізняється від звичайного образу wordpress? Ім’я у нього справді довільне, як і версія. Бажано тільки, щоб ім’я образу якось відповідало застосунку у ньому. А ось чим відрізняється від стандартного — так це тим, що веб-каталог /var/www/html у ньому замінений нашим, з кастомізованим вище плагіном.

І як нам такий образ отримати у результаті? Просто. Створюємо файлик з ім’ям Dockerfile:

FROM wordpress

COPY ./wordpress /var/www/html

Загадкові слова FROM і COPY за змістом зрозумілі — отримуємо наш образ з образу wordpress шляхом копіювання нашої локальної папки wordpress/ в образ /var/www/html.

Переконайтеся, що вміст папки demo-wordpress виглядає так:

wordpress/
compose-dev.yaml
Dockerfile
local.env

Описавши, що треба зробити, власне, робимо (крапка в кінці — must have).

$ docker build -t mywordpress:v1 .

Тепер, якщо ви створите новий Dev Environment, вже використовуватиметься створений вами wordpress-образ.

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

Припустимо, наш репозиторій зберігається на Gitlab. Тоді, щоб пояснити Gitlab, що потрібно зробити після пуша в репозиторій, потрібно створити YAML-файл з ім’ям .gitlab-ci.yml і наступною структурою:

stages: # Етапи
- stage 1
- stage 2

# Задачі, які треба зробити на кожному етапі
Job 1:
  stage: stage 1
  script:
  - bash command
  - …

Job 2:
  stage: stage 2
  script:
  - bash command
  - …

Якщо дуже коротко, оголошуємо етапи складання у розділі stages і завдання (jobs) кожному з етапів. Конкретні кроки кожного із завдань описуються у секціях scripts.

Простий приклад .gitlab-ci.yml:

stages:
  - hello


Say hello:
  stage: hello
  script:
    - echo Hello from pipeline

Після пушу змін до репозиторію, пайплайн привітається з нами :)

Ми не розглядатимемо пристрій CI/CD, ранери та інше цього разу, тільки продемонструємо ще й процес складання образу, про який говорилося вище.

Робочий файл .gitlab-ci.yml вже для складання виглядає так:

image: docker


services:
  - docker:dind


variables:
  IMAGE: $CI_REGISTRY_IMAGE:$CI_COMMIT_SHORT_SHA


stages:
  - build


Build Docker image:
  stage: build
  script:
    - docker build -t $IMAGE .
    - echo $CI_REGISTRY_PASSWORD | docker login -u $CI_REGISTRY_USER $CI_REGISTRY --password-stdin
    - docker push $IMAGE

Без деталей тут запускається (внизу) команда docker build, яка збирає образ і потім пушить його в Gitlab-repository, звідки він може бути взятий вже для подальшого деплою.

На жаль, обсяг статті не дозволяє описати тут і деплой. Інші нові елементи (image, services, variables) потрібні, щоб була можливість зібрати образ.

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


Кожна підписка на наш DevOps Podcast поліпшує настрій всій команді. Підписуйтесь :)

👍ПодобаєтьсяСподобалось22
До обраногоВ обраному12
LinkedIn
Дозволені теги: blockquote, a, pre, code, ul, ol, li, b, i, del.
Ctrl + Enter
Дозволені теги: blockquote, a, pre, code, ul, ol, li, b, i, del.
Ctrl + Enter
Як приклад, запустімо локальний вебсервер nginx. Для цього нам потрібно описати Docker Desktop, що саме ми хочемо запустити. Ми створюємо папку, наприклад, «nginx», і в ній файл з назвою «compose-dev.yaml» з наступним вмістом:

version: ’3′

services:
nginx:
image: nginx
ports:
— 8080:80

А навіщо створювати Docker Compose файл, якщо можна просто запустити команду: docker run -p 8080:80 nginx

Можна й run. Але якщо треба вказати не лише порт, а й волуми, змінні або заранити декілька контейнерів водночас, то використання command line стає незручним. До того ж, наявність файлу дає змогу не вишукувати в історії шелла, як же ж само той контейнер був запущений востаннє.

Ви у вашому пості розбираєте конкретне завдання — запустити nginx. Один контейнер, не три, не сто, а саме один.
І якщо ви написали ваш пост для новачків, то найрозумніше було використовувати саме docker run, а не городити город із Docker Compose.

nginx — це тільки перший пріклад, далі там йде про два й про три контейнери. Тому з самого початку використовується compose.

І якщо ви написали ваш пост для новачків, то найрозумніше було використовувати саме docker run,

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

Я б все ж таки почав з основ, будь який девопс у сучасному розумінні базується на людині(команді) інженерів, з нормальними скілами системного інженера (сісадміна) з усіма звідси витікаючими.
Тут можна багато ломати списи, щось доказувати. але нормальна автоматизація базується не лише на докері, або кубері. Банально — міграція AWS EKS з 1.22 на 1.23 вимагає знання не лише контейнерів, а й розуміння що таке AWS та які тулзи він має, як воно все працює, що таке ролі, як їх додавати, міняти, які вони є та для чого юзаються.
Додамо сюди що для автоматизації потрібно юзати Infrastructure as Code і тут починається пекло з teraform та його модулями.
Автоматизувати зборку того ж образа докеру — декілька підходів, стандартний Jenkins (у мене) або Code Build / Image Build / Code Deploy
Автоматизувати викатку всього цього у кластер — ArgoCD + helmfile / kustomize
Все це описати у terraform, додати чарти/маніфести/пайплайни і по фінішу виходить що для базових речей починається реальне пекло і це лише верхній рівень, додати сюди ще конфігурацію VPC, розділення оточень, пірінг, бази sql/no sql і т.д — вийде що devops далеко за рамками лише контейнерів, а на проді default конціги не завжди працюють нормально.

DevOps для новачків: базові знання та практики

це вже має бути після базових знань стосовно OSI та що відбувається на кожному рівні, та з базовими речами стосовно софта умовного LAMP(LNMP) та з додаванням postgresql/redis/mongo/elastic. Багато хто такий підход не підтримує, але якщо дивитись ширше, дещо складно буде розгортати знання у хмарах, не розуміючи що таке мережа, як вона працює, що таке маршрутизація, як elastic змінює данні, що там по індексах і т.д....

PS стаття норм і за неї дякую — як для розробника, який хоче трохи опанувати новий підхід, для новачка у напрямку devops імхо з іншого починати потрібно.

Дійсно, матеріал призначений більш для розробників — щоб трохи зрозуміти, що ті всі девопси роблять. Згоден з тим, що вже для девопсів-початківців треба сперше опанувати как мінімум Linux cli та TCP/IP, а потім вже йти до контейнерів і клаудів.

Якщо ми в команді самі пишемо Docker images та маніфести Kubernetes, то ми теж трохи DevOps?

Надіюсь вам докидують хоч 30% від девопсової компенсації до вашої зарплати розробника? :)

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

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

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

Я працював на проекті, де CI/CD та багато чого іншого, як копією PyPi-репозиторією займались не девопси, а окрема команда — ріленги. Секурністю — нетсеки зі своїми сканерами хостів, пакетів та бібліотек, налаштуванням мереж — нетопси, на якій платформі що крутити — платопси, моніторинг — монопси і так далі. Але це були не сучасні клауди.

На великих проектах адекватних компаній декомпозиція ролей та обовязків це звична річ, так як технології розвиваються та ускладнюються, на менших це інколи бажання мати інженера 5в1 за смішні гроші, а якщо ще девопси в доковідні часи ганяли чаї на кухні по пів дня, а на свої задачі менеджменту розказували, що розробник може це сам зробити, а він лише напише статтю на конфлуєнсі, щоб далі ганяти чаї і нічого не робити (або брати другий фултайм чи парттайм), то взагалі ідеально :)

Для запуску докер на вінді... Ой, ти користуешся VirtualBox або vagrant?) То все, забудь))))

І це десь тільки одна тисячна того, що зараз потрібно знати навіть джуну девопсу

Підписатись на коментарі