Перейти до вмісту

Модуль 1.8: YAML для Kubernetes

Модуль 1.8: YAML для Kubernetes

Розділ «Модуль 1.8: YAML для Kubernetes»

Складність: [СЕРЕДНЯ]
Час на виконання: 35-40 хвилин
Попередні модулі: Модулі 1.1-1.7 (знайомство з ресурсами K8s)


Що ви зможете зробити

Розділ «Що ви зможете зробити»

До кінця цього модуля ви зможете:

  1. Побудувати структурно правильні маніфести Kubernetes, використовуючи фундаментальний синтаксис YAML, включаючи скаляри, списки (sequences), словники (mappings) та багаторядкові рядки.
  2. Розібрати чотири обов’язкові поля кожного ресурсу Kubernetes (apiVersion, kind, metadata, spec), щоб пояснити їхні ролі в декларативному керуванні станом.
  3. Діагностувати помилки валідації структури та схеми у файлах YAML, інтерпретуючи вивід команд kubectl apply --dry-run та kubectl explain.
  4. Спроектувати складні конфігурації розгортання з декількома ресурсами, використовуючи просунуті шаблони YAML, такі як роздільники документів, змінні оточення та монтування Volume-ів.

Була 2:15 ночі вівторка, коли основний сервіс оформлення замовлень середньої e-commerce платформи раптово зник із продуктивного кластера. Черговий інженер із заспаними очима та на каві, що вже давно охолола, гарячково перевіряв Deployment pipeline-и. Щойно було випущено hotfix для усунення критичної вразливості у фоновому робочому процесі. Pipeline світився зеленим, але Pod-и оформлення замовлень зникли.

Після 45 хвилин пошуків було виявлено першопричину: одне зайве тире у файлі YAML. Розробник випадково перетворив словник (mapping) міток розгортання на елемент списку, що зробило недійсним selector, який пов’язував Service із Deployment. API-сервер Kubernetes, бездоганно виконуючи те, що йому наказали, побачив Deployment без відповідних Pod-ів, і Service почав спрямовувати трафік у порожнечу. Ця крихітна синтаксична помилка коштувала компанії десятків тисяч доларів втраченого доходу.

Історія з передової: “Згорнутий” сертифікат В іншому сумнозвісному інциденті у фінансовій технологічній фірмі інженер оновив TLS-сертифікат, що зберігався як Secret у Kubernetes. Замість того, щоб використовувати літеральний блоковий скаляр (|) для збереження суворих переносів рядків у сертифікаті, вони випадково використали складений блоковий скаляр (>). Коли Kubernetes змонтував Secret в Ingress-контролер, весь сертифікат було розпарсено як один величезний рядок, де замість переносів рядків були пробіли. Ingress-контролер постійно падав, оскільки формат сертифіката був недійсним, що призвело до дворічного глобального збою. Різниця в один символ (> проти |) обійшла базові перевірки синтаксису YAML, тому що сам YAML був технічно коректним — він просто зіпсував дані.

YAML (YAML Ain’t Markup Language) — це lingua franca (мова спілкування) у Kubernetes. Це те, як ви повідомляєте бажаний стан керуючій площині (control plane). Хоча Kubernetes технічно може приймати JSON, YAML є стандартом, зручним для читання людиною. Однак його залежність від значущих пробілів та тонких синтаксичних правил робить його “мінним полем” для новачків. Оволодіння YAML — це не просто вивчення мови конфігурації; це вивчення того, як точно та безпечно взаємодіяти з API Kubernetes. Цей модуль перетворить YAML із джерела розчарування на потужний і передбачуваний інструмент для декларативної інфраструктури.


1. Основи YAML для інфраструктури

Розділ «1. Основи YAML для інфраструктури»

Перш ніж занурюватися у специфічні схеми Kubernetes, ви повинні зрозуміти основні структури даних YAML. YAML — це мова серіалізації даних, розроблена для того, щоб її було легко читати людям, і вона легко відображалася на нативні структури даних у мовах програмування (такі як словники, списки та рядки).

