Модуль 1.1: Інфраструктура як код
Складність:
[СЕРЕДНЯ]— Базова концепціяЧас на проходження: 30-35 хвилин
Передумови: Базові навички роботи з командним рядком
Що ви зможете зробити
Розділ «Що ви зможете зробити»Після завершення цього модуля ви зможете:
- Пояснити, що таке Інфраструктура як код (Infrastructure as Code, IaC) і чому вона замінила ручне налаштування серверів
- Порівняти інструменти IaC (Terraform, Ansible, Pulumi) та пояснити, коли використовувати кожен з них
- Написати просту декларативну конфігурацію та пояснити, чим вона відрізняється від скрипта
- Визначити антипатерни IaC (clickops, імперативні скрипти для декларативних задач, дрейф конфігурації)
Чому це важливо
Розділ «Чому це важливо»У 2012 році Knight Capital Group втратила 460 мільйонів доларів лише за 45 хвилин. Чому? Технічний спеціаліст вручну розгорнув нове програмне забезпечення на 7 з 8 серверів, забувши про восьмий. Ця невідповідність призвела до того, що система почала агресивно купувати дорого і продавати дешево. Одна помилка при ручному налаштуванні знищила багатомільярдну компанію.
До появи Інфраструктури як код (IaC) налаштування серверів було ручним процесом, схильним до помилок, який неможливо було точно відтворити. “На моїй машині працює” було типовим виправданням. IaC змінив усе: інфраструктура стала придатною для версіонування, тестування та повторення. Розуміння IaC є критично важливим, оскільки сам Kubernetes є системою IaC.
Зупиніться та подумайте: Як ваша нинішня організація відстежує зміни в інфраструктурі? Якби ваш основний дата-центр зник сьогодні, чи змогли б ви відновити його з репозиторію, чи покладалися б на чиюсь пам’ять?
Старий шлях: ClickOps
Розділ «Старий шлях: ClickOps»Уявіть собі: 2005 рік. Вам потрібно налаштувати вебсервер.
Ручний процес:1. Замовлення фізичного сервера (2-4 тижні)2. Очікування, поки дата-центр встановить його в стійку (1 тиждень)3. Підключення через SSH та встановлення пакетів4. Налаштування шляхом редагування файлів5. Надія, що ви пам'ятаєте, що саме зробили6. Молитва, щоб нічого не зламалося
Документація: "Запитайте Дейва, це він налаштовував"Проблеми:
- Немає записів про те, що було зроблено
- Неможливо відтворити налаштування
- Різні “ідентичні” сервери поводяться по-різному
- Дейв іде у відпустку — все ламається
Інфраструктура як код
Розділ «Інфраструктура як код»IaC означає опис інфраструктури у файлах, які можна версіонувати, поширювати та виконувати.
┌─────────────────────────────────────────────────────────────┐│ ІНФРАСТРУКТУРА ЯК КОД │├─────────────────────────────────────────────────────────────┤│ ││ Традиційно: ││ ┌─────────┐ ┌─────────┐ ┌─────────┐ ││ │ Людина │ ───► │ Консоль │ ───► │ Сервер │ ││ │ │ │ (GUI) │ │ │ ││ └─────────┘ └─────────┘ └─────────┘ ││ ││ З IaC: ││ ┌─────────┐ ┌─────────┐ ┌─────────┐ ││ │ Код │ ───► │Інструмент│───► │ Сервер │ ││ │ (файли) │ │(Terraform)│ │ │ ││ └─────────┘ └─────────┘ └─────────┘ ││ │ ││ ▼ ││ ┌─────────┐ ││ │ Git │ Контроль версій, можливість огляду, повторення ││ └─────────┘ ││ │└─────────────────────────────────────────────────────────────┘Ключові принципи
Розділ «Ключові принципи»1. Декларативний чи імперативний
Розділ «1. Декларативний чи імперативний»Імперативний (Як):"Встановити nginx, потім відредагувати /etc/nginx/nginx.conf,потім перезапустити nginx"
Декларативний (Що):"Я хочу, щоб nginx працював з цією конфігурацією"Декларативний підхід є кращим — ви описуєте бажаний стан, а інструмент сам визначає, як його досягти.
2. Ідемпотентність
Розділ «2. Ідемпотентність»Виконання одного і того ж коду кілька разів дає однаковий результат:
# Запуск цього 10 разів створить 10 серверів (ПОГАНО)create_server web-1
# Запуск цього 10 разів гарантує, що існує 1 сервер (ДОБРЕ)ensure_server_exists web-1Зупиніться та подумайте: Якщо ви запустите імперативний bash-скрипт, який двічі створює користувача, він, швидше за все, видасть фатальну помилку вдруге, бо користувач уже існує. Що зробить ідемпотентна декларативна система?
3. Контроль версій
Розділ «3. Контроль версій»git log --oneline infrastructure/abc123 Add production database replicadef456 Increase web server count to 5ghi789 Initial infrastructure setup
# "Хто змінив прод?" — Просто перевірте git blameЛандшафт інструментів IaC
Розділ «Ландшафт інструментів IaC»┌─────────────────────────────────────────────────────────────┐│ КАТЕГОРІЇ ІНСТРУМЕНТІВ IaC │├─────────────────────────────────────────────────────────────┤│ ││ PROVISIONING (Створення інфраструктури) ││ ├── Terraform (хмаро-незалежний, найпопулярніший) ││ ├── Pulumi (реальні мови програмування) ││ ├── CloudFormation (тільки AWS) ││ └── ARM Templates (тільки Azure) ││ ││ CONFIGURATION (Налаштування існуючих машин) ││ ├── Ansible (без агентів, на базі SSH) ││ ├── Chef (Ruby DSL, на базі агентів) ││ ├── Puppet (на базі агентів, корпоративний) ││ └── Salt (на базі Python) ││ ││ KUBERNETES-NATIVE (Створення та налаштування K8s) ││ ├── Helm (менеджер пакетів для K8s) ││ ├── Kustomize (кастомізація на базі патчів) ││ └── kubectl apply (пряме застосування YAML) ││ │└─────────────────────────────────────────────────────────────┘Terraform: Галузевий стандарт
Розділ «Terraform: Галузевий стандарт»Terraform від HashiCorp є найпоширенішим інструментом IaC:
# main.tf - Конфігурація Terraform
# Визначення провайдера (де створювати ресурси)provider "aws" { region = "us-west-2"}
# Визначення ресурсуresource "aws_instance" "web" { ami = "ami-0c55b159cbfafe1f0" instance_type = "t2.micro"
tags = { Name = "web-server" Environment = "production" }}
# Визначення виводуoutput "public_ip" { value = aws_instance.web.public_ip}# Робочий процес Terraformterraform init # Завантаження провайдерівterraform plan # Попередній перегляд змінterraform apply # Створення інфраструктуриterraform destroy # Повне видаленняЧому Terraform виграє
Розділ «Чому Terraform виграє»| Функція | Terraform | CloudFormation |
|---|---|---|
| Підтримка хмар | Будь-яка хмара | Тільки AWS |
| Управління станом | Вбудоване | Керується AWS |
| Синтаксис | HCL (читабельний) | JSON/YAML (багатослівний) |
| Складність навчання | Середня | Специфічна для AWS |
| Спільнота | Величезна | Обмежена AWS |
Ansible: Налаштування стало простішим
Розділ «Ansible: Налаштування стало простішим»Ansible використовує YAML “playbooks” для налаштування машин:
# playbook.yml - Ansible playbook---- name: Configure web server hosts: webservers become: yes # Запуск від імені root
tasks: - name: Install nginx apt: name: nginx state: present update_cache: yes
- name: Copy configuration template: src: nginx.conf.j2 dest: /etc/nginx/nginx.conf notify: Restart nginx
- name: Ensure nginx is running service: name: nginx state: started enabled: yes
handlers: - name: Restart nginx service: name: nginx state: restarted# Запуск плейбукаansible-playbook -i inventory.ini playbook.ymlКлючова перевага: Без агентів. Потрібен лише доступ через SSH.
IaC для Kubernetes
Розділ «IaC для Kubernetes»Kubernetes — ЦЕ і є Інфраструктура як код:
# deployment.yaml - Бажаний станapiVersion: apps/v1kind: Deploymentmetadata: name: webspec: replicas: 3 selector: matchLabels: app: web template: metadata: labels: app: web spec: containers: - name: nginx image: nginx:1.25# Застосувати бажаний станkubectl apply -f deployment.yaml
# Kubernetes узгоджує фактичний стан із бажаним# Це IaC в дії!Зв’язок: Kubernetes використовує ті самі декларативні та ідемпотентні принципи, що й Terraform та Ansible.
Компроміси: Ціна IaC
Розділ «Компроміси: Ціна IaC»Хоча IaC є необхідним для сучасної інженерії, він має певні компроміси:
- Швидкість чи структура: Налаштування через хмарну консоль (ClickOps) значно швидше для короткого разового експерименту. IaC вимагає написання коду, планування та застосування, що створює додаткові витрати часу для простого завдання.
- Поріг входження: Команди не можуть просто створювати сервери; вони повинні вивчити доменно-специфічні мови (наприклад, HCL для Terraform) та зрозуміти принципи управління станом (state management).
- Складність управління станом: Інструменти на кшталт Terraform зберігають стан середовища у файлі. Безпечне керування цим файлом стану (блокування для запобігання одночасним запускам, шифрування для приховування секретів) стає новим операційним завданням.
Найкращі практики IaC
Розділ «Найкращі практики IaC»1. Все в Git
Розділ «1. Все в Git»infrastructure/├── terraform/│ ├── main.tf│ ├── variables.tf│ └── outputs.tf├── kubernetes/│ ├── deployments/│ └── services/└── ansible/ └── playbooks/2. Використовуйте модулі та компоненти повторного використання
Розділ «2. Використовуйте модулі та компоненти повторного використання»# Не повторюйтесяmodule "web_server" { source = "./modules/ec2-instance"
name = "web-1" instance_type = "t2.micro"}
module "api_server" { source = "./modules/ec2-instance"
name = "api-1" instance_type = "t2.small"}3. Розділяйте середовища
Розділ «3. Розділяйте середовища»environments/├── dev/│ └── main.tf # Маленькі інстанси, одна репліка├── staging/│ └── main.tf # Середні інстанси, тестування└── prod/ └── main.tf # Великі інстанси, висока доступність4. Ніколи не редагуйте вручну
Розділ «4. Ніколи не редагуйте вручну»Золоте правило: якщо цього немає в коді, воно не існує.
Ручні зміни = дрейф конфігурації = баги о 3 годині ночіРобочий процес IaC
Розділ «Робочий процес IaC»┌─────────────────────────────────────────────────────────────┐│ РОБОЧИЙ ПРОЦЕС IaC │├─────────────────────────────────────────────────────────────┤│ ││ 1. Написання ──► 2. Огляд ──► 3. Тестування ││ коду (PR/MR) (Plan) ││ │ │ ││ │ ▼ ││ 6. Моніторинг ◄── 5. Застосування ◄── 4. Затвердження ││ стану змін (Merge) ││ ││ Усі зміни проходять через огляд коду ││ Усі зміни можна перевірити (аудит) ││ Усі зміни можна скасувати ││ │└─────────────────────────────────────────────────────────────┘Чи знали ви?
Розділ «Чи знали ви?»- NASA використовує Terraform для управління своєю хмарною інфраструктурою. Якщо це достатньо добре для космосу, це достатньо добре і для вашого стартапу.
- Назва Ansible походить з науково-фантастичних романів Урсули Ле Гуїн, де “ansible” — це пристрій для миттєвого зв’язку крізь космос.
- “Худоба, а не домашні тварини” (Cattle, not pets) — це принцип IaC. Ставтеся до серверів як до худоби (замінні, пронумеровані), а не як до домашніх тварин (з іменами, незамінні). Ви повинні мати можливість без хвилювань видалити та відтворити будь-який сервер.
- “Дрейф конфігурації” (Configuration Drift) спочатку був терміном системного адміністрування, що описував явище, коли сервери в кластері з часом стають дедалі менш схожими через нерегулярні, недокументовані ручні оновлення.
Типові помилки
Розділ «Типові помилки»| Помилка | Чому це шкодить | Рішення |
|---|---|---|
| Ручні зміни після деплою IaC | Дрейф конфігурації | Повторний деплой з коду |
| Невикористання контролю версій | Немає історії змін, неможливо відкотитися | Використовуйте Git для всього |
| Хардкодинг секретів | Загроза безпеці | Використовуйте менеджери секретів |
| Монолітні конфігурації | Важко підтримувати | Використовуйте модулі |
| Відсутність бекапу стану | Втрата даних про інфраструктуру | Дистанційне зберігання стану |
| Відсутність тестів IaC в CI перед застосуванням | Помилка в синтаксисі зупинить прод | Використовуйте лінтери та plan в CI/CD |
| Ігнорування виводу plan | Випадкове видалення ресурсів | Завжди читайте diff перед затвердженням |
| Специфічний для середовища хардкодинг | Код не можна використати для staging/prod | Використовуйте змінні для відмінностей середовищ |
Практична вправа: IaC за допомогою kubectl
Розділ «Практична вправа: IaC за допомогою kubectl»Перед тим, як перейти до практики, розглянемо приклад IaC в Kubernetes.
Мета: Створити декларативну конфігурацію для простого Pod.
Крок 1: Код (Бажаний стан)
apiVersion: v1kind: Podmetadata: name: my-web-podspec: containers: - name: nginx image: nginx:alpineКрок 2: Дія (Apply)
Замість запуску kubectl run my-web-pod --image=nginx:alpine (імперативно), ми застосовуємо файл (декларативно):
kubectl apply -f pod.yamlКрок 3: Узгодження (Ідемпотентність)
Якщо ми знову запустимо kubectl apply -f pod.yaml, Kubernetes порівняє бажаний стан (наш файл) із фактичним станом, що працює в кластері. Оскільки вони точно збігаються, він нічого не робитиме.
Практична вправа
Розділ «Практична вправа»Завдання: Відчути принципи IaC на прикладі ресурсів Kubernetes.
Крок 1. Створити Deployment декларативно
cat << 'EOF' > deployment.yamlapiVersion: apps/v1kind: Deploymentmetadata: name: iac-demospec: replicas: 2 selector: matchLabels: app: iac-demo template: metadata: labels: app: iac-demo spec: containers: - name: nginx image: nginx:1.25EOF
kubectl apply -f deployment.yamlКрок 2. Перевірити ідемпотентність та внесення змін
# 1. Застосувати знову (ідемпотентність)kubectl apply -f deployment.yaml# Зверніть увагу, вивід скаже "deployment.apps/iac-demo unchanged"
# 2. Змінити кодsed -i '' 's/replicas: 2/replicas: 4/' deployment.yaml
# 3. Застосувати зміниkubectl apply -f deployment.yaml
# 4. Перевірити зміниkubectl get deployment iac-demo# Тепер показує 4 реплікиКрок 3. Написати з нуля
Тепер, не копіюючи зверху, напишіть новий файл з назвою config.yaml, який створює Kubernetes ConfigMap з назвою app-settings та ключем theme, встановленим у значення "dark". Потім застосуйте його декларативно.
Рішення для кроку 3
- Створення декларативного файлу:
cat << 'EOF' > config.yamlapiVersion: v1kind: ConfigMapmetadata: name: app-settingsdata: theme: "dark"EOF- Застосування з використанням принципів IaC:
kubectl apply -f config.yaml- Очищення ресурсів вправи:
kubectl delete -f deployment.yamlkubectl delete -f config.yamlrm deployment.yaml config.yamlКонтрольні запитання
Розділ «Контрольні запитання»-
Ви запускаєте скрипт деплою критичної бази даних. Конвеєр (pipeline) ламається на пів дорозі. Ви запускаєте його знову. Замість створення дубліката бази даних, інструмент розпізнає першу і просто завершує налаштування. Який принцип тут працює?
Відповідь
Це демонструє **ідемпотентність**. Виконання ідемпотентної операції кілька разів дає той самий ефект, що й одноразове виконання. Інструмент порівнює поточний стан із бажаним і вносить лише необхідні зміни, а не сліпо виконує команди. Це запобігає помилкам на кшталт створення дублікатів ресурсів. -
Вашій команді потрібно запустити 50 інстансів AWS EC2, налаштувати VPC та встановити балансувальники навантаження. Після запуску віртуальних машин на них потрібно виконати складні налаштування користувачів на рівні ОС та встановити специфічні бінарні файли додатків. Яка комбінація інструментів буде найбільш доречною?
Відповідь
Використання **Terraform** для створення інфраструктури (provisioning) та **Ansible** для її налаштування (configuration) буде найбільш доречним підходом. Terraform чудово справляється з декларативним створенням та керуванням хмарними ресурсами (VPC, інстанси EC2). Ansible найкраще підходить для налаштування операційних систем та програмного забезпечення на цих інстансах після їх створення. Їх поєднання дозволяє використовувати сильні сторони обох інструментів. -
Молодший інженер пише bash-скрипт з 15 операторами
if/else, щоб перевірити, чи встановлено Nginx, встановити його, якщо він відсутній, а потім запустити сервіс, якщо він зупинений. Ви пропонуєте замінити його 5-рядковим YAML-файлом Kubernetes. Чому підхід з YAML є фундаментально іншим та безпечнішим?Відповідь
Bash-скрипт є **імперативним** — він диктує покрокові інструкції ("як" це зробити). YAML-файл Kubernetes є **декларативним** — він описує бажаний кінцевий стан ("що" має бути). Декларативні підходи безпечніші, оскільки вони покладаються на контролер (як Kubernetes), який постійно узгоджує фактичний стан із бажаним. Це усуває потребу в крихкій логіці `if/else` і автоматично обробляє неочікувані початкові умови. -
Під час інциденту інженер підключається через SSH до прод-сервера і вручну редагує конфігураційний файл, щоб збільшити значення тайм-ауту. Проблему вирішено. Через два тижні команда деплоїть нову версію додатка через свій IaC-конвеєр, і проблема з тайм-аутом негайно повертається. Що сталося?
Відповідь
Це класичний приклад **дрейфу конфігурації** (configuration drift). Ручна зміна, зроблена під час інциденту, не була зафіксована в репозиторії IaC. Коли через два тижні запустився конвеєр IaC, він застосував конфігурацію, визначену в системі контролю версій. Це фактично перезаписало ручне виправлення і повернуло проблему з тайм-аутом, доводячи, чому всі зміни повинні проходити через код. -
О 3 годині ночі виникає критичний баг на поді. Черговий інженер виявляє, що рядок підключення до бази даних був змінений на сервері додатків. Ніхто не знає, хто і коли його змінив. Як Інфраструктура як код вирішує цю проблему?
Відповідь
IaC покладається на **контроль версій** (наприклад, Git) як на єдине джерело істини. Якщо всі зміни вносяться через IaC, ручне редагування на сервері або неможливе, або автоматично скасовується. Інженер міг би просто подивитися на історію Git (наприклад, `git log` або `git blame`), щоб побачити, хто саме змінив рядок підключення. Крім того, вони могли б побачити, коли це було зроблено, і переглянути pull request, який затвердив цю зміну, отримавши повний журнал аудиту. -
Ваша організація вимагає, щоб усі зміни в інфраструктурі були підзвітними, зворотними та перевірялися колегами перед застосуванням. Розробник скаржиться, що Kubernetes робить це неможливим, бо йому доводиться цілий день використовувати команди
kubectl run. Як ви виправите це непорозуміння?Відповідь
Розробник використовує Kubernetes імперативно через CLI, що порушує принципи IaC. Kubernetes за своєю суттю є системою IaC, якщо її використовувати правильно. Визначаючи ресурси в YAML-файлах і зберігаючи їх у Git, організація може забезпечити огляд змін. Застосування їх через CI/CD конвеєр гарантує, що Kubernetes повністю підтримує підзвітні, зворотні та рецензовані зміни інфраструктури. -
Ви застосовуєте YAML-файл Deployment до кластера, створюючи 3 репліки вебдодатка. Через десять хвилин ви випадково натискаєте “Вгору” та “Enter” у терміналі, знову запускаючи ту саму команду
kubectl apply -f deployment.yaml. Що зробить кластер?Відповідь
Кластер не зробить **нічого**. Оскільки команда `apply` є ідемпотентною та декларативною, Kubernetes порівнює бажаний стан у YAML-файлі з поточним станом у кластері. Бачачи, що 3 репліки вебдодатка вже працюють з точно такою конфігурацією, він не вносить жодних змін. Він просто повідомить, що ресурс не змінився.
Підсумок
Розділ «Підсумок»Інфраструктура як код трансформує управління інфраструктурою:
Основні принципи:
- Декларативність замість імперативності
- Ідемпотентні операції
- Контроль версій
- Зміни, що підлягають огляду (review)
Ключові інструменти:
- Terraform: Створення хмарних ресурсів
- Ansible: Налаштування машин
- Kubernetes: Оркестрація контейнерів (IaC вбудовано)
Чому це важливо:
- Відтворюваність середовищ
- Журнал аудиту для всіх змін
- Аварійне відновлення (відбудова з коду)
- Співпраця через огляд коду
Зв’язок з Kubernetes: Усе, що ви робите в Kubernetes, відповідає принципам IaC. YAML-файли — це ваш код інфраструктури.
Наступний модуль
Розділ «Наступний модуль»Модуль 1.2: GitOps — використання Git як єдиного джерела істини для інфраструктури.