Модуль 1.4: Kustomize — конфігурація без шаблонів
Складність:
[СЕРЕДНЯ]— базова навичка CKA для Kubernetes 1.35+Час на проходження: 40-55 хвилин
Передумови: Модуль 0.1 (робочий кластер), базові знання YAML, упевнене читання об’єктів Deployment і Service
Результати навчання
Розділ «Результати навчання»Після цього модуля ви зможете:
- Спроєктувати структуру каталогів «база й оверлеї», яка зберігає спільні маніфести Kubernetes придатними для повторного використання, водночас дозволяючи зміни, специфічні для середовища.
- Застосувати перетворення Kustomize для просторів імен, назв, міток, образів, об’єктів ConfigMap, Secret та патчів, не редагуючи базові ресурси.
- Налагодити відрендерений вивід Kustomize перед застосуванням його до кластера за допомогою
kubectl kustomize,kubectl diff -kта валідації в режимі dry-run. - Оцінити, коли Kustomize є правильним інструментом порівняно з Helm, звичайним
kubectl applyчи GitOps-контролером. - Виправити типові збої оверлеїв, такі як неправильні відносні шляхи, невідповідність цілі патча, пошкодження міток селектора та несподіванки з хешем генератора.
Чому цей модуль важливий
Розділ «Чому цей модуль важливий»Гіпотетичний сценарій: платформена команда успадковує репозиторій Kubernetes із трьома майже однаковими теками з назвами dev, staging і prod. Кожна тека містить Deployment, Service, ConfigMap та Ingress для одного й того самого застосунку. Під час інциденту команда патчить відсутню readiness-перевірку у продакшені, а потім забуває застосувати те саме виправлення до staging. Через два тижні staging проходить кандидата на реліз, який продакшен відхилив би. Збій спричинила не непередбачуваність Kubernetes; його спричинив дрейф конфігурації, який зробила легким сама структура репозиторію.
Kustomize розв’язує саме цей клас проблем, відокремлюючи те, що залишається незмінним, від того, що змінюється залежно від середовища. Спільна форма застосунку живе в базі. Кожне середовище має оверлей, який посилається на базу й описує лише відмінності: простір імен, тег образу, кількість реплік, мітки, ліміти ресурсів або згенеровану конфігурацію. Той, хто навчається, далі працює зі звичайним YAML Kubernetes, але фінальний маніфест збирається детермінованим рендерером перед тим, як kubectl надішле будь-що на API-сервер.
Для CKA Kustomize важливий, бо він вбудований у kubectl і з’являється в практичних завданнях, де водночас важливі швидкість і коректність. Вас можуть попросити застосувати наданий оверлей, виправити зламаний kustomization.yaml, переглянути відрендерений вивід або пропатчити Deployment, не змінюючи базу. Поза іспитом ті самі навички виринають у GitOps-репозиторіях, процесах просування релізів та доставці застосунків для багатьох середовищ.
Аналогія з прозорою плівкою
Уявіть Kustomize як прозорі плівки-накладки на проєкторі. Базовий слайд містить стабільний застосунок: Deployment, Service, мітки, перевірки та порти контейнера. Плівка продакшену додає п’ять реплік і суворіші ліміти ресурсів. Плівка розробки додає інший простір імен і дешевший тег образу. Кожна плівка змінює те, що бачить аудиторія, але оригінальний слайд лишається цілим і придатним для повторного використання.
Частина 1: Ментальна модель
Розділ «Частина 1: Ментальна модель»Kustomize не є менеджером пакетів і не є рушієм шаблонів. Це рендерер маніфестів, який читає ресурси Kubernetes, застосовує перетворення, застосовує патчі, запускає генератори та друкує фінальний YAML. Ця різниця важлива, бо Kustomize не встановлює історію релізів, не керує залежностями чартів і не пам’ятає попереднього розгортання. Він видає маніфести; далі kubectl apply -k застосовує ці маніфести.
Перша звичка, яку варто виробити, — перегляд відрендереного виводу перед застосуванням. Команда kubectl kustomize <каталог> друкує YAML, який згенерував би Kustomize. Команда kubectl apply -k <каталог> рендерить і застосовує той самий вивід. На іспиті й у реальних кластерах попередній перегляд ловить зламані шляхи, неправильні назви, небажані зміни селекторів та несподівані згенеровані назви ще до того, як вони стануть об’єктами API.
Ментальна модель стає простішою, якщо розділити три моменти в часі. По-перше, у вас є вихідні файли в Git, які можуть містити базу, один чи кілька оверлеїв, патчі та вхідні дані генераторів. По-друге, Kustomize рендерить ці файли в єдиний потік звичайного YAML Kubernetes. По-третє, kubectl apply порівнює цей відрендерений YAML зі станом кластера й надсилає запити на створення або оновлення до API-сервера. Більшість заплутаних помилок Kustomize виникають тому, що той, хто навчається, пропускає середній момент і припускає, що файли на диску — це те саме, що й об’єкти, які отримає Kubernetes.
Цей середній момент також є тим, де Kustomize заслуговує на своє місце в робочому процесі CKA. Вам не потрібен кластер, щоб відповісти на багато запитань про зламаний оверлей, бо рендерер може довести, чи збігаються шляхи, назви, патчі та згенеровані посилання. Коли завдання обмежене в часі, це важить більше, ніж здається спочатку. Невдале застосування може лишити вас за читанням серверних помилок, повідомлень контролера допуску та часткового стану об’єктів, тоді як невдалий рендеринг зазвичай вказує назад на конкретний локальний каталог або файл, який ви можете виправити безпосередньо.
┌────────────────────────────────────────────────────────────────┐│ Kustomize Rendering Flow ││ ││ base/ overlays/prod/ ││ ┌──────────────────────┐ ┌────────────────────────┐ ││ │ deployment.yaml │ │ kustomization.yaml │ ││ │ service.yaml │ │ patch-replicas.yaml │ ││ │ kustomization.yaml │ │ patch-resources.yaml │ ││ └──────────┬───────────┘ └───────────┬────────────┘ ││ │ │ ││ └──────────────┬───────────────────┘ ││ ▼ ││ ┌─────────────────┐ ││ │ Kustomize build │ ││ │ render only │ ││ └────────┬────────┘ ││ ▼ ││ final Kubernetes YAML ││ │ ││ kubectl apply sends this ││ ▼ ││ Kubernetes API server │└────────────────────────────────────────────────────────────────┘База має бути нудною. Вона має визначати об’єкти, потрібні кожному середовищу, з безпечними значеннями за замовчуванням і назвами, які мають сенс ще до того, як додано префікси, специфічні для середовища. Оверлей має бути малим і чітко спрямованим. Він каже: «для цього середовища використовуй цей простір імен, цей тег образу, ці ліміти ресурсів та ці згенеровані значення конфігурації».
Корисне ревізійне запитання — чи зміг би майбутній колега прочитати базу, не знаючи, яке середовище її використовуватиме. Якщо відповідь «так», база, ймовірно, виконує свою роботу. Якщо база згадує кількість реплік лише для продакшену, прапорці налагодження лише для розробки чи простір імен лише для staging, тоді репозиторій починає ховати рішення про середовища у спільному шарі. Kustomize не зупиняє вас від цієї проєктної помилки, тож дисципліна має походити з того, як ви розділяєте файли.
| Термін | Що це означає | Практична перевірка |
|---|---|---|
| База (base) | Каталог, що містить придатні для повторного використання ресурси Kubernetes і kustomization.yaml, який їх перелічує. | Чи могло б інше середовище повторно використати це без копіювання файлів? |
| Оверлей (overlay) | Каталог із власним kustomization.yaml, який посилається на базу й додає зміни, специфічні для середовища. | Чи містить це лише те, що відрізняється для одного середовища? |
| Патч (patch) | Частковий YAML-документ або JSON-патч, який змінює відповідний ресурс у відрендереному наборі. | Чи збігається ціль із видом ресурсу та оригінальною назвою? |
| Трансформер (transformer) | Функція Kustomize, яка змінює багато ресурсів, наприклад назви, простори імен, мітки, анотації чи образи. | Чи застосувалося б це послідовно до всіх включених ресурсів? |
| Генератор (generator) | Функція, що створює об’єкти ConfigMap чи Secret із літералів, файлів або файлів середовища. | Чи змінюється назва згенерованого об’єкта, коли змінюється вміст? |
| Відрендерений вивід | Фінальний YAML, який видає Kustomize перед застосуванням до Kubernetes. | Чи перевірили ви це перед зміною кластера? |
Підказка для активного навчання: перш ніж читати наступний розділ, спрогнозуйте, що має жити в базі, а що — в оверлеї для вебзастосунку. Якщо ваша відповідь кладе
replicas: 10у базу, запитайте, чи дійсно кожне середовище хоче ту саму продакшен-потужність.
Частина 2: Побудуйте чисту базу
Розділ «Частина 2: Побудуйте чисту базу»Каталог бази починається зі звичайних маніфестів Kubernetes. Усередині Deployment чи Service немає особливого синтаксису лише через те, що Kustomize їх відрендерить. Це одна з причин, чому Kustomize добре працює для команд, які вже знають YAML Kubernetes: база лишається читабельною для стандартного інструментарію Kubernetes, рев’ю коду та документації.
Базі також потрібен файл kustomization.yaml. Цей файл є локальним рецептом збирання. Він повідомляє Kustomize, які ресурси належать до цієї одиниці та які перетворення чи генератори мають виконатися. Якщо в каталозі є YAML-файли, але немає kustomization.yaml, kubectl apply -k не знає, як трактувати його як пакет Kustomize.
Поширена угода в інтерактивних оболонках — скорочувати kubectl, але ця звичка ризикована в навчальних матеріалах і скопійованих скриптах, бо аліаси часто не розкриваються під час неінтерактивного виконання. Середовище CKA також може стартувати з чистої оболонки, тож цей модуль скрізь використовує повну команду kubectl. Перед початком завдання з обмеженням за часом безпечнішою перевіркою готовності є підтвердження, що справжній бінарний файл доступний і що його клієнтська версія друкується очікувано.
kubectl version --clientНаведена нижче база визначає невеликий вебзастосунок. Вона навмисно тримає простір імен поза базою, бо простори імен зазвичай відрізняються залежно від середовища. Вона також використовує стабільні мітки для селекторів і зіставлення подів. Пізніші розділи пояснять, чому необережна зміна міток селектора — один із найлегших способів зламати інакше валідний оверлей.
mkdir -p webapp/baseapiVersion: apps/v1kind: Deploymentmetadata: name: webapp labels: app.kubernetes.io/name: webapp app.kubernetes.io/component: frontendspec: replicas: 1 selector: matchLabels: app.kubernetes.io/name: webapp app.kubernetes.io/component: frontend template: metadata: labels: app.kubernetes.io/name: webapp app.kubernetes.io/component: frontend spec: containers: - name: webapp image: nginx:1.25 ports: - containerPort: 80 resources: requests: memory: "64Mi" cpu: "100m"apiVersion: v1kind: Servicemetadata: name: webapp labels: app.kubernetes.io/name: webappspec: selector: app.kubernetes.io/name: webapp app.kubernetes.io/component: frontend ports: - name: http port: 80 targetPort: 80apiVersion: kustomize.config.k8s.io/v1beta1kind: Kustomization
resources: - deployment.yaml - service.yamlПерегляньте базу перед створенням оверлеїв. Цей крок навчає вас сприймати Kustomize спершу як рендерер, а вже потім як механізм застосування. Якщо відрендерена база невалідна, кожен оверлей, який на неї посилається, успадковує цю проблему.
kubectl kustomize webapp/base/Ви маєте побачити Deployment і Service. До кластера ще нічого не застосовано. Команда безпечна, бо вона лише друкує YAML. Якщо ви хочете клієнтську валідацію Kubernetes без зміни кластера, передайте відрендерений вивід у застосування в режимі dry-run.
kubectl kustomize webapp/base/ | kubectl apply --dry-run=client -f -База навмисно мінімальна, але вона не є заготовкою. Вона містить ресурси API, які визначають форму робочого навантаження. Оверлей вирішить середовище, версію образу, кількість реплік та операційну політику. Саме це розділення запобігає тому, щоб дрейф середовищ став звичкою в обслуговуванні.
Зверніть увагу, що базові Deployment і Service використовують ту саму стабільну пару міток для зв’язку селектора. Це зроблено навмисно, бо мітки селектора є частиною контракту між об’єктами, а не просто декоративними метаданими. Service, який добирає поди за app.kubernetes.io/name і app.kubernetes.io/component, має далі знаходити поди після того, як оверлей відрендериться. Коли пізніше ви додасте мітки середовища, префікси та зміни образів, варто переконатися, що ці зміни випадково не змінюють значення контракту селектора.
Є також практична іспитова причина тримати базу малою та конвенційною. Якщо база є валідним YAML Kubernetes, ви можете міркувати про неї тими самими звичками, які вже використовуєте для об’єктів Deployment і Service. Ви можете оглянути spec.selector.matchLabels, порівняти їх із мітками шаблону пода й перевірити образ контейнера, не вивчаючи другого синтаксису. Kustomize додає композицію навколо цих об’єктів; він не усуває потреби розуміти самі об’єкти.
Частина 3: Додавайте оверлеї без копіювання бази
Розділ «Частина 3: Додавайте оверлеї без копіювання бази»Оверлей посилається на базу за відносним шляхом. Якщо оверлей розташований у webapp/overlays/dev/, то ../../base означає «піднятися з dev до overlays, піднятися з overlays до webapp, потім увійти до base». Більшість збоїв Kustomize у початківців — це не збої синтаксису YAML; це збої шляхів, спричинені неправильним підрахунком рівнів каталогів.
Наведений нижче оверлей для розробки додає простір імен, префікс назви та мітку середовища. Префікс запобігає колізіям назв, коли кілька відрендерених варіантів спільно використовують один кластер. Простір імен тримає об’єкти в правильній адміністративній межі. Мітка полегшує запит, фільтрацію та операції з усіма ресурсами середовища розробки.
mkdir -p webapp/overlays/dev webapp/overlays/prodapiVersion: kustomize.config.k8s.io/v1beta1kind: Kustomization
resources: - ../../base
namePrefix: dev-namespace: development
labels: - pairs: environment: dev app.kubernetes.io/managed-by: kustomize includeSelectors: falseТрансформер labels тут безпечніший, ніж сліпа стратегія міток, що змінює селектори. Мітки середовища корисні в метаданих об’єктів і шаблонах подів, але додавання їх до селекторів може змусити об’єкти Service і Deployment добирати вужчий набір подів, ніж ви мали на увазі. Для нового робочого навантаження зміни селекторів можуть спрацювати. Для наявного робочого навантаження мутації селекторів можуть зазнати невдачі, бо селектори Deployment є незмінними.
Важлива фраза в тому абзаці — «для наявного робочого навантаження». Kubernetes дозволяє багатьом полям змінюватися з часом, але він трактує селектор Deployment як ідентичність, а не як оздоблення. Якщо трансформер міток змінює селектори після того, як Deployment уже існує, API-сервер може відхилити оновлення, бо контролер більше не володів би тим самим набором подів. Навіть якщо об’єкт новий і застосування успішне, зміни селекторів усе одно можуть здивувати операторів, бо Service і Deployment можуть перестати погоджуватися щодо того, які поди є частиною застосунку.
Підказка для активного навчання: спрогнозуйте відрендерені назви перед запуском команди. Service називатиметься
webapp,dev-webappчиwebapp-dev? Потім запустіть попередній перегляд і перевірте, чи збіглася ваша ментальна модель із виводом.
kubectl kustomize webapp/overlays/dev/Продакшен-оверлей зазвичай потребує сильніших відмінностей. Він може змінювати репліки, теги образів, ліміти ресурсів, згенеровану конфігурацію чи анотації, які використовують інструменти політик і спостережуваності. Ключове в тому, що оверлей усе одно уникає копіювання всього Deployment. Він виражає лише рішення, специфічні для продакшену.
Продакшен — це середовище, де дисципліна оверлеїв окупається найочевидніше. Ви хочете, щоб продакшен відрізнявся там, де цього вимагають операції, але ви не хочете, щоб продакшен став відгалуженням визначення застосунку. П’ять реплік, суворіші ліміти ресурсів, продакшен-простір імен і захищений тег образу — це легітимні продакшен-рішення. Копіювання всього Deployment лише для вираження цих рішень створює друге джерело істини, і це друге джерело зрештою пропустить спільне виправлення, якщо тільки культура рев’ю не є винятково суворою.
apiVersion: kustomize.config.k8s.io/v1beta1kind: Kustomization
resources: - ../../base
namePrefix: prod-namespace: production
labels: - pairs: environment: production app.kubernetes.io/managed-by: kustomize includeSelectors: false
images: - name: nginx newTag: "1.25-alpine"
patches: - path: patch-replicas.yaml - path: patch-resources.yamlapiVersion: apps/v1kind: Deploymentmetadata: name: webappspec: replicas: 5apiVersion: apps/v1kind: Deploymentmetadata: name: webappspec: template: spec: containers: - name: webapp resources: requests: memory: "256Mi" cpu: "250m" limits: memory: "512Mi" cpu: "500m"Зверніть увагу на назву цілі патча: webapp, а не prod-webapp. Kustomize зіставляє патчі з оригінальною ідентичністю ресурсу до того, як застосовується префікс назви. Це дивує тих, хто навчається, бо фінальна назва об’єкта містить префікс, але файл патча все одно описує базовий ресурс, який він хоче змінити.
Перегляньте продакшен і уважно огляньте вивід. Фінальна назва Deployment має містити префікс, простір імен має бути production, тег образу має бути зміненим, а кількість реплік має дорівнювати п’яти. Якщо чогось із цього бракує, виправте рендеринг перед застосуванням до кластера.
kubectl kustomize webapp/overlays/prod/Частина 4: Трансформери як контрольовані масові правки
Розділ «Частина 4: Трансформери як контрольовані масові правки»Трансформери потужні, бо вони застосовують послідовну зміну до багатьох ресурсів. Вони також ризиковані, бо широке перетворення може торкнутися більшої кількості полів, ніж очікує початківець. Правильний спосіб їх використання — розуміти, яких полів вони торкаються, переглядати вивід і тримати оверлеї середовищ достатньо вузькими, щоб рев’ю лишалося осмисленим.
Уявіть трансформер як контрольовану масову правку з обізнаністю про Kubernetes. Пошук-і-заміна в текстовому редакторі може змінити назви там, де вони є коментарями, прикладами чи непов’язаними рядками. Трансформери Kustomize працюють зі структурованими полями ресурсів і для відомих зв’язків посилань оновлюють пов’язані поля разом. Ця структура корисна, але вона не усуває потреби в судженні. Вам усе одно треба вирішити, чи масова правка є найзрозумілішим вираженням наміру, чи цілеспрямований патч був би безпечнішим для одного об’єкта.
Трансформери назв прості. namePrefix додає текст перед назвами ресурсів, тоді як nameSuffix додає текст після. Kustomize також оновлює внутрішні посилання, коли розуміє зв’язок, наприклад Deployment, що посилається на згенерований ConfigMap. Це одна з причин, чому Kustomize кращий за простий пошук-і-заміну.
# Example name transformationapiVersion: kustomize.config.k8s.io/v1beta1kind: Kustomization
resources: - ../../base
namePrefix: prod-nameSuffix: -blue┌──────────────────────────┐│ Base name ││ webapp │└─────────────┬────────────┘ │ namePrefix: prod- │ nameSuffix: -blue ▼┌──────────────────────────┐│ Rendered name ││ prod-webapp-blue │└──────────────────────────┘Трансформер простору імен встановлює metadata.namespace на ресурсах із простором імен. Він не робить ресурси з областю кластера такими, що мають простір імен. Об’єкт Namespace, ClusterRole, ClusterRoleBinding, CustomResourceDefinition та StorageClass мають область кластера, тож трансформер простору імен не може перетворити їх на об’єкти з простором імен. Це важливо, коли оверлей містить водночас ресурси застосунку та ресурси рівня кластера.
# Example namespace transformationapiVersion: kustomize.config.k8s.io/v1beta1kind: Kustomization
resources: - ../../base
namespace: productionТрансформер образів є кращим способом змінити теги образів, коли назва образу вже існує в базі. Він уникає написання патча проти вкладеного списку контейнерів і його легше переглядати під час рев’ю. Він може змінити тег, реєстр або обидва.
# Example image transformationapiVersion: kustomize.config.k8s.io/v1beta1kind: Kustomization
resources: - ../../base
images: - name: nginx newName: registry.example.com/platform/nginx newTag: "1.25-alpine"Мітки заслуговують на особливу обачність. Старіші приклади часто використовують commonLabels, який може додавати мітки до селекторів, а також до метаданих об’єктів. Це може бути прийнятним, коли створюється цілком нове робоче навантаження, але це небезпечно, коли оновлюється живий Deployment, бо поля селектора є незмінними. Віддавайте перевагу новішому трансформеру labels, коли вам потрібен контроль над тим, чи включаються поля селектора.
# Safer label transformation for environment metadataapiVersion: kustomize.config.k8s.io/v1beta1kind: Kustomization
resources: - ../../base
labels: - pairs: environment: production team: platform includeSelectors: false| Трансформер | Що він змінює | Головний ризик | Безпечніша звичка |
|---|---|---|---|
namePrefix | Назви ресурсів і відомі посилання. | Патчі, написані проти назв із префіксом, не збігаються. | Патчте базову назву й переглядайте фінальні назви. |
nameSuffix | Назви ресурсів і відомі посилання. | Довгі назви можуть перевищити обмеження довжини назв Kubernetes. | Тримайте суфікси короткими та зорієнтованими на середовище. |
namespace | Метадані ресурсів із простором імен. | Ресурси з областю кластера лишаються з областю кластера. | Переглядайте змішані набори ресурсів перед застосуванням. |
images | Посилання на образи контейнерів, що збігаються з оригінальною назвою образу. | Невідповідність назви лишає образ незміненим. | Переглядайте й шукайте image: у відрендереному виводі. |
labels | Метадані, селектори та шаблони залежно від опцій. | Зміни селекторів можуть зламати або бути відхиленими. | Використовуйте includeSelectors: false для операційних міток. |
commonAnnotations | Анотації об’єктів. | Чутливі значення можуть бути розкриті в метаданих. | Тримайте секрети в даних Secret, а не в анотаціях. |
Рев’ю Kustomize старшого рівня запитує, чи виражає трансформер намір краще за патч. Якщо ви змінюєте кожен ресурс в оверлеї, трансформер зрозуміліший. Якщо ви змінюєте одне поле на одному об’єкті, патч часто зрозуміліший. Якщо ви змінюєте поведінку, яку Kubernetes трактує як незмінну, вам потрібно спланувати міграцію, а не припускати, що рендерер може проштовхнути її силою.
Рев’ю має також запитати, чи буде відрендерений вивід зрозумілим тому, хто пізніше налагоджуватиме кластер. Трансформер простору імен легко пояснити, бо кожен об’єкт із простором імен потрапляє в простір імен середовища. Трансформер образів легко пояснити, бо базова назва образу зіставляється з конкретним тегом чи реєстром у цьому оверлеї. Широке правило міток із включенням селекторів пояснити складніше, бо воно може водночас торкнутися метаданих, шаблонів подів і селекторів контролера. Коли ефект широкий, крок попереднього перегляду стає частиною проєктування, а не лише фінальною перевіркою.
Частина 5: Патчі та чому назви важливі
Розділ «Частина 5: Патчі та чому назви важливі»Патчі — це те, як оверлеї роблять цілеспрямовані зміни ресурсів із бази. Два практичні стилі патчів, які ви бачитимете найчастіше, — це стратегічні merge-патчі та JSON-патчі 6902. Стратегічні merge-патчі виглядають як часткові об’єкти Kubernetes. JSON-патчі виглядають як список операцій над JSON-шляхами. Обидва корисні, але вони розв’язують різні проблеми.
Найвагоміша причина використати патч — те, що зміна належить одному об’єкту, а не всьому оверлею. Кількість реплік, readiness-перевірка, ліміт ресурсів чи налаштування безпеки пода можуть бути специфічними для продакшену, але це не обов’язково потребує трансформера, що торкається кожного ресурсу. Патчі дозволяють вам тримати базу читабельною, водночас виражаючи операційну відмінність поруч із середовищем, якому вона належить. Компроміс у тому, що ідентичність патча має бути точною: вид, назва, версія API та ключі злиття списків мають збігатися з тим, що рендерить Kustomize.
Стратегічне злиття зазвичай простіше для нативних об’єктів Kubernetes, таких як Deployment. Воно розуміє ключі злиття для багатьох списків Kubernetes. Наприклад, контейнери зливаються за name, тож патч, який згадує контейнер webapp, змінює саме цей контейнер замість заміни всього списку контейнерів. Саме тому назви контейнерів мають бути точними.
apiVersion: apps/v1kind: Deploymentmetadata: name: webappspec: template: spec: containers: - name: webapp readinessProbe: httpGet: path: / port: 80 initialDelaySeconds: 5 periodSeconds: 10Якщо базовий контейнер називається webapp, а патч використовує app, стратегічний merge-патч може додати другий контейнер замість зміни наявного. Цей відрендерений YAML може навіть бути валідним YAML Kubernetes, водночас лишаючись операційно неправильним. Саме тому важливо переглядати повний вивід і читати список контейнерів.
Що сталося б, якби: ваш продакшен-патч посилається на контейнер із назвою
app, але контейнер базового Deployment називаєтьсяwebapp. Перед запуском команди вирішіть, чого ви очікуєте — помилки валідації, нового контейнера чи зміненого наявного контейнера. Потім відрендеріть оверлей і огляньтеspec.template.spec.containers.
JSON-патчі 6902 кращі, коли вам потрібні точні операції, особливо проти скалярних полів чи списків, де поведінка стратегічного злиття не є тим, чого ви хочете. Вони також корисні, коли ви хочете, щоб патч зазнав невдачі, якщо шлях відсутній, бо операція replace очікує, що цільовий шлях існує.
# webapp/overlays/prod/kustomization.yaml fragmentpatches: - target: kind: Deployment name: webapp patch: |- - op: replace path: /spec/replicas value: 5 - op: add path: /metadata/annotations/reviewed-by value: platform-teamЦілеспрямування патчів також може використовувати вид, назву, простір імен, групу, версію та селектори міток. Для іспитової роботи цілься за видом і назвою, якщо завдання чітко не просить добору за мітками. Для роботи з репозиторієм вказуйте достатньо ідентичності, щоб випадкові збіги були малоймовірними.
# Target one Deployment by kind and base namepatches: - path: patch-resources.yaml target: kind: Deployment name: webapp# Target all frontend Deployments by labelpatches: - path: patch-frontend-memory.yaml target: kind: Deployment labelSelector: "app.kubernetes.io/component=frontend"| Стиль патча | Найкраще використання | Приклад рішення | Режим збою для перевірки |
|---|---|---|---|
| Стратегічне злиття | Нативні об’єкти Kubernetes, де частковий YAML читабельний. | Додати ресурси, перевірки, репліки чи контекст безпеки пода. | Неправильний ключ злиття списку створює новий елемент списку. |
| JSON 6902 | Точні операції проти конкретних шляхів. | Замінити /spec/replicas чи додати одну анотацію. | Неправильний шлях зазнає невдачі або змінює непередбачений шлях. |
| Цілеспрямований патч | Один ресурс потребує відомої зміни. | Пропатчити лише Deployment/webapp. | Назва цілі використовує відрендерену назву замість базової. |
| Патч за добором міток | Клас ресурсів потребує тієї самої зміни. | Пропатчити всі frontend-Deployment. | Селектор збігається з більшою кількістю ресурсів, ніж задумано. |
Звичка старшого рівня — робити намір патча очевидним під час рев’ю. Файл патча з назвою patch.yaml змушує рецензентів відкривати його, перш ніж вони дізнаються, який ризик він несе. Патч із назвою patch-resources.yaml чи patch-readiness-probe.yaml повідомляє рецензенту, яка поведінка має змінитися, і полегшує помічання випадкового розповзання обсягу.
Файли патчів мають бути достатньо малими, щоб рецензент міг швидко відповісти на два запитання. Якому ресурсу цей патч має відповідати, і яку поведінку він має змінити? Якщо патч водночас змінює репліки, ресурси, перевірки, мітки та анотації, важче виявити випадкову мутацію селектора чи невідповідність назви контейнера. Поділ патчів за наміром — це не церемонія; це спосіб зробити рев’ю відрендереного виводу швидшим і надійнішим, коли репозиторій виростає за межі одного застосунку.
Частина 6: Генератори ConfigMap і Secret
Розділ «Частина 6: Генератори ConfigMap і Secret»Генератори створюють об’єкти ConfigMap і Secret із файлів, літералів чи файлів середовища. Вони корисні, бо вміст конфігурації часто належить поруч із оверлеєм, якому вона належить. Оверлей розробки може встановити докладний рівень логування. Продакшен-оверлей може встановити суворіший таймаут. Генератор тримає цю конфігурацію, що належить середовищу, близько до kustomization, який належить середовищу.
Генератори також роблять зміни конфігурації видимими в тому самому рев’ю, що й зміни робочого навантаження. Якщо продакшен-оверлей змінює файл таймауту й патч ліміту ресурсів разом, рецензенти можуть міркувати про обидва ефекти перед застосуванням маніфесту. Без генератора команди часто створюють ConfigMap вручну в окремій теці або застосовують їх вручну, що послаблює зв’язок між версією застосунку та конфігурацією, на яку він розраховує. Kustomize не розв’язує кожної проблеми керування конфігурацією, але дає вам чистий спосіб тримати звичайні вхідні дані ConfigMap і Secret усередині межі оверлею.
Найважливіша поведінка генератора — суфікс хешу. За замовчуванням Kustomize додає хеш вмісту до назв згенерованих ConfigMap і Secret. Коли вміст змінюється, назва згенерованого об’єкта змінюється. Якщо Deployment посилається на цей згенерований об’єкт через посилання на назву, керовані Kustomize, шаблон пода теж змінюється, що запускає розгортання.
mkdir -p webapp/overlays/prod/configcat > webapp/overlays/prod/config/app.properties << 'EOF'LOG_LEVEL=infoFEATURE_FLAGS=checkout-v2REQUEST_TIMEOUT_SECONDS=10EOF# webapp/overlays/prod/kustomization.yaml fragmentconfigMapGenerator: - name: webapp-config files: - config/app.propertiesDeployment може споживати цей згенерований ConfigMap за логічною назвою з генератора. Kustomize переписує посилання на хешовану відрендерену назву. Це корисна частина: ви пишете стабільну логічну назву, а Kustomize тримає застосовану назву адресованою за вмістом.
# Example base Deployment fragmentenvFrom: - configMapRef: name: webapp-config┌──────────────────────────┐│ Generator logical name ││ webapp-config │└─────────────┬────────────┘ │ content changes ▼┌──────────────────────────┐│ Rendered ConfigMap name ││ webapp-config-abc123 │└─────────────┬────────────┘ │ Deployment reference rewritten ▼┌──────────────────────────┐│ Pod template changes ││ rollout is triggered │└──────────────────────────┘Secret можна згенерувати так само, але генерування Secret саме по собі не робить поводження із секретами безпечним. Якщо ви закомітите файли з паролями у відкритому тексті в Git, Kustomize сумлінно створить Secret зі злитого матеріалу. Для реальних середовищ використовуйте sealed secrets, оператори зовнішніх секретів, SOPS чи інший процес керування секретами. Для CKA вам потрібно лише розуміти механіку Kustomize.
# webapp/overlays/prod/kustomization.yaml fragmentsecretGenerator: - name: webapp-db literals: - username=webapp - password=change-me-in-real-life type: OpaqueІноді команди вимикають суфікси хешу, бо старий застосунок очікує фіксованої назви ConfigMap. Це компроміс, а не нешкідлива вподоба. Стабільна згенерована назва легша для застарілих посилань, але вона усуває автоматичний тригер розгортання, спричинений змінами назви.
# Disabling the generator hash suffixapiVersion: kustomize.config.k8s.io/v1beta1kind: Kustomization
configMapGenerator: - name: webapp-config literals: - LOG_LEVEL=info
generatorOptions: disableNameSuffixHash: trueНазва поля — disableNameSuffixHash, а не disableNameSuffix. Ця деталь важлива в усуненні несправностей, бо приклади з пам’яті чи застарілих нотаток можуть призвести до kustomization, який поводиться не так, як очікувалося. Коли є сумнів, відрендеріть вивід і огляньте згенеровані назви замість припущення, що опція спрацювала.
Суфікси хешу варто зберігати, якщо тільки ви не можете назвати систему, яка справді вимагає стабільних назв згенерованих об’єктів. З увімкненим суфіксом зміна вмісту ConfigMap стає зміною назви, а переписане посилання шаблону пода дає контролеру Deployment причину створити нові поди. З вимкненим суфіксом дані об’єкта можуть змінитися, тоді як шаблон пода лишається ідентичним, тож наявні поди можуть далі працювати зі старішою конфігурацією, похідною від середовища, доки щось інше їх не перезапустить. Цю різницю легко пропустити, якщо ви оглядаєте лише ConfigMap і забуваєте оглянути шаблон Deployment.
Частина 7: Налагодження Kustomize як оператор
Розділ «Частина 7: Налагодження Kustomize як оператор»Налагодження Kustomize починається ще до того, як ви звертаєтеся до API-сервера. Якщо рендеринг зазнає невдачі, Kubernetes ніколи не побачить ресурсів. Якщо рендеринг успішний, але вивід неправильний, Kubernetes може прийняти об’єкт, який поводиться інакше, ніж ви мали на меті. Найбезпечніший робочий процес — відрендерити, оглянути, валідувати, порівняти, потім застосувати.
Цей порядок навмисно консервативний, бо він відокремлює локальні помилки від помилок кластера. Поганий відносний шлях, відсутній файл kustomization чи незбіжна ціль патча — це локальна проблема композиції. Відхилений незмінний селектор, відсутній простір імен чи невдала політика допуску — це проблема взаємодії з кластером. Якщо ви застосовуєте перед рендерингом, ці категорії змішуються, і ви витрачаєте час, ставлячи API-серверу запитання, на які локальний рендерер міг би відповісти швидше.
kubectl kustomize webapp/overlays/prod/Використовуйте grep чи yq, якщо вони доступні, щоб швидко оглянути конкретне поле, але не покладайтеся на них на іспиті, якщо не знаєте, що вони існують. Звичайного виводу kubectl kustomize достатньо для більшості завдань. Шукайте у відрендереному YAML name:, namespace:, image:, replicas: та будь-яке поле, яке завдання конкретно просило змінити.
kubectl kustomize webapp/overlays/prod/ | grep -E "name:|namespace:|image:|replicas:"Валідація в режимі dry-run ловить помилки рівня API без створення ресурсів. Це не повний серверний тест допуску, коли використовується клієнтський dry-run, але він ловить багато структурних помилок. Серверний dry-run може бути сильнішим, коли API-сервер досяжний і підтримує задіяні типи ресурсів.
kubectl kustomize webapp/overlays/prod/ | kubectl apply --dry-run=client -f -kubectl apply --dry-run=server -k webapp/overlays/prod/Diff показує, що змінилося б порівняно з поточним кластером. Це корисно, коли відрендерений оверлей валідний, але може оновити наявні об’єкти несподіваним чином. У робочому процесі GitOps застосування може виконувати контролер, але людина все одно отримує користь від локального рендерингу й порівняння під час рев’ю.
kubectl diff -k webapp/overlays/prod/Застосовуйте лише після того, як рендеринг відповідає завданню. На CKA спершу створюйте простори імен, якщо оверлей їх очікує, а завдання їх не надає. Встановлення Kustomize namespace: production не створює автоматично об’єкт Namespace, якщо ви не включите ресурс Namespace.
kubectl create namespace productionkubectl apply -k webapp/overlays/prod/kubectl get deploy,svc -n productionХороша послідовність усунення несправностей навмисно повторювана. По-перше, доведіть, що шлях існує. По-друге, доведіть, що база рендериться. По-третє, доведіть, що оверлей рендериться. По-четверте, доведіть, що відрендерений вивід містить задуману зміну. По-п’яте, застосуйте чи порівняйте. Ця послідовність не дає вам налагоджувати кластер, коли проблема насправді у відносному шляху в локальному каталозі.
┌──────────────────────────────┐│ Kustomize troubleshooting │└───────────────┬──────────────┘ ▼┌──────────────────────────────┐│ Does the overlay path exist? │└───────────────┬──────────────┘ ▼┌──────────────────────────────┐│ Does the base render alone? │└───────────────┬──────────────┘ ▼┌──────────────────────────────┐│ Does the overlay render? │└───────────────┬──────────────┘ ▼┌──────────────────────────────┐│ Is the intended field right? │└───────────────┬──────────────┘ ▼┌──────────────────────────────┐│ dry-run, diff, then apply │└──────────────────────────────┘Коли оверлей зазнає невдачі з помилкою накопичення ресурсів, читайте шлях у повідомленні про помилку буквально. Зазвичай він повідомляє вам, який файл чи каталог Kustomize намагався завантажити. Коли патч, схоже, нічого не робить, перевірте цільовий вид, цільову назву, версію API та назви контейнерів. Коли згенерований ConfigMap не перекочує поди, огляньте, чи було переписане посилання Deployment і чи вимкнено суфіксування хешу.
Для практики CKA виробіть звичку записувати задумане поле перед запуском команди. Якщо завдання каже, що продакшен має мати п’ять реплік, запитайте, де це число має з’явитися у відрендереному Deployment, а потім перевірте саме це поле. Якщо завдання каже, що продакшен-образ має використовувати конкретний тег, шукайте image: у відрендереному виводі й підтвердіть, що тег змінився в тому контейнері, який ви мали на увазі. Ця маленька пауза перетворює налагодження Kustomize з «дивитися на стіну YAML» на «довести чи спростувати одне очікування за раз».
Частина 8: Kustomize проти Helm проти звичайних маніфестів
Розділ «Частина 8: Kustomize проти Helm проти звичайних маніфестів»Kustomize, Helm і звичайні маніфести можуть розгортати об’єкти Kubernetes, але вони оптимізовані для різних ситуацій. Звичайні маніфести найлегші, коли є лише одне середовище й мало варіацій. Kustomize найсильніший, коли ви володієте маніфестами й потребуєте оверлеїв для середовищ без шаблонів. Helm найсильніший, коли ви хочете пакування, файли значень, залежності та історію релізів.
Це порівняння не про те, який інструмент професійніший. Воно про те, де живе варіація і хто володіє вихідним матеріалом. Якщо ви володієте Deployment і потребуєте трьох варіантів для середовищ, Kustomize дозволяє вам тримати звичайний YAML Kubernetes, водночас виражаючи відмінності без копіювання всього об’єкта. Якщо ви споживаєте сторонній застосунок, який уже постачається як чарт, Helm може дати вам краще підтримуваний інтерфейс, ніж пряме редагування відрендереного YAML. Якщо вам потрібен один тимчасовий під для налагодження, звичайні маніфести простіші за побудову ієрархії каталогів навколо нього.
Інший корисний спосіб вирішити — запитати, хто має змогти переглянути зміну. Оверлеї Kustomize дружні до рецензентів Kubernetes, бо фінальний намір лишається близьким до стандартних маніфестів: патч Deployment усе одно виглядає як частина Deployment, а трансформер образів усе одно називає образ. Значення Helm можуть бути чистішими для пакованого ПЗ, але зв’язок між значенням і відрендереним об’єктом може потребувати знання чарта. Звичайні маніфести найлегше читати для одноразової роботи, але вони не дають вбудованої відповіді, коли той самий об’єкт потребує контрольованих відмінностей між середовищами.
Неправильне рішення часто виявляється як тертя під час зміни. Якщо кожна тека середовища містить скопійований YAML, звичайні маніфести перевищили свій корисний розмір. Якщо репозиторій Kustomize починає симулювати умовні оператори, цикли та придатні для повторного використання функції, команда, можливо, намагається використати Kustomize як мову шаблонів. Якщо чарт Helm має лише один Deployment і три значення, Helm може бути більшою машинерією, ніж потребує завдання.
| Аспект | Звичайні маніфести | Kustomize | Helm |
|---|---|---|---|
| Основна модель | Застосувати YAML-файли безпосередньо. | Відрендерити бази плюс оверлеї. | Відрендерити чарти із шаблонами та значеннями. |
| Найкраща відповідність | Одне середовище чи прості демонстрації. | Власні маніфести з контрольованими відмінностями середовищ. | Паковані застосунки, залежності, життєвий цикл релізів. |
| Мова шаблонів | Немає. | Немає. | Шаблони Go. |
Вбудовано в kubectl | Так, через звичайне застосування. | Так, через kubectl apply -k і kubectl kustomize. | Ні, окремий Helm CLI. |
| Історія релізів | Немає. | Немає. | Так, релізи Helm відстежують ревізії. |
| Контроль дрейфу | Вручну, якщо не поєднано з GitOps. | Сильна структура репозиторію, сильніша з GitOps. | Сильніша модель релізів, сильніша з GitOps. |
| Швидкість на іспиті | Швидко для простих ресурсів. | Швидко для оверлеїв і завдань із патчами. | Корисно, коли завдання з чартами явні. |
Для CKA обирайте інструмент, який просить завдання. Якщо завдання каже застосувати конфігурацію Kustomize, використовуйте kubectl apply -k. Якщо воно просить переглянути каталог Kustomize, використовуйте kubectl kustomize. Якщо воно просить реліз Helm, використовуйте Helm. Не перетворюйте завдання Kustomize на завдання Helm, бо ви віддаєте перевагу Helm; перевіряльник очікує конкретного результату в кластері, а іноді й конкретного робочого процесу.
У реальних командах Kustomize часто поєднується з GitOps-контролерами, такими як Argo CD чи Flux. Репозиторій містить бази та оверлеї. Контролер спостерігає за шляхом оверлею й застосовує відрендерений вивід. Відкат тоді походить з історії Git чи поведінки синхронізації контролера, а не від самого Kustomize. Це здорове розділення: Kustomize рендерить конфігурацію, а GitOps керує безперервним узгодженням.
Частина 9: Робочий приклад — виправлення зламаного продакшен-оверлею
Розділ «Частина 9: Робочий приклад — виправлення зламаного продакшен-оверлею»Сценарій вправи: команда повідомляє, що kubectl apply -k webapp/overlays/prod/ зазнає невдачі після прибирання каталогів. База все ще існує, але оверлей не може її знайти. Замість випадкового редагування спершу налагодьте шлях рендерингу.
Зламаний оверлей:
apiVersion: kustomize.config.k8s.io/v1beta1kind: Kustomization
resources: - ../base
namePrefix: prod-namespace: productionОверлей живе в webapp/overlays/prod/. Звідти ../base означає webapp/overlays/base, якого не існує. Правильний шлях — ../../base, бо оверлей має піднятися до overlays, потім до webapp, потім спуститися в base.
Виправлений оверлей:
apiVersion: kustomize.config.k8s.io/v1beta1kind: Kustomization
resources: - ../../base
namePrefix: prod-namespace: productionТепер відрендеріть перед застосуванням:
kubectl kustomize webapp/overlays/prod/Припустімо, рендеринг успішний, але продакшен-завдання також вимагає п’яти реплік, а відрендерений Deployment усе ще має одну. Додайте патч із базовою назвою ресурсу, а не з фінальною назвою з префіксом.
apiVersion: apps/v1kind: Deploymentmetadata: name: webappspec: replicas: 5apiVersion: kustomize.config.k8s.io/v1beta1kind: Kustomization
resources: - ../../base
namePrefix: prod-namespace: production
patches: - path: patch-replicas.yamlНарешті, відрендеріть і перевірте точне поле:
kubectl kustomize webapp/overlays/prod/ | grep -A 8 "kind: Deployment"Цей приклад малий, але він моделює робочий процес старшого рівня. Ви виправили шлях, перевірили рендеринг, додали найменший патч, який виражав продакшен-відмінність, і перевірили відрендерене поле перед застосуванням. Важлива навичка — не запам’ятати саме цю розкладку файлів; це слідувати повторюваному шляху міркувань, коли вивід Kustomize вас дивує.
Цей шлях міркувань масштабується за межі прикладу, бо він тримає запитання вузьким на кожному кроці. Зламаний шлях виправляється в рецепті оверлею, а не в Deployment. Відсутня зміна реплік виправляється в цілі патча, а не копіюванням усієї бази в продакшен. Заплутана фінальна назва пояснюється порядком перетворень Kustomize, а не здогадом, що Kubernetes перейменував об’єкт після застосування. Коли ви можете назвати шар, якому належить симптом, Kustomize перестає здаватися магією й починає поводитися як детермінований крок збирання.
Чи знали ви?
Розділ «Чи знали ви?»- Kustomize вбудований у
kubectlпочинаючи з Kubernetes v1.14: це робить його практичним в іспитових середовищах, бо ви можете використовуватиkubectl kustomizeіkubectl apply -kбез встановлення окремого бінарного файлу. - Інструменти GitOps зазвичай розуміють шляхи Kustomize безпосередньо: Argo CD і Flux можуть спостерігати за каталогом оверлею, рендерити його й безперервно узгоджувати отримані ресурси з кластером.
- Назви згенерованих ConfigMap і Secret за замовчуванням чутливі до вмісту: суфікс хешу змінюється, коли змінюються вхідні дані генератора, що допомагає запускати розгортання Deployment, коли посилання шаблону пода переписуються.
- Kustomize можна поєднати з Helm у складніших робочих процесах: команди іноді рендерять чи розгортають вивід чарта Helm, а потім застосовують оверлеї Kustomize, але це додає складності й має бути виправдане реальною потребою.
Типові помилки
Розділ «Типові помилки»| Помилка | Чому вона трапляється | Як її виправити |
|---|---|---|
| Посилання на базу з неправильним відносним шляхом | Kustomize зазнає невдачі ще до того, як Kubernetes побачить будь-який ресурс, часто з помилкою накопичення чи «must resolve to a file». | Рахуйте від каталогу оверлею й перевірте за допомогою kubectl kustomize <overlay>. |
Забутий файл kustomization.yaml у базі чи оверлеї | Каталог, повний YAML, не є автоматично одиницею Kustomize. | Додайте apiVersion, kind: Kustomization і список resources до кожного каталогу Kustomize. |
| Написання патчів проти відрендерених назв із префіксом | Патчі не збігаються, бо Kustomize цілиться в оригінальну базову назву ресурсу. | Використовуйте metadata.name із бази, потім перевірте фінальну назву з префіксом у відрендереному виводі. |
| Використання широких перетворень міток, що мутують селектори | Селектори Deployment незмінні після створення, а Service можуть перестати добирати задумані поди. | Віддавайте перевагу трансформеру labels із includeSelectors: false для метаданих середовища. |
| Вимикання суфіксів хешу генератора без розуміння впливу на розгортання | Поди можуть далі працювати зі старою конфігурацією, бо назва ресурсу, на який посилаються, не змінюється. | Тримайте суфікси хешу ввімкненими, доки застаріла інтеграція не вимагатиме стабільних назв, тоді плануйте перезапуски окремо. |
| Застосування перед рендерингом | Валідний YAML усе одно може бути неправильним YAML, а застосування робить помилки живими. | Запустіть kubectl kustomize, потім dry-run чи diff перед kubectl apply -k. |
| Поводження з Kustomize як із Helm | Kustomize не має історії релізів, команди відкату, залежностей чартів чи мови шаблонів. | Використовуйте історію Git чи GitOps для відкату й обирайте Helm, коли вимагається керування пакетами. |
| Копіювання базових маніфестів у кожен оверлей | Спільні зміни дрейфують між середовищами, відтворюючи проблему, яку Kustomize має розв’язати. | Тримайте базу як джерело спільних ресурсів і кладіть лише відмінності в оверлеї. |
Тест
Розділ «Тест»Використовуйте ці запитання як вправи з міркування, а не як перевірки на пригадування. У кожному з них визначте шар, якому належить проблема, перш ніж обрати команду: вихідні файли, рендеринг Kustomize, валідація Kubernetes чи живий стан кластера. Ця звичка відповідає тому, як працює реальне усунення несправностей, бо одне невдале розгортання може зачіпати більше ніж один шар. Найкраща відповідь рідко є «запустити застосування знову»; зазвичай це «довести, який шар неправильний, виправити найменше, і знову переглянути».
-
Ваша команда розгортає той самий API в розробку, staging і продакшен. Розробник скопіював Deployment у всі три теки середовищ і змінив кількість реплік у кожній копії. Виправлення контексту безпеки пізніше застосували лише до продакшену. Як ви переробили б репозиторій із Kustomize і чому це зменшує ризик?
Відповідь
Створіть спільний каталог
base/, що містить Deployment, Service та будь-яку спільну конфігурацію. Потім створітьoverlays/dev/,overlays/staging/таoverlays/prod/, кожен зі своїмkustomization.yaml, що посилається на../../base. Кладіть зміни, специфічні для середовища, такі як простір імен, префікс назви, тег образу, кількість реплік і ліміти ресурсів, в оверлеї. Це зменшує ризик, бо виправлення контексту безпеки робиться один раз у базі й успадковується кожним середовищем. Оверлеї все одно виражають реальні відмінності, але вони більше не дублюють усе визначення робочого навантаження. -
Під час завдання CKA
kubectl apply -k webapp/overlays/staging/зазнає невдачі з повідомленням, що Kustomize не може накопичити ресурси з../base. Каталог бази —webapp/base, а оверлей —webapp/overlays/staging. Що ви маєте перевірити й змінити перед повторною спробою застосування?Відповідь
Перевірте відносний шлях від каталогу оверлею, а не від поточного каталогу вашої оболонки. З
webapp/overlays/stagingшлях../baseвказує наwebapp/overlays/base, що є неправильним. Правильний шлях зазвичай../../base. Змініть записresourcesоверлею на../../base, потім запустітьkubectl kustomize webapp/overlays/staging/, щоб перевірити рендеринг перед застосуванням. -
Продакшен-оверлей використовує
namePrefix: prod-. Файл патча цілиться вmetadata.name: prod-webapp, але відрендерений Deployment усе ще має стару кількість реплік. Фінальний об’єкт називаєтьсяprod-webapp. Чому патч не спрацював і яка правильна назва цілі патча?Відповідь
Kustomize зіставляє патчі з базовою ідентичністю ресурсу до застосування префікса назви. Хоча фінальний відрендерений об’єкт називається
prod-webapp, патч має цілитися в базову назву ресурсу, зазвичайwebapp. Змініть файл патча наmetadata.name: webapp, відрендеріть за допомогоюkubectl kustomizeі підтвердіть, щоspec.replicasзмінилося у фінальному виводі. -
Команда додає
commonLabels: { environment: prod }до оверлею для наявного Deployment. Застосування зазнає невдачі, бо селектор Deployment незмінний. Що сталося і як команді безпечніше додати мітки середовища?Відповідь
Перетворення міток, імовірно, спробувало додати мітку середовища також до полів селектора, а не лише до метаданих. Селектори Deployment незмінні після того, як Deployment існує, тож Kubernetes відхилив оновлення. Використовуйте трансформер
labelsізincludeSelectors: false, коли додаєте операційні метадані, які не мають змінювати селектори. Потім відрендеріть вивід і перевірте, що метадані й мітки шаблону пода доречні, тоді як незмінні селектори лишаються незміненими. -
Ваш застосунок читає налаштування з ConfigMap, згенерованого Kustomize. Після зміни файлу конфігурації й повторного застосування оверлею ви очікуєте розгортання, але Deployment не перезапускається. Які дві деталі, пов’язані з Kustomize, ви оглянули б першими?
Відповідь
По-перше, огляньте, чи ввімкнено суфіксування хешу генератора. Якщо встановлено
generatorOptions.disableNameSuffixHash: true, назва ConfigMap лишається стабільною й може не запускати зміну шаблону пода. По-друге, огляньте, чи посилання Deployment кероване так, щоб Kustomize міг переписати його на згенеровану назву. Відрендеріть оверлей і порівняйте назву згенерованого ConfigMap із назвою, на яку посилається Deployment. Якщо посилання не змінюється, у Kubernetes немає причини перекочувати поди. -
Колега хоче використати Kustomize для сторонньої стеки моніторингу, яка вже має підтримуваний чарт Helm із залежностями та примітками до релізу. Він також хоче історію відкатів. Як ви оцінили б цей вибір?
Відповідь
Kustomize найсильніший, коли команда володіє маніфестами й потребує оверлеїв для середовищ. Стороння стека моніторингу із залежностями чарта й очікуваною історією відкатів часто краще пасує до Helm. Helm надає пакування чартів, значення, залежності та ревізії релізів. Kustomize усе одно можна було б використати для налаштування відрендереного виводу в складнішому робочому процесі, але це додає складності. Рекомендація має ґрунтуватися на операційній вимозі: якщо керування пакетами й історія релізів є центральними, Helm, імовірно, є кращим основним інструментом.
-
Ви рендерите продакшен-оверлей і помічаєте два контейнери в Deployment:
webappіapp. У базі спочатку був лишеwebapp, а ваш патч мав додати ліміти ресурсів. Що ймовірно спричинило другий контейнер і як ви це виправите?Відповідь
Стратегічний merge-патч, імовірно, використав неправильну назву контейнера. Стратегічне злиття Kubernetes використовує
nameяк ключ злиття для списку контейнерів, тож запис патча з назвоюappне змінює наявний контейнерwebapp; він може створити новий запис контейнера. Виправте патч, змінивши назву контейнера наwebapp, відрендеріть оверлей знову й перевірте, що є один контейнер з очікуваними запитами та лімітами ресурсів.
Практична вправа
Розділ «Практична вправа»Завдання: побудувати, оглянути, застосувати й усунути несправності структури Kustomize для вебзастосунку з оверлеями розробки та продакшену.
Ця вправа слідує тій самій послідовності, яку ви маєте використовувати на іспиті: створіть базу, додайте простий оверлей, додайте продакшен-оверлей, відрендеріть перед застосуванням, валідуйте за допомогою dry-run, застосовуйте лише після того, як вивід правильний, а потім приберіть. Команди написані для запуску в оболонці з доступним kubectl і робочим кластером Kubernetes.
Вправа навмисно повторює команди рендерингу частіше, ніж міг би квапливий оператор. Це повторення є суттю. Ви тренуєте себе сприймати відрендерений YAML як контракт між репозиторієм і кластером, а не як необов’язковий діагностичний артефакт. Коли вивід виглядає неправильно, зупиніться в репозиторії й виправте вхідні дані Kustomize. Коли вивід виглядає правильно, але API-сервер його відхиляє, переключіть увагу на обмеження кластера, такі як простори імен, незмінні поля, політика допуску та дозволи.
Крок 1: створіть структуру каталогів
Розділ «Крок 1: створіть структуру каталогів»mkdir -p webapp/basemkdir -p webapp/overlays/devmkdir -p webapp/overlays/prodmkdir -p webapp/overlays/prod/configКрок 2: створіть базовий Deployment
Розділ «Крок 2: створіть базовий Deployment»cat > webapp/base/deployment.yaml << 'EOF'apiVersion: apps/v1kind: Deploymentmetadata: name: webapp labels: app.kubernetes.io/name: webapp app.kubernetes.io/component: frontendspec: replicas: 1 selector: matchLabels: app.kubernetes.io/name: webapp app.kubernetes.io/component: frontend template: metadata: labels: app.kubernetes.io/name: webapp app.kubernetes.io/component: frontend spec: containers: - name: webapp image: nginx:1.25 ports: - containerPort: 80 envFrom: - configMapRef: name: webapp-config resources: requests: memory: "64Mi" cpu: "100m"EOFКрок 3: створіть базовий Service
Розділ «Крок 3: створіть базовий Service»cat > webapp/base/service.yaml << 'EOF'apiVersion: v1kind: Servicemetadata: name: webapp labels: app.kubernetes.io/name: webappspec: selector: app.kubernetes.io/name: webapp app.kubernetes.io/component: frontend ports: - name: http port: 80 targetPort: 80EOFКрок 4: створіть базовий kustomization
Розділ «Крок 4: створіть базовий kustomization»cat > webapp/base/kustomization.yaml << 'EOF'apiVersion: kustomize.config.k8s.io/v1beta1kind: Kustomization
resources: - deployment.yaml - service.yaml
configMapGenerator: - name: webapp-config literals: - LOG_LEVEL=debug - FEATURE_FLAGS=localEOFКрок 5: відрендеріть базу й огляньте згенеровані назви
Розділ «Крок 5: відрендеріть базу й огляньте згенеровані назви»kubectl kustomize webapp/base/Шукайте назву згенерованого ConfigMap і посилання Deployment на цю назву. Вони мають збігтися після того, як Kustomize перепише посилання. Якщо Deployment усе ще посилається на простий webapp-config, тоді як згенерований ConfigMap має суфікс, зупиніться й огляньте YAML, перш ніж рухатися далі.
Крок 6: створіть оверлей розробки
Розділ «Крок 6: створіть оверлей розробки»cat > webapp/overlays/dev/kustomization.yaml << 'EOF'apiVersion: kustomize.config.k8s.io/v1beta1kind: Kustomization
resources: - ../../base
namePrefix: dev-namespace: development
labels: - pairs: environment: dev app.kubernetes.io/managed-by: kustomize includeSelectors: false
images: - name: nginx newTag: "1.25"EOFКрок 7: відрендеріть розробку й перевірте перетворення
Розділ «Крок 7: відрендеріть розробку й перевірте перетворення»kubectl kustomize webapp/overlays/dev/Підтвердіть, що назви починаються з dev-, ресурси з простором імен використовують development, образ — nginx:1.25, а мітки селектора все ще збігаються з мітками шаблону пода, потрібними для Service і Deployment.
Крок 8: створіть вхідні дані продакшен-конфігурації
Розділ «Крок 8: створіть вхідні дані продакшен-конфігурації»cat > webapp/overlays/prod/config/app.properties << 'EOF'LOG_LEVEL=infoFEATURE_FLAGS=checkout-v2REQUEST_TIMEOUT_SECONDS=10EOFКрок 9: створіть продакшен-патчі
Розділ «Крок 9: створіть продакшен-патчі»cat > webapp/overlays/prod/patch-replicas.yaml << 'EOF'apiVersion: apps/v1kind: Deploymentmetadata: name: webappspec: replicas: 5EOFcat > webapp/overlays/prod/patch-resources.yaml << 'EOF'apiVersion: apps/v1kind: Deploymentmetadata: name: webappspec: template: spec: containers: - name: webapp resources: requests: memory: "256Mi" cpu: "250m" limits: memory: "512Mi" cpu: "500m"EOFКрок 10: створіть продакшен-оверлей
Розділ «Крок 10: створіть продакшен-оверлей»cat > webapp/overlays/prod/kustomization.yaml << 'EOF'apiVersion: kustomize.config.k8s.io/v1beta1kind: Kustomization
resources: - ../../base
namePrefix: prod-namespace: production
labels: - pairs: environment: production app.kubernetes.io/managed-by: kustomize includeSelectors: false
images: - name: nginx newTag: "1.25-alpine"
configMapGenerator: - name: webapp-config behavior: replace files: - config/app.properties
patches: - path: patch-replicas.yaml - path: patch-resources.yamlEOFКрок 11: відрендеріть продакшен і перевірте конкретні поля
Розділ «Крок 11: відрендеріть продакшен і перевірте конкретні поля»kubectl kustomize webapp/overlays/prod/kubectl kustomize webapp/overlays/prod/ | grep -E "name:|namespace:|replicas:|image:|memory:|cpu:"Продакшен-Deployment має називатися з префіксом prod-, працювати в просторі імен production, використовувати п’ять реплік, використовувати nginx:1.25-alpine та містити суворіші запити й ліміти ресурсів.
Крок 12: валідуйте без зміни кластера
Розділ «Крок 12: валідуйте без зміни кластера»kubectl apply --dry-run=client -k webapp/overlays/prod/Якщо ваш кластер підтримує відповідну серверну валідацію, також запустіть:
kubectl apply --dry-run=server -k webapp/overlays/prod/Крок 13: застосуйте розробку й продакшен
Розділ «Крок 13: застосуйте розробку й продакшен»kubectl create namespace developmentkubectl create namespace productionkubectl apply -k webapp/overlays/dev/kubectl apply -k webapp/overlays/prod/Якщо будь-який простір імен уже існує, команда створення може повідомити, що він уже існує. У середовищі для практики ви можете продовжити, якщо простір імен наявний і у вас є дозвіл його використовувати.
Крок 14: перевірте стан кластера
Розділ «Крок 14: перевірте стан кластера»kubectl get deploy,svc,configmap -n developmentkubectl get deploy,svc,configmap -n productionkubectl get deploy prod-webapp -n production -o jsonpath='{.spec.replicas}{"\n"}'kubectl get deploy prod-webapp -n production -o jsonpath='{.spec.template.spec.containers[0].image}{"\n"}'Крок 15: навмисно зламайте й виправте один оверлей
Розділ «Крок 15: навмисно зламайте й виправте один оверлей»Відредагуйте webapp/overlays/prod/kustomization.yaml і тимчасово змініть ../../base на ../base. Потім запустіть:
kubectl kustomize webapp/overlays/prod/Прочитайте повідомлення про помилку, виправте шлях і відрендеріть знову. Цей навмисний збій будує діагностичну звичку, потрібну вам під тиском іспиту.
Критерії успіху
Розділ «Критерії успіху»- Ви можете пояснити, чому база містить спільні ресурси, але не специфічні для середовища продакшен-налаштування.
- Ви можете відрендерити базу й оверлей перед застосуванням будь-якого з них.
- Ви можете використати
namePrefix,namespace,labels,images, патчі та генератори в робочому оверлеї. - Ви можете пояснити, чому продакшен-патчі цілять у
metadata.name: webappзамістьprod-webapp. - Ви можете перевірити, що назви згенерованих ConfigMap і посилання Deployment збігаються у відрендереному виводі.
- Ви можете діагностувати й виправити зламаний відносний шлях в оверлеї.
- Ви можете валідувати за допомогою dry-run перед застосуванням ресурсів до кластера.
- Ви можете прибрати все, створене вправою.
Прибирання
Розділ «Прибирання»kubectl delete -k webapp/overlays/dev/kubectl delete -k webapp/overlays/prod/kubectl delete namespace development productionrm -rf webapp/Тренувальні вправи
Розділ «Тренувальні вправи»Вправа 1: попередній перегляд перед застосуванням
Розділ «Вправа 1: попередній перегляд перед застосуванням»Створіть крихітну базу Kustomize й доведіть собі, що попередній перегляд не змінює кластер. Ця вправа тренує найбезпечніший перший хід для будь-якого іспитового завдання, що передбачає -k.
mkdir -p drill-previewcat > drill-preview/deployment.yaml << 'EOF'apiVersion: apps/v1kind: Deploymentmetadata: name: preview-demospec: replicas: 1 selector: matchLabels: app: preview-demo template: metadata: labels: app: preview-demo spec: containers: - name: nginx image: nginx:1.25EOF
cat > drill-preview/kustomization.yaml << 'EOF'apiVersion: kustomize.config.k8s.io/v1beta1kind: Kustomization
resources: - deployment.yamlEOF
kubectl kustomize drill-preview/kubectl get deploy preview-demokubectl apply -k drill-preview/kubectl get deploy preview-demokubectl delete -k drill-preview/rm -rf drill-previewВправа 2: виправлення назви патча
Розділ «Вправа 2: виправлення назви патча»Ця вправа створює патч, який цілить у неправильну назву. Ваше завдання — відрендерити, помітити, що зміни бракує, виправити ціль патча й відрендерити знову.
mkdir -p drill-patch/base drill-patch/overlaycat > drill-patch/base/deployment.yaml << 'EOF'apiVersion: apps/v1kind: Deploymentmetadata: name: apispec: replicas: 1 selector: matchLabels: app: api template: metadata: labels: app: api spec: containers: - name: api image: nginx:1.25EOF
cat > drill-patch/base/kustomization.yaml << 'EOF'apiVersion: kustomize.config.k8s.io/v1beta1kind: Kustomization
resources: - deployment.yamlEOF
cat > drill-patch/overlay/patch-replicas.yaml << 'EOF'apiVersion: apps/v1kind: Deploymentmetadata: name: prod-apispec: replicas: 3EOF
cat > drill-patch/overlay/kustomization.yaml << 'EOF'apiVersion: kustomize.config.k8s.io/v1beta1kind: Kustomization
resources: - ../base
namePrefix: prod-
patches: - path: patch-replicas.yamlEOF
kubectl kustomize drill-patch/overlay/Виправте patch-replicas.yaml так, щоб назва цілі була api, потім відрендеріть знову й підтвердіть, що фінальний Deployment prod-api має три репліки.
rm -rf drill-patchВправа 3: спостереження за хешем генератора
Розділ «Вправа 3: спостереження за хешем генератора»Ця вправа показує, чому назви згенерованих ConfigMap змінюються, коли змінюється вміст. Відрендеріть один раз, змініть літерал і відрендеріть знову.
mkdir -p drill-generatorcat > drill-generator/kustomization.yaml << 'EOF'apiVersion: kustomize.config.k8s.io/v1beta1kind: Kustomization
configMapGenerator: - name: app-config literals: - LOG_LEVEL=infoEOF
kubectl kustomize drill-generator/
cat > drill-generator/kustomization.yaml << 'EOF'apiVersion: kustomize.config.k8s.io/v1beta1kind: Kustomization
configMapGenerator: - name: app-config literals: - LOG_LEVEL=debugEOF
kubectl kustomize drill-generator/rm -rf drill-generatorВправа 4: оберіть правильний інструмент
Розділ «Вправа 4: оберіть правильний інструмент»Прочитайте кожен сценарій і вирішіть, чи звичайні маніфести, Kustomize чи Helm є найкращим основним інструментом. Потім порівняйте свою відповідь із поясненням.
- У вас є один Namespace і один под для налагодження для швидкого завдання з усунення несправностей.
- Ви володієте вебзастосунком і потребуєте варіантів для dev, staging і продакшену.
- Вам треба встановити сторонній контролер ingress із залежностями та відкатом релізів.
Запропоноване міркування
Звичайних маніфестів достатньо для швидкого пода налагодження, бо немає придатної для повторного використання структури середовищ. Kustomize пасує до власного вебзастосунку, бо база може тримати спільне робоче навантаження, тоді як оверлеї тримають відмінності середовищ. Helm пасує до стороннього контролера ingress, бо пакування чартів, залежності, значення та історія релізів є частиною вимоги.
Джерела
Розділ «Джерела»- https://kubernetes.io/docs/tasks/manage-kubernetes-objects/kustomization/
- https://kubernetes.io/docs/reference/kubectl/generated/kubectl_kustomize/
- https://kubernetes.io/docs/reference/kubectl/generated/kubectl_apply/
- https://kubernetes.io/docs/reference/kubectl/generated/kubectl_diff/
- https://kubernetes.io/docs/concepts/workloads/controllers/deployment/
- https://kubernetes.io/docs/concepts/services-networking/service/
- https://kubernetes.io/docs/concepts/configuration/configmap/
- https://kubernetes.io/docs/concepts/configuration/secret/
- https://kubernetes.io/docs/concepts/overview/working-with-objects/labels/
- https://kubernetes.io/docs/concepts/overview/working-with-objects/names/
- https://kubectl.docs.kubernetes.io/references/kustomize/kustomization/
- https://argo-cd.readthedocs.io/en/stable/user-guide/kustomize/
- https://fluxcd.io/flux/components/kustomize/kustomizations/
- kubernetes.io: kustomization — Сторінка завдання Kustomize у документації Kubernetes прямо стверджує, що kubectl підтримує файли kustomization починаючи з 1.14, і показує точні команди.
- kubernetes.io: kubectl kustomize — Довідник kubectl kustomize явно каже, що аргумент каталогу має містити
kustomization.yaml. - kubernetes.io: deployment — Документація Deployment прямо стверджує і вимогу зіставлення міток селектора й шаблона, і незмінність селектора.
- kubernetes.io: namespaces — Документація просторів імен явно розрізняє об’єкти з простором імен і об’єкти з областю всього кластера.
- kubernetes.io: update api object kubectl patch — Завдання kubectl patch показує, що списки контейнерів використовують стратегічне злиття з
nameяк ключем злиття, і демонструє поведінку злиття списків. - rfc-editor.org: rfc6902 — RFC 6902 є основним стандартом, що визначає документи JSON Patch як упорядковані послідовності операцій над JSON-локаціями.
- kubernetes.io: kubectl diff — Довідник kubectl diff визначає diff саме в цих термінах і документує
-k/--kustomize. - argo-cd.readthedocs.io: kustomize — Посібник Argo CD з Kustomize прямо каже, що Argo рендерить за допомогою Kustomize, коли шлях містить
kustomization.yaml, і радить вказувати шлях на оверлей. - fluxcd.io: kustomizations — Документація Flux Kustomization прямо описує збирання зі шляху, поводження з простором імен, валідацію та поведінку застосування.
- helm.sh: charts — Документація чартів Helm прямо охоплює рендеринг шаблонів Go, файли значень та залежності чартів.
Наступний модуль
Розділ «Наступний модуль»Модуль 1.5: CRD та оператори — розширення Kubernetes за допомогою Custom Resource Definitions.