Скаляри, Словники та Списки

Розділ «Скаляри, Словники та Списки»

На найнижчому рівні файл YAML будується з трьох примітивних структур:

  1. Скаляри (Scalars): Поодинокі значення (рядки, цілі числа, булеві значення). Це листя дерева даних.
  2. Словники (Mappings): Пари ключ-значення. Вони визначають властивості об’єкта.
  3. Списки (Sequences): Впорядковані колекції елементів.

Ці структури можуть мати нескінченну вкладеність для представлення складних систем:

# Це Словник (Mapping) на кореневому рівні
server: nginx
port: 8080
is_active: true # Булевий скаляр
# Це Список (Sequence) скалярів
allowed_origins:
- https://example.com
- https://api.example.com
# Це Словник, що містить Список Словників
users:
- name: alice
role: admin
permissions:
- read
- write
- name: bob
role: editor
permissions:
- read

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

Зупиніться та подумайте: Подивіться на блок users вище. Скільки елементів у списку users? Який тип даних містить ключ permissions?

Відповідь Список `users` має 2 елементи (словники для alice та bob). Ключ `permissions` містить Список (Sequence) рядкових скалярів.

Багаторядкові рядки: оператори | та >

Розділ «Багаторядкові рядки: оператори | та >»

Передаючи файли конфігурації, скрипти або сертифікати в ConfigMap або Secret у Kubernetes, вам часто знадобиться вставляти багаторядкові рядки. YAML надає для цього два індикатори блокових скалярів:

  • Літеральний блоковий скаляр (|): Зберігає переноси рядків та точне форматування. Це те, що вам потрібно в 99% випадків для скриптів, конфігураційних файлів або TLS-сертифікатів.
  • Складений блоковий скаляр (>): Перетворює переноси рядків на пробіли, створюючи один довгий рядок, за винятком порожніх рядків.
# Літеральний (|) - ідеально зберігає структуру для скрипту
setup_script: |
#!/bin/bash
echo "Починаємо налаштування..."
apt-get update
apt-get install -y curl
# Складений (>) - добре підходить для довгих описів, які мають бути одним абзацом
description: >
Це дуже довгий опис, який я хочу написати
у кілька рядків у моєму редакторі для зручності читання,
але я хочу, щоб програма бачила його як один
безперервний рядок тексту.

Перш ніж продовжити: Якщо ви вставляєте ключ сертифіката .pem у Secret Kubernetes, який багаторядковий оператор ви ПОВИННІ використовувати і чому?

Відповідь Ви ПОВИННІ використовувати літеральний блоковий скаляр (`|`). Сертифікати покладаються на суворі межі нових рядків (наприклад, `-----BEGIN CERTIFICATE-----`, після якого йде перенос рядка). Якщо ви використаєте `>`, він "складе" сертифікат в один недійсний рядок.

Просунутий YAML: Якорі (&) та Псевдоніми (*)

Розділ «Просунутий YAML: Якорі (&) та Псевдоніми (*)»

Хоча вони рідше зустрічаються у стандартних маніфестах Kubernetes через перевагу Helm або Kustomize для шаблонізації, нативний YAML підтримує принципи DRY (Don’t Repeat Yourself) за допомогою якорів та псевдонімів.

Якір (&) визначає блок YAML, а псевдонім (*) вставляє його в іншому місці.

# Визначаємо якір з назвою 'common_labels'
base_labels: &common_labels
app: web-tier
environment: production
managed-by: platform-team
frontend_pod:
metadata:
# Використовуємо ключ злиття (<<) для вставки псевдоніма
<<: *common_labels
name: react-frontend
backend_pod:
metadata:
<<: *common_labels
name: node-api

Активна вправа: Подивіться на структуру frontend_pod вище. Якби ви перетворили цей YAML у JSON, як би виглядав отриманий JSON-об’єкт для frontend_pod.metadata?

Відповідь
{
"app": "web-tier",
"environment": "production",
"managed-by": "platform-team",
"name": "react-frontend"
}

Ключ злиття (merge key) розгортає словник безпосередньо в місці виклику.


2. Анатомія маніфесту Kubernetes

Розділ «2. Анатомія маніфесту Kubernetes»

Кожен окремий ресурс, який ви створюєте в Kubernetes — від простого Pod до складного CustomResourceDefinition — вимагає рівно чотирьох полів на кореневому рівні. Якщо будь-яке з них відсутнє, API-сервер негайно відхилить запит. Розуміння цих чотирьох полів є ключем до опанування декларативного стану.

+----------------------------------------------------+
| Анатомія маніфесту Kubernetes |
+----------------------------------------------------+
| |
| apiVersion: apps/v1 <-- 1. Яка схема API? |
| kind: Deployment <-- 2. Який тип об'єкта? |
| |
| metadata: <-- 3. Хто я? |
| name: my-app (Ідентичність) |
| namespace: prod |
| labels: ... |
| |
| spec: <-- 4. Чого я хочу? |
| replicas: 3 (Бажаний стан) |
| template: ... |
| |
+----------------------------------------------------+

Це повідомляє API-серверу, яку версію схеми використовувати для валідації. API Kubernetes розвиваються. Ресурс може початися у v1alpha1, перейти до v1beta1 і, нарешті, стати v1. Поле apiVersion вказує, які саме поля дозволені в решті файлу. Сюди включаються назви груп (наприклад, apps/v1, networking.k8s.io/v1). Якщо косої риски немає, ресурс належить до “основної” (core) групи (наприклад, просто v1 для Pod-ів, Service-ів та ConfigMap-ів).

Приклад: Якщо ви спробуєте створити Deployment з apiVersion: v1, API-сервер відхилить його, оскільки Deployment-и керуються схемою apps/v1.

Тип об’єкта, який ви намагаєтеся створити (наприклад, Pod, Service, Deployment, StatefulSet, Ingress). Він завжди пишеться з великої літери (CamelCase).

Дані, які унікально ідентифікують об’єкт і дозволяють кластеру організовувати його.

  • name: Повинно бути унікальним у межах простору імен (namespace) для цього конкретного типу (kind).
  • namespace: Віртуальний кластер, до якого належить об’єкт. За замовчуванням використовується default, якщо не вказано інше. Якщо ви забудете це вказати, ви можете випадково розгорнути ресурс не в тому середовищі!
  • labels: Пари ключ-значення, що використовуються для організації та вибору підмножин об’єктів (наприклад, tier: frontend, env: prod). Вони є функціональними та критично важливими для маршрутизації трафіку.
  • annotations: Неідентифікаційні метадані, що використовуються зовнішніми інструментами або контролерами (наприклад, build-commit: 4a2b9c, nginx.ingress.kubernetes.io/rewrite-target: /). Вони є описовими і зазвичай не впливають на стандартну маршрутизацію Kubernetes.

Це серце маніфесту. Поле spec декларує ваш бажаний стан. Кожен kind має кардинально різну схему spec. Поле spec у Pod визначає контейнери та Volume-и; spec у Service визначає порти та selector-и. Керуюча площина (control plane) Kubernetes постійно працює над тим, щоб фактичний стан відповідав бажаному стану, визначеному в цьому блоці.

(Примітка: деякі об’єкти, такі як ConfigMap та Secret, використовують поле data замість spec, але принцип залишається тим самим).

Зупиніться та подумайте: Ви створюєте ConfigMap. Яке з 4 стандартних кореневих полів буде замінено, і як воно називається?

Відповідь Поле `spec` замінюється на `data` (або `binaryData`). ConfigMap-и та Secret-и не мають "специфікації" бажаного стану; вони просто містять сирі дані.

3. Оволодіння kubectl explain

Розділ «3. Оволодіння kubectl explain»

Ви не можете запам’ятати всю схему API Kubernetes. Існують тисячі полів, а кастомні ресурси додають ще тисячі. Коли вам потрібно дізнатися, як налаштувати readiness probe або змонтувати Volume, вам не потрібно шукати в Інтернеті — у вас є офіційна документація, вбудована прямо у ваш термінал через kubectl explain.

kubectl explain звертається до OpenAPI-схеми вашого кластера.

Хочете дізнатися, які поля доступні в spec у Pod?

Terminal window
# Загальний синтаксис: kubectl explain <kind>.<field>.<field>
kubectl explain pod.spec

Вивід містить опис блоку spec і список усіх доступних полів у ньому, включаючи їхні типи даних (<string>, <[]Object>, <map[string]string>).

  • <string>: Очікує рядковий скаляр (наприклад, restartPolicy: Always).
  • <[]Object>: Символи [] означають, що очікується Список (Sequence). Ви повинні використовувати тире (наприклад, containers:).
  • <map[string]string>: Очікує Словник (Mapping) рядків до рядків (наприклад, nodeSelector:).

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

Terminal window
kubectl explain pod.spec.containers.livenessProbe

Приклад виводу:

KIND: Pod
VERSION: v1
RESOURCE: livenessProbe <Probe>
DESCRIPTION:
Periodic probe of container liveness. Container will be restarted if the
probe fails. Cannot be updated...
FIELDS:
exec <ExecAction>
Exec specifies the action to take.
httpGet <HTTPGetAction>
HTTPGet specifies the http request to perform.
...

Можна заглибитися ще далі:

Terminal window
kubectl explain pod.spec.containers.livenessProbe.httpGet

Якщо ви хочете побачити весь скелет об’єкта одразу без описів, використовуйте прапор --recursive. Це неймовірно корисно для візуального розуміння вкладеної структури складних об’єктів, таких як Deployment.

Terminal window
kubectl explain deployment --recursive

Активна вправа: Використовуйте свій термінал (або уявіть, що використовуєте його). Вам потрібно додати “node selector”, щоб Pod запускався лише на вузлах з SSD. Яку саме команду kubectl explain ви б запустили, щоб знайти документацію для поля node selector всередині Pod?

Відповідь
Terminal window
kubectl explain pod.spec.nodeSelector

Це покаже вам, що nodeSelector очікує тип <map[string]string>, тобто ви повинні надати пари ключ-значення, що представляють мітки (labels) вузлів.


4. Типові шаблони YAML у Kubernetes

Розділ «4. Типові шаблони YAML у Kubernetes»

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

Змінні оточення (Списки Словників)

Розділ «Змінні оточення (Списки Словників)»

Змінні оточення в контейнері визначаються як список (sequence) словників (mappings), де кожен словник повинен мати принаймні ключі name та value. Ви також можете вставляти значення з ConfigMap-ів або Secret-ів, використовуючи valueFrom.

apiVersion: v1
kind: Pod
metadata:
name: env-demo
spec:
containers:
- name: my-app
image: nginx:alpine
env: # Поле 'env' приймає Список (Sequence)
- name: DATABASE_URL # Перший елемент списку, пряме значення
value: "postgres://db:5432"
- name: LOG_LEVEL # Другий елемент списку
value: "debug"
- name: API_KEY # Третій елемент, значення з Secret
valueFrom:
secretKeyRef:
name: app-secrets
key: api-key

Монтування Volume-ів (З’єднання частин)

Розділ «Монтування Volume-ів (З’єднання частин)»

Робота з Volume-ами в YAML — це двоетапний процес. Спочатку ви визначаєте Volume на рівні Pod (spec.volumes). Потім ви монтуєте його в конкретні контейнери (spec.containers[].volumeMounts). Обидва поля є списками.

apiVersion: v1
kind: Pod
metadata:
name: volume-demo
spec:
containers:
- name: app-container
image: busybox
command: ["sleep", "3600"]
volumeMounts: # Де контейнер бачить цей volume?
- name: config-store # Повинно точно збігатися з назвою volume нижче!
mountPath: /etc/config
readOnly: true
volumes: # Який саме volume стоїть за цим?
- name: config-store # Ідентифікатор
configMap: # Тип volume (заповнює файли з ConfigMap)
name: my-app-config

Label-и та Selector-и (Словники)

Розділ «Label-и та Selector-и (Словники)»

Label-и — це прості пари ключ-значення, що використовуються для ідентифікації. Selector-и використовуються такими ресурсами, як Service та Deployment, щоб знайти інші ресурси на основі цих міток. Для просунутого пошуку Deployment-и використовують matchLabels або matchExpressions.

# Service, що шукає конкретні pod-и
apiVersion: v1
kind: Service
metadata:
name: frontend-svc
spec:
selector: # Service спрямовуватиме трафік на будь-який Pod...
app: frontend # ...який має саме таку мітку
tier: web # ...ТА саме таку мітку.
ports:
- port: 80

5. Файли з декількома ресурсами

Розділ «5. Файли з декількома ресурсами»

У реальному світі програма складається з декількох компонентів: Deployment, Service, ConfigMap тощо. Замість того, щоб керувати десятком окремих файлів, ви можете об’єднати декілька ресурсів Kubernetes в один файл YAML, використовуючи роздільник документів: --- (три тире).

apiVersion: v1
kind: ConfigMap
metadata:
name: app-config
data:
color: "blue"
---
apiVersion: apps/v1
kind: Deployment
metadata:
name: my-app
spec:
replicas: 2
# ... деталі розгортання ...
---
apiVersion: v1
kind: Service
metadata:
name: my-app-svc
spec:
# ... деталі сервісу ...

Коли ви запускаєте kubectl apply -f combined.yaml, API-сервер обробляє всі документи.

Перш ніж продовжити: Чи має значення порядок документів, розділених ---, коли ви запускаєте kubectl apply -f combined.yaml?

Відповідь Технічно `kubectl apply` обробляє їх у тому порядку, в якому вони з'являються. Проте, оскільки Kubernetes постійно узгоджує стан (reconciliation), якщо Deployment буде створено раніше за ConfigMap, від якого він залежить, Pod-и просто не зможуть запуститися і перейдуть у стан crash-loop, доки ConfigMap не буде створено миттю пізніше. Зрештою все налагодиться, але за правилами хорошого тону варто ставити залежності (ConfigMap-и, Secret-и, PVC) на початок файлу!

6. Валідація YAML та реальна налагодження

Розділ «6. Валідація YAML та реальна налагодження»

Писати YAML легко; налагоджувати його — важко. API-сервер Kubernetes неймовірно суворий. Ви повинні перевіряти свої файли перед тим, як застосовувати їх до працюючого кластера.

Клієнтська валідація

Розділ «Клієнтська валідація»

Найшвидший спосіб перевірити синтаксис, не впливаючи на кластер, — використати клієнтський “сухий запуск” (dry run). Це перевіряє структуру вашого YAML та базову коректність схеми локально, без зв’язку з контролерами допуску (admission controllers) сервера.

Terminal window
kubectl apply -f my-pod.yaml --dry-run=client

У разі успіху ви побачите pod/my-pod created (dry run). Якщо сталася помилка, kubectl вкаже на конкретний рядок із помилкою.

Серверна валідація

Розділ «Серверна валідація»

Клієнтська валідація бачить не все. Наприклад, вона може не знати, чи існує в кластері конкретне Custom Resource Definition, чи існує простір імен, або чи відхилить вашу зміну admission webhook. Серверний dry-run надсилає дані на API-сервер для повної валідації без збереження об’єкта в etcd.

Terminal window
kubectl apply -f my-pod.yaml --dry-run=server

Перед застосуванням змін до існуючого ресурсу ЗАВЖДИ використовуйте kubectl diff. Вона покаже вам, які саме поля зміняться, використовуючи стандартний формат diff (+ для додавання, - для видалення). Це запобігає випадковим руйнівним оновленням, таким як зміна мітки (label), через що всі ваші Pod-и можуть раптово стати “сиротами”.

Terminal window
kubectl diff -f my-updated-deployment.yaml

Розшифровка повідомлень про помилки

Розділ «Розшифровка повідомлень про помилки»

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

Помилка 1: Пастка відступів

error: error parsing deployment.yaml: error converting YAML to JSON: yaml: line 15: mapping values are not allowed in this context
  • Діагноз: Це майже завжди означає помилку у відступах, зокрема відсутність тире для елемента списку або неправильні пробіли навколо двокрапки. Перевірте рядок 15 та рядки безпосередньо перед ним.

Помилка 2: Невідповідність типів

The Deployment "my-app" is invalid: spec.replicas: Invalid value: "3": spec.replicas must be an integer
  • Діагноз: Ви передали рядок "3" замість цілого числа 3. У YAML лапки примусово встановлюють тип рядка. Приберіть лапки.

Помилка 3: Відсутня схема

error: unable to recognize "pod.yaml": no matches for kind "Pod" in version "apps/v1"
  • Діагноз: Ви використали неправильний apiVersion для цього типу (kind). Pod-и належать до основної групи API v1, а не до apps/v1 (яка призначена для Deployment-ів та StatefulSet-ів).

Помилка 4: Дублікат ключа

error: error parsing config.yaml: error converting YAML to JSON: yaml: unmarshal errors:
line 12: mapping key "port" already defined at line 10
  • Діагноз: Словники (mappings) повинні мати унікальні ключі. Ви не можете визначити port: 80, а потім port: 443 у тому самому блоці словника. Один перезапише інший, або парсер взагалі відхилить файл.

Помилка 5: Валідація невідомого поля

error: error validating "deployment.yaml": error validating data: ValidationError(Deployment.spec.template.spec): unknown field "image" in io.k8s.api.core.v1.PodSpec;
  • Діагноз: Невідповідність схемі. Ви поставили image безпосередньо під spec, але image має бути всередині списку containers (spec.containers[0].image).

  • Версії YAML: Kubernetes в основному використовує специфікації YAML версії 1.2, хоча старіші парсери спиралися на 1.1. У YAML 1.1 рядок NO (без лапок) сприймається як булеве значення False. Це спричинило величезні проблеми для Норвегії (код країни NO), вимагаючи суворого використання лапок у маніфестах Kubernetes.
  • Максимальний розмір маніфесту: Максимальний розмір одного об’єкта, який можна зберігати в etcd (і, відповідно, надіслати через YAML), становить рівно 1.5 Мегабайта. Якщо ваш ConfigMap перевищує цей розмір, вам потрібно переглянути архітектуру або використовувати зовнішнє сховище.
  • Еквівалентність JSON: Оскільки YAML є надмножиною JSON, будь-який коректний JSON-файл автоматично є коректним YAML-файлом. Ви можете виконати kubectl apply -f manifest.json, і це спрацює ідеально.
  • Походження ‘spec’: Поділ на metadata та spec був значною мірою натхненний дизайном внутрішнього оркестратора контейнерів Google — Borg. Поле spec представляє “вектор бажаного стану”, що передається в цикл керування.
  • Проблема 2000 року для YAML: Рядок 22:22 без лапок у YAML 1.1 розпізнається як ціле число у шістдесятковому форматі (як час), що дорівнює 1342. У YAML 1.2 він сприймається як рядок. Щоб уникнути сюрпризів, завжди беріть час або версії в лапки!

ПомилкаЧому це трапляєтьсяЯк виправити
Використання табуляції для відступівКопіювання з браузерів або неправильно налаштовані редактори. Парсери YAML категорично не приймають табуляцію.Налаштуйте вашу IDE на заміну табуляції пробілами. Використовуйте рівно 2 пробіли на рівень відступу.
Неправильний apiVersionВгадування групи API замість перевірки. Deployment — це apps/v1, Ingress може бути networking.k8s.io/v1.Завжди перевіряйте через kubectl api-resources | grep <Kind>, щоб побачити правильну групу API.
Тире проти відсутності тиреПлутанина між списками (sequences) та словниками (mappings). Наприклад, containers: вимагає списку - name:, а metadata: — ні.Читайте схему. Якщо kubectl explain каже <[]Object>, використовуйте тире. Якщо каже <Object> — ні.
Плутанина між рядком та числомНомери портів у Service повинні бути числами. Анотації повинні бути суворо рядками. port: "80" (рядок) не спрацює, якщо очікується число.Прибирайте лапки для чисел (80). Використовуйте лапки для рядків, якщо YAML може їх невірно зрозуміти ("true" замість true).
Відсутність роздільника ---Розміщення декількох ресурсів в одному файлі без роздільника призводить до зупинки парсингу або перезапису даних.Завжди вставляйте --- в окремому рядку між різними об’єктами Kubernetes в одному файлі.
Невідповідність селекторівselector у Service не збігається з labels у Pod всередині Deployment.Тричі перевірте, що ключ і значення в селекторі Service ідентичні міткам, застосованим у шаблоні Pod.

Контрольні запитання

Розділ «Контрольні запитання»
1. Ви пишете ConfigMap і вам потрібно включити багаторядковий bash-скрипт. Ви хочете зберегти точні переноси рядків і форматування. Який індикатор блокового скаляра YAML слід використовувати?

Відповідь: Літеральний блоковий скаляр: | (вертикальна риска). Це гарантує, що переноси рядків будуть збережені точно так, як вони написані, що критично для shell-скриптів.

2. Ви виконуєте kubectl apply -f deployment.yaml і отримуєте помилку: yaml: line 22: did not find expected key. Яка найбільш імовірна причина?

Відповідь: Помилка у відступах біля 22-го рядка. Ця конкретна помилка зазвичай означає, що парсер YAML зустрів значення там, де він очікував ключ словника, що часто спричинено неправильними пробілами або відсутнім тире у списку.

3. Сценарій: Вам потрібно з'ясувати, як саме налаштувати volume AWS Elastic Block Store (EBS) безпосередньо у специфікації Pod. У вас немає доступу до Інтернету. Яку саме команду ви запустите, щоб прочитати документацію?

Відповідь: kubectl explain pod.spec.volumes.awsElasticBlockStore. Ця команда проходить крізь OpenAPI-схему, щоб надати опис конкретних полів, необхідних для цього типу volume.

4. Які чотири обов'язкові кореневі поля повинні бути в будь-якому стандартному маніфесті ресурсу Kubernetes?

Відповідь: apiVersion, kind, metadata та spec (або data у випадку ConfigMap/Secret).

5. Сценарій: Ви написали складний файл StatefulSet YAML на 300 рядків. Ви хочете перевірити синтаксис і переконатися, що API-сервер розуміє схему ресурсу, але ви категорично не хочете створювати об'єкт у кластері зараз. Який прапор потрібно додати до kubectl apply?

Відповідь: --dry-run=server. Це надішле маніфест на API-сервер для повної валідації (включаючи перевірки admission controller-ів та CRD) без збереження змін у etcd. --dry-run=client також підходить для базової перевірки синтаксису, але серверна валідація є більш повною.

6. Правда чи неправда: Ви можете застосувати валідний JSON-файл за допомогою kubectl apply -f my-pod.json.

Відповідь: Правда. YAML офіційно є надмножиною JSON, що означає, що всі стандартні парсери YAML у Kubernetes нативно розуміють і приймають дані у форматі JSON.


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

Попередні умови: Переконайтеся, що у вас є доступ до працюючого кластера Kubernetes (наприклад, minikube або kind) і налаштований kubectl.

Завдання 1: Зламаний фундамент

Розділ «Завдання 1: Зламаний фундамент»

Створіть файл із назвою dojo-app.yaml. Вставте в нього наступний навмисно зламаний YAML. Спробуйте застосувати його за допомогою kubectl apply -f dojo-app.yaml --dry-run=client.

apiVersion: v1
kind: Deployment
metadata:
name: web-app
spec:
replicas: "2"
selector:
matchLabels:
app: web
template:
metadata:
labels:
app: web
spec:
containers:
name: nginx
image: nginx:1.24
Рішення та діагноз 1

Ви повинні побачити помилку на кшталт: no matches for kind "Deployment" in version "v1". Виправлення: Змініть apiVersion: v1 на apiVersion: apps/v1. Deployment-и не знаходяться в основній (core) групі API.

Завдання 2: Помилки типів та структури

Розділ «Завдання 2: Помилки типів та структури»

Знову застосуйте файл (client dry-run). Ви зіткнетеся з новими помилками. Виправляйте їх одну за одною на основі повідомлень про помилки. Використовуйте kubectl explain deployment.spec, якщо заплутаєтеся в структурі.

Рішення та діагноз 2
  1. Помилка: Invalid value: "2": spec.replicas must be an integer. Виправлення: Змініть replicas: "2" на replicas: 2 (приберіть лапки).
  2. Помилка: error converting YAML to JSON: yaml: line 15: mapping values are not allowed in this context (або подібна залежно від парсера). Подивіться на блок containers. Виправлення: Поле containers очікує список (sequence) об’єктів, а не прямий словник. Вам не вистачає тире. Змініть:
    containers:
    name: nginx
    На:
    containers:
    - name: nginx
    image: nginx:1.24

Завдання 3: Безпечне додавання Service

Розділ «Завдання 3: Безпечне додавання Service»

Тепер, коли Deployment валідний, додайте Service в кінець того самого файлу dojo-app.yaml. Service повинен відкривати порт 80 і спрямовувати трафік на ваші Pod-и. Переконайтеся, що ви використовуєте правильний роздільник документів.

Рішення 3

Додайте --- у кінці файлу, а потім додайте визначення Service:

---
apiVersion: v1
kind: Service
metadata:
name: web-app-svc
spec:
selector:
app: web
ports:
- port: 80
targetPort: 80

Завдання 4: Додавання залежності ConfigMap

Розділ «Завдання 4: Додавання залежності ConfigMap»

Тепер додайте третій ресурс на самий початок файлу (перед Deployment): ConfigMap з назвою app-config, одним ключем welcome-message та значенням "Hello KubeDojo!".

Рішення 4

Додайте це на самий початок dojo-app.yaml і відокремте від Deployment за допомогою ---.

apiVersion: v1
kind: ConfigMap
metadata:
name: app-config
data:
welcome-message: "Hello KubeDojo!"
---

Завдання 5: З’єднання частин

Розділ «Завдання 5: З’єднання частин»

Змініть Deployment із Завдання 2 так, щоб контейнер nginx монтував ConfigMap із Завдання 4 як змінну оточення з назвою GREETING. Потім запустіть серверний dry-run для валідації всього файлу.

Terminal window
kubectl apply -f dojo-app.yaml --dry-run=server
Рішення 5

Ваш фінальний валідний dojo-app.yaml має виглядати саме так:

apiVersion: v1
kind: ConfigMap
metadata:
name: app-config
data:
welcome-message: "Hello KubeDojo!"
---
apiVersion: apps/v1
kind: Deployment
metadata:
name: web-app
spec:
replicas: 2
selector:
matchLabels:
app: web
template:
metadata:
labels:
app: web
spec:
containers:
- name: nginx
image: nginx:1.24
env:
- name: GREETING
valueFrom:
configMapKeyRef:
name: app-config
key: welcome-message
---
apiVersion: v1
kind: Service
metadata:
name: web-app-svc
spec:
selector:
app: web
ports:
- port: 80
targetPort: 80

Коли ви запустите kubectl apply -f dojo-app.yaml --dry-run=server, ви повинні побачити вивід, що підтверджує створення всіх трьох ресурсів:

configmap/app-config created (server dry run)
deployment.apps/web-app created (server dry run)
service/web-app-svc created (server dry run)

Якщо ви це бачите, ваш складний файл YAML із декількома ресурсами структурно правильний і відповідає схемі. Ви можете прибрати --dry-run=server, щоб реально розгорнути його!


Ви опанували мову Kubernetes (YAML) і розумієте, як будувати ресурси, що запускають ваші робочі навантаження. Але чому Kubernetes спроектований саме так? Чому варто використовувати декларативний YAML замість імперативних команд?

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