Модуль 2.3: Kustomize
Складність:
[СЕРЕДНЯ]— налаштування Kubernetes без шаблонівЧас на проходження: 40-50 хвилин
Передумови: Модуль 2.1 (Деплойменти), базове розуміння YAML
Результати навчання
Розділ «Результати навчання»Після завершення цього модуля ви зможете:
- Проєктувати структуру баз (base) та накладок (overlay) Kustomize, що зберігає спільні маніфести Kubernetes стабільними, водночас допускаючи зміни, специфічні для середовища.
- Впроваджувати трансформації, перевизначення образів, генератори та патчі за допомогою
kubectl kustomizeтаkubectl apply -k. - Діагностувати збої рендерингу та застосування, спричинені неправильними шляхами, невідповідністю цілі патча, змінами селекторів або поведінкою згенерованих імен.
- Оцінювати, коли Kustomize краще підходить для розгортання, ніж Helm, і коли модель пакування Helm є правильним компромісом.
Чому цей модуль важливий
Розділ «Чому цей модуль важливий»Гіпотетичний сценарій: ваша команда володіє одним вебзастосунком, який працює у середовищах розробки, стейджингу та продакшену. Deployment, Service, мітки та розкладка портів здебільшого ідентичні, але продакшен потребує більше реплік, іншого простору імен, фіксованого тегу образу та суворіших налаштувань середовища виконання. Якщо кожне середовище володіє повною копією YAML, ці копії починають розходитися. Одна людина оновлює селектор у розробці, інша оновлює образ у продакшені, а третя забуває, що Service залежить від тієї самої форми мітки в кожному середовищі.
Kustomize вирішує цю проблему, розглядаючи Kubernetes YAML як вихідний матеріал, замість того щоб замінювати його мовою шаблонів. База містить звичайні маніфести, які kubectl уже міг би застосувати. Накладка посилається на цю базу, а потім нашаровує зміни, такі як мітки, простори імен, теги образів, згенеровані ConfigMap або точкові патчі. Результат — це все ще звичайний Kubernetes YAML, але він рендериться з невеликого графа композиції, який робить спільний задум видимим, а специфічний для середовища задум — явним.
Це важливо для CKAD, оскільки Kustomize вбудовано в kubectl, а іспит винагороджує швидкі, надійні командні звички. Це також важливо поза іспитом, тому що чиста структура Kustomize дає рецензентам корисне запитання: «Що змінилося між dev і prod?» Замість того щоб читати два майже однакові файли Deployment рядок за рядком, вони можуть перевірити накладку й побачити лише налаштування. У цьому модулі ви побудуєте таку структуру, попередньо переглянете відрендерений вивід, застосуєте його за допомогою kubectl apply -k і налагодите збої, які зазвичай з’являються, коли накладки стають чимось більшим, ніж іграшковий приклад.
Kustomize як шаровий Kubernetes YAML
Розділ «Kustomize як шаровий Kubernetes YAML»Kustomize починається з навмисно простої ідеї: зберігати YAML ресурсу валідним до налаштування, а потім описувати правки поруч із ним. Це відрізняється від текстового шаблону. Шаблон Helm може містити умови, цикли та значення, які не утворюють валідного об’єкта Kubernetes аж до моменту рендерингу. Kustomize надає перевагу меншій поверхні: почати з реальних об’єктів, а потім додати трансформації, які достатньо знають про посилання Kubernetes, щоб тримати пов’язані поля узгодженими, коли імена та простори імен змінюються.
Найважливіша ментальна модель полягає в тому, що база — це не абстрактний батьківський клас. Це каталог ресурсів, які можна відрендерити самостійно, а накладка — це інший каталог, який імпортує базу й застосовує контрольований набір змін. Для невеликого застосунку база може містити один Deployment і один Service. Для більшого застосунку вона також може включати ServiceAccount, NetworkPolicy, ConfigMap та ресурси Ingress. Накладка не повинна повторювати ці файли, якщо весь об’єкт не є справді іншим.
| Концепт | Опис |
|---|---|
| База (Base) | Початкові, незмінені ресурси Kubernetes |
| Накладка (Overlay) | Налаштування, застосовані поверх бази |
| Патч (Patch) | Модифікації конкретних полів |
| kustomization.yaml | Файл, що визначає, що саме налаштовувати |
Таблиця коротка, але операційна відмінність важлива. База — це місце, куди ви кладете тривку форму застосунку. Накладка — це місце, куди ви кладете локальне рішення для конкретного середовища, кластера, орендаря чи завдання іспиту. Патч — це місце, де ви кажете: «для цього відрендереного варіанта зміни це поле в тому об’єкті». Файл kustomization.yaml — це специфікація матеріалів і план трансформацій для каталогу.
┌─────────────────────────────────────────────────────────┐│ Kustomize Flow │├─────────────────────────────────────────────────────────┤│ ││ Base Overlay ││ ┌─────────────┐ ┌─────────────┐ ││ │ deployment │───────▶│ + replicas │ ││ │ service │ │ + env vars │ ││ │ configmap │ │ + labels │ ││ └─────────────┘ └─────────────┘ ││ │ │ ││ └─────────┬───────────┘ ││ ▼ ││ ┌─────────────┐ ││ │ Combined │ ││ │ Resources │ ││ └─────────────┘ ││ │ ││ ▼ ││ kubectl apply -k ./ ││ │└─────────────────────────────────────────────────────────┘Діаграма показує конвеєр рендерингу, а не контролер, що працює в кластері. Kustomize виконується саме на боці клієнта, коли ви запускаєте kubectl kustomize, kubectl apply -k або kubectl delete -k. API-сервер отримує фінальні відрендерені об’єкти точно так само, як він отримав би ті самі об’єкти з окремих файлів YAML. Це означає, що налагодження починається ще до того, як ви торкнетеся кластера: відрендеріть вивід, перевірте імена, селектори, образи, простори імен та згенеровані посилання, а потім застосовуйте, лише коли відрендерений YAML відповідає бажаному стану.
Зробіть паузу й передбачте: якщо селектор Service дорівнює app: web у базі, а накладка змінює мітки і на шаблоні Pod’а Deployment, і на селекторі Service, що зламається, якщо змінити лише одну сторону? Відповідь має керувати тим, як ви використовуєте трансформери міток. Селектори — це контракти між об’єктами. Зміна мітки, яка досягає Pod’ів, але не Service’ів, може зробити так, що розгортання виглядатиме справним, тоді як трафік тихо йтиме в нікуди.
Kustomize також має межу, яку легко пропустити. Він чудово компонує відомий набір маніфестів, але не намагається стати мовою програмування загального призначення. Коли вашому розгортанню потрібні опціональні підчарти, глибоке умовне розгалуження, повторно використовувані версіоновані пакети або схеми значень на час встановлення, Helm може виявитися кращим інструментом. Коли ваша задача — «ті самі ресурси, інші деталі середовища», Kustomize тримає конфігурацію ближче до API Kubernetes.
Побудова базової kustomization
Розділ «Побудова базової kustomization»Базовий каталог має бути нудним. У цьому й полягає суть. Ви хочете, щоб колега відкрив базу й побачив анатомію застосунку, не шукаючи серед специфічного для середовища шуму. Якщо базовий Deployment каже, що контейнер слухає порт 80, Service вибирає app: web, а ім’я ресурсу — web-app, ці рішення мають залишатися істинними в усіх середовищах, доки реальна межа середовища не вимагатиме відмінності.
Найменша корисна структура має kustomization.yaml поруч із ресурсами, якими він керує. Kustomize виявляє лише ті ресурси, що перелічені в цьому файлі; він не застосовує автоматично кожен файл YAML у каталозі. Цей явний перелік запобігає несподіваним застосуванням, коли поруч лежать тимчасові файли, чернеткові маніфести чи старі експерименти. Він також дає вам зручний для іспиту контрольний список: якщо відрендереного об’єкта бракує, спершу перевірте, чи його перелічено під resources:.
my-app/├── kustomization.yaml├── deployment.yaml└── service.yamlapiVersion: kustomize.config.k8s.io/v1beta1kind: Kustomization
resources:- deployment.yaml- service.yamlПоля apiVersion та kind ідентифікують файл як конфігурацію Kustomize, а не як робочий об’єкт Kubernetes. Під resources кожен шлях вказується відносно каталогу, що містить цей kustomization.yaml. Ресурсом може бути файл, каталог, що містить іншу kustomization, або в деяких робочих процесах Kustomize — віддалене посилання, але для роботи з CKAD очікуйте локальних файлів і локальних баз. Тримайте шляхи простими й перевіряйте їх із того каталогу, який ви рендерите.
# Preview what will be appliedkubectl kustomize ./my-app/
# Apply the kustomizationkubectl apply -k ./my-app/
# Delete resourceskubectl delete -k ./my-app/Попередній перегляд і застосування — це різні звички. kubectl kustomize ./my-app/ друкує відрендерений YAML і завершується, не змінюючи кластер. kubectl apply -k ./my-app/ рендерить ту саму композицію й надсилає її API-серверу. kubectl delete -k ./my-app/ рендерить той самий набір об’єктів і видаляє ці об’єкти за ідентичністю. Якщо шлях до каталогу неправильний, файл ресурсу відсутній або патч не збігається, попередній перегляд виявить це, перш ніж API-сервер щось побачить.
Сценарій вправи: вам дістається каталог, що містить deployment.yaml, service.yaml та old-service.yaml, але лише на перші два є посилання в resources:. Колега запитує, чому old-service.yaml не розгорнувся. Правильна відповідь — не «Kustomize його пропустив». Правильна відповідь у тому, що kustomization.yaml є авторитетним переліком ресурсів, а неперелічені файли ігноруються. Така явність безпечніша за обхід каталогу за шаблоном, тому що вона робить членство в розгортанні придатним для рецензування.
Для іспитної швидкості використовуйте kubectl kustomize як локальний переглядач diff. Перегляньте відрендерені metadata.name, metadata.namespace, селектори, образ контейнера та результат патча перед застосуванням. Якщо ваш вивід довгий, передавайте його через less локально, коли він доступний, але тримайте основну команду безпечною для копіювання-вставлення. У стиснених лабораторіях простого kubectl kustomize ./path | sed -n '1,120p' часто достатньо, щоб підтвердити перші імена ресурсів і поля, які ви змінили.
Трансформації: імена, мітки, простори імен та образи
Розділ «Трансформації: імена, мітки, простори імен та образи»Трансформації — це широкі правки, які Kustomize може застосувати до всіх ресурсів. Вони корисні, коли зміна не прив’язана до одного поля в одному об’єкті. Простір імен належить майже кожному ресурсу з простором імен. Префікс імені може застосовуватися до всіх об’єктів у накладці, щоб ресурси розробки та продакшену могли співіснувати. Мітку можна додати до ресурсів для позначення власника, відстеження середовища або вибірки. Цінність трансформації — у послідовності: одне оголошення передбачувано змінює відрендерений набір.
Мітки заслуговують на особливу увагу, бо одні мітки є описовими, а інші — селекторами. Описову мітку можна вільно додавати, щоб допомогти людям і автоматизації знаходити об’єкти. Мітка-селектор є частиною зв’язку між контролером, його Pod’ами та Service’ами, які маршрутизують трафік до цих Pod’ів. Новіший трансформер labels у Kustomize дозволяє вам вибрати, чи має мітка бути включеною до селекторів і шаблонів Pod’ів. Цей вибір безпечніший за бездумне додавання міток усюди.
apiVersion: kustomize.config.k8s.io/v1beta1kind: Kustomization
resources:- deployment.yaml- service.yaml
labels:- pairs: app: my-app environment: production includeSelectors: true includeTemplates: trueВикористовуйте includeSelectors: true лише тоді, коли ви справді маєте намір змінити селектори як частину відрендереної ідентичності. Якщо і Service, і Deployment починаються зі збіжних селекторів, Kustomize може зберегти зв’язок узгодженим, коли трансформер застосовується до обох сторін. Якщо ви додаєте операційну мітку, таку як owner: platform або cost-center: shared, ви часто не хочете, щоб ця мітка потрапляла до незмінних селекторів. Зміни селекторів можуть змусити заміну контролера або спричинити збої застосування на наявних Deployment’ах.
commonAnnotations: owner: team-platform managed-by: kustomizeАнотації зазвичай безпечніші для метаданих, які не повинні брати участі у вибірці. Вони можуть містити підказки щодо власника, нотатки розгортання чи маркери інструментів, не змінюючи того, як Service’и знаходять Pod’и. Kustomize може додавати спільні анотації до всіх ресурсів, але вам усе одно слід уникати розміщення там секретів чи мінливих значень. Зміна анотації на шаблоні Pod’а може спричинити розгортання, що корисно для деяких робочих процесів і несподівано для інших.
namePrefix: prod-nameSuffix: -v1Результат: deployment стає prod-deployment-v1
Трансформації імен виглядають простими, але вони є однією з найсильніших можливостей Kustomize, тому що він розуміє поширені посилання на імена в Kubernetes. Якщо Deployment посилається на згенерований ConfigMap, або на ServiceAccount посилається шаблон Pod’а, Kustomize може оновити ці посилання, коли ім’я трансформується. Це набагато безпечніше за пошук-і-заміну, тому що імена ресурсів Kubernetes з’являються в різних полях залежно від виду (kind) та версії API.
namespace: productionУсі ресурси будуть розгорнуті в цьому просторі імен.
Трансформер простору імен — це хороший приклад того, чому попередній перегляд має значення. Ресурси з областю кластера не отримують простору імен, тому що API Kubernetes його не дозволяє. Ресурси з простором імен отримують. Якщо простору імен не існує, kubectl apply -k зазнає невдачі, коли спробує створити там об’єкти з простором імен. Kustomize рендерить бажаний YAML; він не створює простори імен неявно, доки об’єкт Namespace не перелічено як ресурс.
apiVersion: kustomize.config.k8s.io/v1beta1kind: Kustomization
resources:- deployment.yaml
images:- name: nginx newTag: "1.21"
- name: myapp newName: my-registry.com/myapp newTag: v2.0.0Перевизначення образів — це найчистіший спосіб перенести одну базу між середовищами, не редагуючи Deployment. База може використовувати читабельний образ, такий як nginx:1.20 чи myapp:latest, тоді як накладка фіксує обраний середовищем тег або реєстр. Поле name збігається з ім’ям образу, знайденим у ресурсі. newTag змінює тег, а newName змінює частину репозиторію. Це тримає просування образу видимим у накладці, а не похованим у скопійованому Deployment.
Перш ніж це запускати, який вивід ви очікуєте, якщо Deployment використовує nginx:1.20, а накладка оголошує images: [{ name: nginx, newTag: "1.21" }]? Ви маєте очікувати, що відрендерений Deployment збереже те саме ім’я контейнера й інші поля, але поле образу має стати nginx:1.21. Якщо вивід не змінюється, перевірте, чи ім’я образу в ресурсі справді збігається з nginx, або чи образ уже записаний з іншим префіксом реєстру.
Ці трансформації компонуються, тож порядок концептуально має значення, навіть коли ви не пишете його як скрипт. Kustomize читає ресурси, застосовує генератори, застосовує трансформації, розв’язує посилання й видає фінальні об’єкти. Під час налагодження перевіряйте фінальний YAML, а не припускайте, що трансформація застосувалася лише тому, що оголошення існує. Оголошення з неправильною ціллю або ім’ям образу, яке не збігається, шкідливе в найгірший спосіб: воно видає валідний YAML, який не містить зміни, яку ви мали на меті.
Генерування ConfigMap та Secret
Розділ «Генерування ConfigMap та Secret»ConfigMap і Secret часто є першими об’єктами, які змушують тих, хто навчається, оцінити Kustomize. У чистому Kubernetes ви можете створити їх як статичний YAML. У Kustomize генератори дозволяють вам описати джерело даних у kustomization.yaml, після чого Kustomize створює об’єкт і оновлює посилання. Важлива поведінка — суфікс хеша вмісту. За замовчуванням згенеровані ConfigMap і Secret отримують суфікс імені, похідний від їхнього вмісту, тож зміна даних породжує нове ім’я об’єкта.
Цей хеш корисний, тому що Pod’и не перезапускаються автоматично лише через те, що змінився вміст наявного ConfigMap. Якщо Deployment посилається на app-config-abc123, а дані генератора змінюються, Kustomize рендерить нове ім’я, таке як app-config-def456, і оновлює посилання Deployment. Ця зміна шаблону Pod’а спричиняє розгортання. Іншими словами, згенероване ім’я перетворює вміст конфігурації на частину ревізії робочого навантаження.
apiVersion: kustomize.config.k8s.io/v1beta1kind: Kustomization
resources:- deployment.yaml
configMapGenerator:- name: app-config literals: - LOG_LEVEL=info - API_URL=http://api.example.comІм’я згенерованого ConfigMap зазвичай не буде точно app-config. Воно включатиме суфікс, якщо ви не вимкнете цю поведінку. Посилання всередині відомих полів оновлюються, тому Deployment усе ще може казати, що хоче app-config у вихідному маніфесті, тоді як відрендерений вивід вказує на ім’я із суфіксом. Це ще одне місце, де попередній перегляд виводу навчає вас того, що побачить API-сервер.
configMapGenerator:- name: app-config files: - config.properties - settings.jsonГенерування з файлів корисне, коли конфігурація вже живе у форматах, схожих на застосункові. Кожен файл стає ключем у ConfigMap, якщо ви не використовуєте власне зіставлення ключів. Це тримає великі блоки конфігурації поза маніфестом Deployment, водночас залишаючи повний відрендерений результат придатним для перевірки. Для практики CKAD літерали швидше друкувати, але генерування на основі файлів поширене в реальних репозиторіях, тому що воно відображає те, як застосунки читають локальну конфігурацію.
Та сама kustomization може оголосити кілька генераторів Secret в одному переліку — літерали для облікових даних і файли для матеріалу TLS:
secretGenerator:- name: db-credentials literals: - username=admin - password=secret123- name: tls-certs files: - tls.crt - tls.key type: kubernetes.io/tlsSecret’и, згенеровані Kustomize, — це об’єкти Secret Kubernetes, а не система керування секретами. Згенерований YAML усе ще містить значення, закодовані в base64, з якими слід обережно поводитися в репозиторіях і логах. Для іспитних вправ значення-заповнювача достатньо, щоб продемонструвати механіку. У продакшені поєднуйте Kustomize зі схваленим робочим процесом для секретів, таким як sealed secrets, зовнішні контролери секретів або безпечний CI-процес, який вводить матеріал секрету поза публічним деревом сирцевого коду.
Зупиніться й подумайте: Kustomize додає суфікс хеша до згенерованих ConfigMap, наприклад app-config-abc123. Чому це може бути корисним? Корисна частина — не унікальність сама по собі. Корисна частина в тому, що зміна вмісту конфігурації стає зміною імені, а ця зміна імені оновлює посилання шаблону Pod’а. Тоді Kubernetes має чітку причину створити нові Pod’и з новою конфігурацією.
За замовчуванням Kustomize додає суфікс хеша до згенерованих ConfigMap і Secret:
app-configстаєapp-config-abc123- Посилання оновлюються автоматично
Вимкнути за допомогою (корисно, якщо застарілі системи вимагають фіксованих імен, хоча це запобігає автоматичним поступовим оновленням):
generatorOptions: disableNameSuffixHash: trueВимкнення суфікса — це компроміс, а не трюк для очищення. Фіксоване ім’я може бути необхідним, коли зовнішня система, старіший маніфест або ручний процес очікує точного імені об’єкта. Ціна в тому, що зміна даних може сама по собі не спричинити розгортання, тому що посилання шаблону Pod’а залишається незмінним. Якщо ви вимикаєте суфікс, вирішіть, як робоче навантаження підхопить зміни конфігурації. Це може означати ручний kubectl rollout restart, оновлення анотації або контролер, який стежить за ConfigMap.
Старий згенерований об’єкт може залишитися після оновлення, і це не автоматично є помилкою. Він може підтримувати відкати, тому що попередній ReplicaSet усе ще може посилатися на попереднє хешоване ім’я. У невеликому просторі імен старі згенеровані об’єкти легко помітити й очистити вручну. У довговічному середовищі вам потрібна політика очищення, яка поважає вікна відкату. Не видаляйте старі ConfigMap бездумно під час активного розслідування розгортання.
Патчі та композиція накладок
Розділ «Патчі та композиція накладок»Патчі призначені для змін, які настільки специфічні, що широкий трансформер був би надто грубим. Зміна всіх імен ресурсів належить трансформеру. Зміна кількості реплік одного Deployment належить патчу. Додавання обмежень ресурсів до кожного Deployment може бути точковим патчем із селектором виду (kind), але воно потребує перевірки, тому що переліки контейнерів та їхні імена різняться між застосунками. Патчі дають вам точність, а точність вимагає збігу з правильним об’єктом.
Найпоширеніший збій під час патчингу — це невідповідність цілі. Наприклад, патч називає my-app, але базовий Deployment насправді названо web-app. Або ж накладка додає namePrefix: prod-, і той, хто навчається, помилково думає, що патч має націлюватися на prod-web-app, а не на початкове ім’я. Патчі Kustomize зазвичай націлюються на ту ідентичність ресурсу, яку він має в базі ще до трансформацій, а вже потім трансформації застосовуються до фінального виводу. Коли ви сумніваєтеся, відрендеріть вивід і до, і після видалення патча, щоб наочно побачити, що саме змінилося.
apiVersion: kustomize.config.k8s.io/v1beta1kind: Kustomization
resources:- deployment.yaml
patches:- patch: |- apiVersion: apps/v1 kind: Deployment metadata: name: my-app spec: replicas: 5Цей вбудований патч читається як невеликий об’єкт Kubernetes, тому що це патч у стилі стратегічного злиття (strategic merge). Він ідентифікує об’єкт за видом і ім’ям, а потім надає лише ті поля, які слід додати або змінити. Патчу не потрібно повторювати весь Deployment. Саме тому патчі придатніші для рецензування, ніж копіювання повного об’єкта в накладку: рецензент бачить рівно те, яке поле перевизначається.
patches:- path: increase-replicas.yamlincrease-replicas.yaml:
apiVersion: apps/v1kind: Deploymentmetadata: name: my-appspec: replicas: 5Файли патчів кращі, коли патч складається з більш ніж кількох рядків або коли кілька накладок повторно використовують ту саму форму патча. Файл також тримає kustomization.yaml читабельним. Компроміс — навігація: людині, яка рецензує накладку, доводиться відкривати інший файл, щоб зрозуміти зміну. Для невеликих іспитних завдань вбудовані патчі швидкі. Для командних репозиторіїв файли патчів часто старіють краще, тому що їх можна назвати за наміром, наприклад increase-replicas.yaml чи add-resource-limits.yaml.
Для точних модифікацій:
patches:- target: kind: Deployment name: my-app patch: |- - op: replace path: /spec/replicas value: 5 - op: add path: /metadata/labels/version value: v2Патчі JSON корисні, коли вам потрібна точна операція, така як replace, add чи remove, за вказівником JSON. Вони менш поблажливі, ніж патчі стратегічного злиття, тому що шлях має збігатися зі структурою відрендереного об’єкта. Ця суворість корисна для хірургічних правок і ризикована для тих, хто навчається й не перевірив YAML. Якщо ви використовуєте патч JSON, переглядайте негайно й підтверджуйте, що модифіковане поле з’являється рівно там, де ви очікували.
Що сталося б, якби ваша накладка посилалася на ../../base, але базовий каталог було перейменовано на common? Ви маєте побачити помилку накопичення або шляху, перш ніж будь-що буде застосовано. Швидка діагностика — відрендерити накладку й прочитати шлях у помилці. Потім перевірте перелік resources: накладки, а не базові маніфести. Невдале посилання на ресурс живе в накладці, тому що саме там оголошено відносний шлях.
patches:- target: kind: Deployment patch: |- - op: add path: /spec/template/spec/containers/0/resources value: limits: memory: 256Mi cpu: 200mНацілювання на всі Deployment’и може заощадити час, але воно також приховує припущення. Вказівник JSON вище припускає, що перший контейнер — це той, який має отримати обмеження. У вправі CKAD з одним контейнером це нормально. У реальному багатоконтейнерному Pod’і індекс 0 може бути sidecar’ом, патерн ініціалізації може змінитися пізніше, або новий контейнер може бути вставлено перед застосунком. Надавайте перевагу іменованим патчам стратегічного злиття, коли ідентичність контейнера має значення, і використовуйте патчі з широкою ціллю лише тоді, коли структура ресурсу однорідна за політикою.
Патчинг має дотримуватися простого робочого процесу. Спершу відрендеріть саму базу, щоб ви точно знали її початкову форму. Потім відрендеріть накладку й перевірте лише ті поля, які мали змінитися. Нарешті застосуйте накладку тоді, коли відрендерений результат уже відповідає вашому наміру. Цей робочий процес ловить неправильні імена, неправильні шляхи та ненавмисні правки селекторів ще тоді, коли ціна помилки — усе ще лише локальна команда. Він також виробляє ту саму звичку CKAD: доводити коректність виводу, перш ніж змінювати стан кластера.
Накладки для середовищ
Розділ «Накладки для середовищ»Каталог накладки перетворює Kustomize з однокаталогової зручності на придатний для підтримки патерн розгортання. База каже, чим є застосунок. Кожна накладка каже, як цей застосунок має відрізнятися для однієї цілі. Розробка може використовувати одну репліку, простір імен розробки та швидкозмінний тег образу. Продакшен може використовувати більше реплік, простір імен продакшену, зафіксований тег релізу та суворішу конфігурацію. Спільна база залишається незмінною.
my-app/├── base/│ ├── kustomization.yaml│ ├── deployment.yaml│ └── service.yaml├── overlays/│ ├── dev/│ │ └── kustomization.yaml│ ├── staging/│ │ └── kustomization.yaml│ └── prod/│ └── kustomization.yamlЦя структура поширена, бо вона робить шляхи рецензування очевидними. Зміна під base/ впливає на кожну накладку, яка її імпортує. Зміна під overlays/prod/ впливає лише на продакшен. Це сильний сигнал власності. Вона також допомагає з міркуваннями про відкат: якщо продакшен зламався після зміни лише в накладці, ви можете зосередитися на накладці продакшену. Якщо кожне середовище зламалося після зміни в базі, починайте з бази.
apiVersion: kustomize.config.k8s.io/v1beta1kind: Kustomization
resources:- deployment.yaml- service.yamlБазова kustomization має уникати рішень про специфічний для середовища простір імен, репліки та просування образу, якщо тільки кожне середовище справді їх не поділяє. Базі цілком нормально включати стабільні мітки, які описують застосунок, але будьте обережні з мітками, що передбачають середовище чи канал релізу. База, яка вже каже environment: production, змушує кожну непродакшенну накладку це скасовувати, що є протилежністю чистій композиції.
apiVersion: kustomize.config.k8s.io/v1beta1kind: Kustomization
resources:- ../../base
namePrefix: dev-namespace: development
patches:- patch: |- apiVersion: apps/v1 kind: Deployment metadata: name: my-app spec: replicas: 1
images:- name: my-app newTag: dev-latestНакладка розробки навмисно невелика. Вона імпортує базу, додає префікс до імен, вибирає простір імен, встановлює одну репліку та вказує на тег образу розробки. Оскільки патч націлюється на базове ім’я my-app, накладка залишається читабельною, навіть попри те, що відрендерений Deployment буде названо dev-my-app. Цю відмінність варто практикувати, тому що багато тих, хто навчається, марнують час, патчачи ім’я після префікса й дивуючись, чому патч не збігається.
apiVersion: kustomize.config.k8s.io/v1beta1kind: Kustomization
resources:- ../../base
namePrefix: prod-namespace: production
patches:- patch: |- apiVersion: apps/v1 kind: Deployment metadata: name: my-app spec: replicas: 5
images:- name: my-app newTag: v1.2.3
configMapGenerator:- name: app-config literals: - LOG_LEVEL=warn - ENABLE_DEBUG=falseНакладка продакшену вводить інший вид зміни: генерування конфігурації. Вона все ще не копіює Deployment чи Service. Натомість вона описує відмінності продакшену. Це тримає дельту середовища достатньо компактною для рецензування. Рецензент може запитати, чи п’яти реплік достатньо, чи v1.2.3 є схваленим тегом і чи LOG_LEVEL=warn є доречним, не перевіряючи повторно всю форму Deployment.
# Apply devkubectl apply -k overlays/dev/
# Apply prodkubectl apply -k overlays/prod/
# Previewkubectl kustomize overlays/prod/Команди застосування мають вказувати на накладку, яку ви маєте намір розгорнути, а не на базу, коли потрібні специфічні для середовища зміни. Застосування бази напряму іноді корисне для локального димового тесту, але воно оминає рішення накладки. У кластері, де розробка та продакшен можуть співіснувати, префікси імен та простори імен роблять відрендерені ідентичності відмінними. У єдиному іспитному просторі імен ви можете опустити префікси, якщо завдання очікує точних імен, але тоді ви маєте уникати застосування кількох накладок в один простір імен.
Який підхід ви обрали б тут і чому: скопіювати повний Deployment до overlays/prod/ чи тримати Deployment у base/ й патчити лише репліки та тег образу? Підхід із патчем кращий, коли форма об’єкта спільна, тому що він зменшує дрейф і шум рецензування. Копіювання повного об’єкта виправдане лише тоді, коли продакшен є справді іншою формою робочого навантаження, а не просто іншим налаштуванням середовища.
Накладки також можуть стати надто хитромудрими. Якщо накладка має багато патчів, які скасовують інші патчі, імпортовані компоненти, порядок яких важко осмислити, та згенеровані імена, від яких залежать зовнішні системи, дизайн переріс просту модель «база плюс дельта середовища». На цьому етапі розділіть базу, введіть чіткіші компоненти або поміркуйте, чи інструмент пакування з явними значеннями буде чеснішим. Kustomize залишається придатним для підтримки, коли кожен шар має єдину причину для існування.
Попередній перегляд, застосування та швидке налагодження
Розділ «Попередній перегляд, застосування та швидке налагодження»Налагодження Kustomize — це здебільшого дисциплінований рендеринг. Якщо kubectl kustomize overlays/prod/ не рендерить той об’єкт, який ви очікуєте, то й kubectl apply -k overlays/prod/ не виправить його якимось чарівним чином. Почніть саме з локального виводу й класифікуйте збій за його типом. Помилка шляху означає, що Kustomize не зміг прочитати файл чи каталог. Невідповідність патча означає, що він не зміг знайти потрібну ціль. Валідний рендеринг із неправильним образом чи мітками означає, що оголошення трансформера не збіглося з тим, із чим, як ви думали, воно мало збігтися.
# Preview kustomizationkubectl kustomize ./
# Apply kustomizationkubectl apply -k ./
# Delete kustomizationkubectl delete -k ./
# View specific overlaykubectl kustomize overlays/prod/Ці чотири команди — іспитова швидка довідка, тому що вони охоплюють весь цикл. Попередній перегляд, застосування, видалення та рендеринг конкретної накладки. Використовуйте повні команди kubectl у скриптах і скопійованих прикладах. Багато інженерів використовують короткий аліас інтерактивно, але аліаси не є надійними в неінтерактивних оболонках і не повинні з’являтися в придатних для виконання прикладах. Безпека копіювання-вставлення має значення, коли працює таймер лабораторії.
apiVersion: kustomize.config.k8s.io/v1beta1kind: Kustomizationresources:- deployment.yamlМінімальної kustomization часто достатньо, щоб почати. Додавайте одну трансформацію за раз і рендеріть після кожної. Якщо ви додасте простір імен, мітки, образи, генератори та патчі всі одразу, перший збій рендерингу дасть вам забагато підозрюваних. Поступовий рендеринг не повільний; це найшвидший спосіб ізолювати помилку. На Kubernetes 1.35 і новіших іспитових середовищах інтеграція kubectl є очікуваною поведінкою, тож локальний цикл рендерингу має бути частиною вашого звичайного робочого процесу.
apiVersion: kustomize.config.k8s.io/v1beta1kind: Kustomization
resources:- deployment.yaml- service.yaml
namespace: my-namespacenamePrefix: prod-
labels:- pairs: app: my-app includeSelectors: true includeTemplates: true
images:- name: nginx newTag: "1.21"
configMapGenerator:- name: config literals: - KEY=valueКоли відрендерений вивід неправильний, читайте його так, як це робив би API-сервер. Чи правильні імена ресурсів після додавання префікса? Чи присутні простори імен там, де дозволено? Чи селектори Service усе ще збігаються з мітками шаблону Pod’а? Чи змінився тег образу на призначеному контейнері? Чи з’явилося ім’я згенерованого ConfigMap у посиланні Deployment? Ці перевірки корисніші за вдивляння у файл kustomization, тому що відрендерений вивід — це правда, яку надішле apply.
Для збоїв шляху запустіть pwd і перевірте шлях накладки, який ви передали kubectl. Відносні шляхи всередині resources: розв’язуються з каталогу файлу kustomization, а не з каталогу оболонки в якомусь нечіткому глобальному сенсі. Для збоїв патча порівняйте apiVersion, kind, metadata.name та іноді простір імен. Для несподіванок генератора перевірте, чи очікується суфікс хеша. Для несподіванок селектора перевірте обидві сторони зв’язку, а не лише поле, яке ви відредагували.
Налагодження має закінчуватися застосуванням лише після того, як рендеринг є правдоподібним. Якщо застосування зазнає невдачі після хорошого рендерингу, помилка перемістилася з композиції Kustomize до валідації, допуску чи стану кластера Kubernetes. Це може означати, що простору імен не існує, що незмінний селектор змінився на наявному Deployment, або що політика образу не приймається політикою. Тримання збоїв рендерингу та збоїв API окремо заощаджує час, тому що вони потребують різних виправлень.
Один практичний трюк налагодження — це класифікувати збій за тією найранішою командою, яка взагалі може його відтворити. Якщо kubectl kustomize overlays/prod/ зазнає невдачі, тримайтеся осторонь кластера й полагодьте сам граф kustomization. Якщо рендеринг успішний, але kubectl apply -k overlays/prod/ зазнає невдачі, тримайте відрендерений вивід на видноті, читаючи помилку API. Помилка простору імен, помилка незмінного селектора чи відмова допуску — це вже не проблема композиції Kustomize. Це проблема застосування Kubernetes з використанням YAML, який Kustomize випадково згенерував.
Коли відрендерений YAML валідний, але дивний, порівнюйте ідентичності ресурсів, перш ніж порівнювати кожне поле. Перевірте kind, metadata.name та metadata.namespace спершу, тому що ці поля вирішують, який об’єкт буде створено, оновлено чи видалено. Потім перевірте поля зв’язку, такі як селектори, посилання на ServiceAccount, посилання на ConfigMap та образи контейнерів. Цей порядок не дає галасливим diff’ам відволікати вас. Суфікс згенерованого ConfigMap може виглядати драматично, але незбіжний селектор Service зазвичай є більш нагальним операційним збоєм.
Для накладок рендеріть базу й накладку окремо, коли джерело зміни незрозуміле. Рендеринг бази каже вам спільну стартову точку. Рендеринг накладки каже вам фінальний стан після імпортів, генераторів, трансформерів і патчів. Якщо поле вже неправильне в базі, полагодьте базу або вирішіть, чи має кожне середовище успадковувати цю форму. Якщо поле правильне в базі й неправильне лише в накладці, перевірте трансформери та патчі накладки, перш ніж торкатися спільних файлів.
Цей самий метод допомагає під час очищення. kubectl delete -k рендерить kustomization і видаляє об’єкти, ідентифіковані поточним рендерингом. Якщо ви змінили імена, префікси, простори імен чи опції генератора після застосування, команда видалення може більше не вказувати на ті самі ідентичності об’єктів. Перегляньте поточний рендеринг перед видаленням. Якщо він більше не збігається із застосованими ідентичностями, або відновіть попередню накладку рівно настільки, щоб видалити чисто, або видаліть залишкові об’єкти явно після підтвердження їхніх імен.
Нарешті, розглядайте згенеровані ресурси як частину відрендереного контракту. Згенерований ConfigMap чи Secret — це не невидимий помічник; це реальний об’єкт Kubernetes із реальним ім’ям, мітками, ключами даних і посиланнями з робочих навантажень. Якщо застосунок не може знайти конфігурацію після розгортання, перевірте відрендерений згенерований об’єкт і відрендерений шаблон Pod’а разом. Помилкою може бути відсутній ключ, несподіваний суфікс через те, що посилання не оновилося, або опція генератора з фіксованим ім’ям, яка завадила розгортанню статися.
Патерни та антипатерни
Розділ «Патерни та антипатерни»Kustomize працює найкраще, коли структура репозиторію розповідає ту саму історію, що й процес розгортання. Кладіть стабільну форму застосунку в базу, кладіть рішення про середовище в накладки й використовуйте патчі для зосереджених змін. Це не лише стиль. Це дає рецензентам менший diff, дає операторам передбачуваний шлях рендерингу й дає тим, хто навчається, чистий спосіб міркувати про те, що змінить kubectl apply -k.
| Патерн | Коли використовувати | Чому це працює |
|---|---|---|
| База плюс накладки середовищ | Той самий застосунок працює в dev, стейджингу та продакшені з невеликими відмінностями | Спільні маніфести залишаються в одному місці, тоді як накладки розкривають дельти середовища |
| Попередній перегляд перед застосуванням | Щоразу, коли kustomization включає трансформації, генератори чи патчі | Відрендерений YAML розкриває результати імені, селектора, простору імен, образу та патча до мутації кластера |
| Невеликі патчі з чіткими цілями | Один ресурс потребує зміни поля, такого як репліки, політика, пов’язана з образом, чи ресурси | Рецензенти можуть побачити призначене перевизначення без перечитування цілого скопійованого об’єкта |
| Генератори із суфіксом хеша | Робочі навантаження мають розгортатися, коли вміст конфігурації змінюється | Згенеровані імена роблять зміни конфігурації видимими в посиланнях шаблону Pod’а |
Усі патерни поділяють одну властивість: вони зменшують прихований стан. База плюс накладки робить успадкування явним через resources:. Попередній перегляд перед застосуванням відокремлює локальний рендеринг від мутації кластера. Невеликі патчі показують намір. Генератори із суфіксом хеша роблять ревізії конфігурації видимими. Коли репозиторій Kustomize стає складним для налагодження, це зазвичай тому, що одну з цих властивостей видимості було втрачено.
| Антипатерн | Що йде не так | Краща альтернатива |
|---|---|---|
| Копіювання повних маніфестів у кожну накладку | Середовища дрейфують, і рецензенти не можуть сказати, які відмінності навмисні | Тримайте спільні об’єкти в базі й патчте лише реальні дельти |
| Бездумне додавання міток до селекторів | Наявні Deployment’и можуть відхиляти зміни незмінних селекторів, або Service’и можуть перестати збігатися з Pod’ами | Вирішіть, чи мітка описова, чи селективна, перш ніж встановлювати includeSelectors |
| Вимкнення хешів генератора за замовчуванням | Зміни конфігурації можуть не розгортати Pod’и, тому що імена об’єктів залишаються фіксованими | Зберігайте хеші, доки інтеграція з фіксованим ім’ям цього не вимагає |
| Патчинг за індексом переліку в складних Pod’ах | Новий sidecar чи переупорядкований перелік контейнерів може запатчити неправильний контейнер | Надавайте перевагу патчам, які збігаються з іменованими контейнерами, коли форма робочого навантаження не гарантована |
Антипатерни привабливі, тому що вони відчуваються швидшими на старті. Скопіювати маніфест швидше, ніж вивчити патч для першої зміни. Додати мітки всюди швидше, ніж думати про селектори. Вимкнення хешів робить імена легшими для читання. Патчі JSON на основі індексу швидко друкувати. Ціна з’являється пізніше, коли відрендерений вивід валідний, але операційно неправильний. Краща альтернатива дещо обдуманіша й набагато легша для аудиту.
Фреймворк для прийняття рішень
Розділ «Фреймворк для прийняття рішень»Обирайте Kustomize, коли ваша основна проблема — контрольована варіація маніфестів Kubernetes. Обирайте Helm, коли ваша основна проблема — пакування, розповсюдження та параметризоване встановлення. Різниця — не «простий інструмент проти просунутого» в моральному сенсі. Це різниця в тому, де живе складність. Kustomize тримає складність у накладках і патчах проти валідного YAML. Helm тримає складність у шаблонах, значеннях, метаданих чарта та керуванні релізами.
Start | vDo you already have valid Kubernetes YAML? |-- no --> Need a reusable install package with values? --> Use Helm | yes | vAre differences mostly labels, namespaces, images, replicas, config, or small patches? |-- yes --> Use Kustomize overlays | no | vDo you need conditionals, loops, dependencies, or chart distribution? |-- yes --> Use Helm | no | vSplit the manifests or simplify the deployment shape, then reassess.Цей фреймворк не дає вам проштовхувати кожне розгортання через інструмент, який ви випадково знаєте найкраще. Якщо сторонній проєкт постачає Helm-чарт, і вам потрібне версіоноване керування релізами, Helm — природний вибір. Якщо у вашої команди є власний YAML, і вам потрібні варіанти розробки, стейджингу та продакшену, Kustomize зазвичай має менше церемоній. Якщо вам потрібні обидва, поширений патерн — відрендерити Helm-чарт, а потім використати Kustomize як шар налаштування після рендерингу, але це додає ще одну межу для налагодження.
| Ситуація | Надавати перевагу Kustomize | Надавати перевагу Helm |
|---|---|---|
| Наявний YAML потребує варіантів середовища | Так, накладки й патчі підходять напряму | Лише якщо також потрібні пакування чи схеми значень |
| Завдання CKAD просить вбудоване налаштування | Так, kubectl apply -k доступний | Зазвичай непотрібний, якщо завдання явно не використовує Helm |
| Застосунок має багато опціональних компонентів | Можливо, але накладки можуть заплутатися | Так, шаблони й значення обробляють умовну структуру |
| Команда хоче об’єкти релізів і версії чартів | Сам Kustomize не надає історії релізів Helm | Так, Helm відстежує релізи й пакування чартів |
| Потрібно патчити сторонній відрендерений YAML | Так, Kustomize корисний як крок після рендерингу | Helm усе ще може володіти початковим рендерингом |
Для практики CKAD за замовчуванням обирайте Kustomize, коли завдання згадує kustomization.yaml, накладки, патчі, згенеровані ConfigMap чи kubectl apply -k. Не хапайтеся за Helm лише тому, що Helm теж може видавати Kubernetes YAML. Іспит перевіряє, чи можете ви скомпонувати й відрендерити ресурси за допомогою вбудованого інструмента. Для продакшен-інженерії приймайте те саме рішення на основі придатності для підтримки: використовуйте інструмент, режими збоїв якого ваша команда може налагодити під тиском.
Чи знали ви?
Розділ «Чи знали ви?»-
Kustomize вбудовано в kubectl з Kubernetes 1.14. Це означає, що іспитове середовище Kubernetes 1.35 чи новіше може рендерити й застосовувати kustomization без окремого бінарного файлу Kustomize.
-
Суфікси хеша на згенерованих ConfigMap і Secret — це сигнали розгортання. Зміна вмісту створює нове згенероване ім’я, а Kustomize оновлює посилання, тож шаблон Pod’а змінюється.
-
Трансформер
labelsможе включати або виключати селектори. Цей вибір має значення, тому що мітки-селектори визначають зв’язки, тоді як описові мітки призначені здебільшого для людей та автоматизації. -
Kustomize і Helm можна комбінувати, але це додає межу налагодження. Helm може спершу відрендерити чарт, потім Kustomize може запатчити відрендерений YAML, тож переглядайте кожен етап.
Типові помилки
Розділ «Типові помилки»| Помилка | Чому це трапляється | Як це виправити |
|---|---|---|
| Неправильний шлях до бази | Накладка використовує відносний шлях, такий як ../../base, але каталог перемістився чи шлях було вписано з неправильного ментального розташування | Відрендеріть за допомогою kubectl kustomize overlays/name/, прочитайте помилку шляху й полагодьте запис resources: відносно kustomization.yaml тієї накладки |
| Невідповідність імені цілі патча | Патч націлюється на ім’я після префікса чи застаріле ім’я ресурсу замість базової ідентичності об’єкта | Збіжте ціль із базовими apiVersion, kind та metadata.name, потім перегляньте накладку, щоб підтвердити, що відрендерене поле змінилося |
Відсутній apiVersion у kustomization | Файл виглядає як звичайний YAML, тож обов’язковий заголовок Kustomize пропускають | Починайте кожну kustomization з apiVersion: kustomize.config.k8s.io/v1beta1 та kind: Kustomization |
Забування секції resources | Файли існують у каталозі, але Kustomize застосовує лише перелічені чи імпортовані ресурси | Явно перелічуйте кожен файл ресурсу чи базовий каталог під resources: |
| Відсутність попереднього перегляду перед застосуванням | До накладки ставляться як до статичного маніфесту, тож помилки виявляються лише після мутації кластера | Спершу запустіть kubectl kustomize <dir> і перевірте імена, простори імен, селектори, образи, згенеровані посилання й патчі |
| Додавання міток-селекторів без наміру | Мітки відчуваються нешкідливими, але селектори впливають на незмінність Deployment і маршрутизацію Service-до-Pod | Використовуйте includeSelectors лише тоді, коли зв’язки селекторів мають змінитися, і використовуйте анотації чи неселекторні мітки для метаданих |
| Рефлекторне вимкнення суфіксів хеша генератора | Стабільні згенеровані імена виглядають легшими для читання, але Pod’и можуть не розгортатися, коли конфігурація змінюється | Зберігайте суфікси хеша, доки інтеграція з фіксованим ім’ям їх не вимагає, і визначте окремий механізм перезапуску, якщо хеші вимкнено |
Патчинг індексу контейнера 0 у спільних робочих навантаженнях | Патч працює в прикладі з одним контейнером, але може влучити в неправильний контейнер, коли додаються sidecar’и | Патчте за ім’ям контейнера, коли можливо, або застосовуйте політику, яка робить патчі на основі індексу безпечними |
Тест
Розділ «Тест»Питання 1: У вашої команди є базовий Deployment, який працює в розробці. Для продакшену вам потрібно змінити простір імен на `production`, збільшити репліки до 5 і використати тег образу `v2.1.0` замість `latest`, не змінюючи базові файли. Як налаштувати це за допомогою Kustomize?
Створіть накладку продакшену, таку як overlays/prod/kustomization.yaml, що посилається на ../../base, встановлює namespace: production, оголошує перевизначення images і патчить кількість реплік Deployment. База залишається спільним визначенням застосунку, тоді як накладка фіксує лише відмінності продакшену. Це краще за копіювання повного Deployment, тому що майбутні виправлення бази автоматично потечуть у продакшен. Перед застосуванням запустіть kubectl kustomize overlays/prod/ і підтвердьте, що відрендерені простір імен, тег образу та кількість реплік правильні.
apiVersion: kustomize.config.k8s.io/v1beta1kind: Kustomizationresources:- ../../basenamespace: productionimages:- name: nginx newTag: "v2.1.0"patches:- patch: |- apiVersion: apps/v1 kind: Deployment metadata: name: web-app spec: replicas: 5Питання 2: Ви запускаєте `kubectl apply -k ./` і отримуєте помилку, що перелічений ресурс не має такого файлу чи каталогу. Файл, схоже, існує, коли ви перелічуєте поточний каталог оболонки. Що слід перевірити першим?
Передусім перевірте шлях саме з перспективи того файлу kustomization.yaml, який містить запис resources:. Відносні шляхи ресурсів розв’язуються з каталогу того файлу, а не з каталогу оболонки, тож ваш поточний каталог оболонки може легко ввести вас в оману, якщо ви рендерите накладку звідкись інде. Також перевірте точне написання імені файлу, його регістр і чи це .yaml, а не .yml. Виправлення полягає в тому, щоб оновити шлях у resources: або запустити команду проти призначеного каталогу, а потім переглянути вивід ще раз, перш ніж застосовувати.
Питання 3: Колега запитує, чому команді не варто використовувати Helm для кожної варіації середовища. Наведіть два конкретні випадки, де Kustomize підходить краще.
Kustomize є кращим вибором, коли у команди вже є валідний Kubernetes YAML і потрібні лише відмінності середовища, такі як простір імен, тег образу, кількість реплік, мітки, згенеровані ConfigMap чи невеликі патчі. Він також сильно підходить тоді, коли вам потрібно налаштувати сторонній відрендерений YAML без підтримки власного форку, тому що патчі можна застосувати вже після того, як базові ресурси стають доступними. Helm усе ще корисний для пакування, керування залежностями, записів про релізи та умовних шаблонів. Рішення завжди має слідувати за формою самої проблеми, а не за тим, який інструмент ви знаєте найкраще.
Питання 4: Ви оновлюєте літерал `configMapGenerator` і повторно застосовуєте накладку. Нові Pod'и посилаються на нове ім'я ConfigMap, але старий ConfigMap усе ще існує. Це збій?
Це очікувана поведінка тоді, коли згенеровані імена включають хеш вмісту. Зміна даних породжує нове згенероване ім’я ConfigMap, а Kustomize оновлює посилання на нього, тож шаблон Pod’а у Deployment змінюється й розгортання справді може статися. Старий ConfigMap може залишитися саме для того, щоб старіші ReplicaSet’и чи операції відкату все ще могли посилатися на ту конфігурацію, з якою їх було створено. Ви можете очистити старі згенеровані ConfigMap уже після завершення вікна відкату, але вам не варто розглядати їхню тимчасову присутність як збій рендерингу.
Питання 5: Накладка продакшену використовує `namePrefix: prod-`, а патч націлюється на Deployment з ім'ям `prod-api`. Базовий Deployment названо `api`, і патч не застосовується. У чому ймовірна проблема?
Патч, найімовірніше, націлюється на вже трансформоване ім’я замість базового імені ресурсу. Kustomize зіставляє багато патчів саме з ідентичністю ресурсу, яка походить із бази, а вже потім застосовує трансформації імен до відрендереного виводу. Тому патч має націлюватися на metadata.name: api, тоді як фінальний відрендерений Deployment усе одно може стати prod-api. Попередній перегляд накладки підтвердить, чи змінилося поле кількості реплік, образу чи ресурсу саме так, як було призначено.
Питання 6: Ваш Service існує, а розгортання Deployment справне, але трафік до Service повертає відсутність ендпоїнтів після трансформації міток. Що ви перевіряєте?
Перевірте одночасно і селектор Service, і мітки шаблону Pod’а у відрендереному виводі. Трансформер міток міг змінити лише одну сторону цього зв’язку чи додати мітку-селектор, якої взагалі немає на самих Pod’ах. Service маршрутизує трафік лише до тих Pod’ів, чиї мітки збігаються з його селектором, тож цілком справний Deployment усе ще може лишатися недосяжним через Service. Полагодьте налаштування трансформера міток або базові мітки, а потім відрендеріть вивід ще раз, перш ніж застосовувати.
Питання 7: Патч JSON додає обмеження ресурсів за `/spec/template/spec/containers/0/resources`. Сьогодні він працює, але команда планує додати sidecar. Який ризик слід підняти на рецензуванні?
Патч залежить від порядку переліку контейнерів, тож він може націлитися на неправильний контейнер, якщо sidecar буде вставлено перед контейнером застосунку. Це прийнятно в суворо контрольованій вправі з одним контейнером, але це крихко в спільному продакшен-навантаженні. Безпечніший підхід — використовувати патч, який збігається з контейнером за ім’ям, коли робоче навантаження має кілька контейнерів чи може обростати sidecar’ами. Рецензування має запитати, чи гарантовано порядок переліку політикою, перш ніж приймати патч.
Практична вправа
Розділ «Практична вправа»Сценарій вправи: створіть повну конфігурацію Kustomize з базою та двома накладками. Ви відрендерите обидві накладки, застосуєте накладку розробки, перевірите живі об’єкти, потім очистите. Мета — не лише змусити команди працювати. Мета — прочитати відрендерений YAML і пояснити, як база, трансформації, генератори та патчі поєднуються у фінальні ресурси.
Частина 1: Створення бази
Розділ «Частина 1: Створення бази»mkdir -p /tmp/kustomize-demo/basecd /tmp/kustomize-demo
# Create deploymentcat << 'EOF' > base/deployment.yamlapiVersion: apps/v1kind: Deploymentmetadata: name: web-appspec: replicas: 1 selector: matchLabels: app: web template: metadata: labels: app: web spec: containers: - name: nginx image: nginx:1.20 ports: - containerPort: 80EOF
# Create servicecat << 'EOF' > base/service.yamlapiVersion: v1kind: Servicemetadata: name: web-appspec: selector: app: web ports: - port: 80EOF
# Create base kustomizationcat << 'EOF' > base/kustomization.yamlapiVersion: kustomize.config.k8s.io/v1beta1kind: Kustomizationresources:- deployment.yaml- service.yamlEOFБаза навмисно невелика. Вона містить один Deployment, один Service і перелік ресурсів, що включає обидва файли. Перш ніж додавати накладки, відрендеріть базу за допомогою kubectl kustomize base/ і перевірте, що селектор Deployment збігається з мітками шаблону Pod’а, і що селектор Service усе ще використовує app: web. Якщо база неправильна, кожна накладка, яка її імпортує, успадкує помилку.
Частина 2: Створення накладки Dev
Розділ «Частина 2: Створення накладки Dev»mkdir -p overlays/dev
cat << 'EOF' > overlays/dev/kustomization.yamlapiVersion: kustomize.config.k8s.io/v1beta1kind: Kustomization
resources:- ../../base
namePrefix: dev-namespace: development
images:- name: nginx newTag: "1.21"
configMapGenerator:- name: app-config literals: - ENV=development - DEBUG=trueEOFНакладка розробки змінює ідентичність, розміщення, тег образу та конфігурацію, не копіюючи Deployment. Відрендеріть її й перевірте ім’я згенерованого ConfigMap. Ви маєте побачити суфікс на згенерованому об’єкті та простір імен розробки на ресурсах із простором імен. Якщо ви не бачите зміни тегу образу, перевірте ім’я базового образу та збіг images.name.
Частина 3: Створення накладки Prod
Розділ «Частина 3: Створення накладки Prod»mkdir -p overlays/prod
cat << 'EOF' > overlays/prod/kustomization.yamlapiVersion: kustomize.config.k8s.io/v1beta1kind: Kustomization
resources:- ../../base
namePrefix: prod-namespace: production
patches:- patch: |- apiVersion: apps/v1 kind: Deployment metadata: name: web-app spec: replicas: 3
images:- name: nginx newTag: "1.22"
configMapGenerator:- name: app-config literals: - ENV=production - DEBUG=falseEOFНакладка продакшену додає патч, тому що кількість реплік — це конкретне поле на одному Deployment. Зверніть увагу, що патч називає web-app, а не prod-web-app. Префікс — це відрендерена трансформація, тоді як ціль патча ідентифікує базовий об’єкт. Відрендеріть продакшен і підтвердьте, що фінальне ім’я має префікс, а фінальна кількість реплік — три.
Частина 4: Попередній перегляд і застосування
Розділ «Частина 4: Попередній перегляд і застосування»# Preview devkubectl kustomize overlays/dev/
# Preview prodkubectl kustomize overlays/prod/
# Apply dev (create namespace first)kubectl create ns developmentkubectl apply -k overlays/dev/
# Verifykubectl get all -n development
# Cleanupkubectl delete -k overlays/dev/kubectl delete ns developmentЗастосовуйте лише після того, як обидва попередні перегляди стануть зрозумілими. Застосування розробки створює імена з префіксом dev- у просторі імен development. Очищення використовує ту саму накладку, що має значення, тому що видалення потребує відрендерити ті самі ідентичності об’єктів. Якщо ви зміните накладку після застосування й перед видаленням, спершу перегляньте ціль видалення, щоб не залишити позаду старі згенеровані об’єкти чи ресурси з префіксом.
Критерії успіху
Розділ «Критерії успіху»- База рендерить Deployment і Service зі збіжними мітками та селекторами.
- Накладка розробки рендерить імена з префіксом
dev-, простір іменdevelopment, тег образу1.21та згенерований ConfigMap. - Накладка продакшену рендерить імена з префіксом
prod-, простір іменproduction, тег образу1.22та запатчену кількість реплік. -
kubectl apply -k overlays/dev/успішно виконується після створення простору імен. -
kubectl get all -n developmentпоказує очікувані ресурси Deployment, ReplicaSet, Pod і Service. - Очищення видаляє ресурси розробки та простір імен, не покладаючись на ручні імена об’єктів.
Нотатки до розв'язку
Якщо рендеринг зазнає невдачі перед застосуванням, спершу полагодьте локальний ввід Kustomize. Помилки шляху зазвичай вказують на записи resources:, тоді як помилки патча зазвичай вказують на невідповідність цілі. Якщо застосування зазнає невдачі після чистого рендерингу, перевірте стан кластера, особливо чи існує простір імен. Для накладки продакшену фінальне ім’я Deployment має включати префікс, але ціль патча має залишатися базовим ім’ям. Для згенерованих ConfigMap очікуйте суфікса й не намагайтеся вгадати його у вихідному YAML.
Тренувальні вправи
Розділ «Тренувальні вправи»Ці вправи зберігають ту саму механіку в менших таймованих відрізках. Використовуйте їх, коли хочете повторення без перебудови повного дерева бази та накладок. Команди очищення видаляють локальні чернеткові каталоги чи ресурси кластера, створені вправою, але все одно переглядайте перед застосуванням, коли вправа торкається кластера.
Вправа 1: Базова Kustomization (Ціль: 3 хвилини)
Розділ «Вправа 1: Базова Kustomization (Ціль: 3 хвилини)»mkdir -p /tmp/drill1 && cd /tmp/drill1
# Create deploymentcat << 'EOF' > deployment.yamlapiVersion: apps/v1kind: Deploymentmetadata: name: nginxspec: replicas: 1 selector: matchLabels: app: nginx template: metadata: labels: app: nginx spec: containers: - name: nginx image: nginxEOF
# Create kustomizationcat << 'EOF' > kustomization.yamlapiVersion: kustomize.config.k8s.io/v1beta1kind: Kustomizationresources:- deployment.yamlnamespace: defaultlabels:- pairs: environment: test includeSelectors: true includeTemplates: trueEOF
# Previewkubectl kustomize ./
# Applykubectl apply -k ./
# Verifykubectl get deployments,pods -l environment=test
# Cleanupkubectl delete -k ./Вправа 2: Перевизначення образу (Ціль: 2 хвилини)
Розділ «Вправа 2: Перевизначення образу (Ціль: 2 хвилини)»mkdir -p /tmp/drill2 && cd /tmp/drill2
cat << 'EOF' > deployment.yamlapiVersion: apps/v1kind: Deploymentmetadata: name: appspec: selector: matchLabels: app: app template: metadata: labels: app: app spec: containers: - name: app image: nginx:1.19EOF
cat << 'EOF' > kustomization.yamlapiVersion: kustomize.config.k8s.io/v1beta1kind: Kustomizationresources:- deployment.yamlimages:- name: nginx newTag: "1.22"EOF
# Verify image changedkubectl kustomize ./ | grep image
# Cleanupcd /tmp && rm -rf drill2Вправа 3: Генератор ConfigMap (Ціль: 3 хвилини)
Розділ «Вправа 3: Генератор ConfigMap (Ціль: 3 хвилини)»mkdir -p /tmp/drill3 && cd /tmp/drill3
cat << 'EOF' > deployment.yamlapiVersion: apps/v1kind: Deploymentmetadata: name: appspec: selector: matchLabels: app: app template: metadata: labels: app: app spec: containers: - name: app image: nginx envFrom: - configMapRef: name: app-configEOF
cat << 'EOF' > kustomization.yamlapiVersion: kustomize.config.k8s.io/v1beta1kind: Kustomizationresources:- deployment.yamlconfigMapGenerator:- name: app-config literals: - DATABASE_URL=postgres://localhost - LOG_LEVEL=debugEOF
# Preview - notice hash suffixkubectl kustomize ./
# Cleanupcd /tmp && rm -rf drill3Вправа 4: Патчі (Ціль: 4 хвилини)
Розділ «Вправа 4: Патчі (Ціль: 4 хвилини)»mkdir -p /tmp/drill4 && cd /tmp/drill4
cat << 'EOF' > deployment.yamlapiVersion: apps/v1kind: Deploymentmetadata: name: webspec: replicas: 1 selector: matchLabels: app: web template: metadata: labels: app: web spec: containers: - name: nginx image: nginxEOF
cat << 'EOF' > kustomization.yamlapiVersion: kustomize.config.k8s.io/v1beta1kind: Kustomizationresources:- deployment.yamlpatches:- patch: |- apiVersion: apps/v1 kind: Deployment metadata: name: web spec: replicas: 3 template: spec: containers: - name: nginx resources: limits: memory: 128Mi cpu: 100mEOF
# Verify patch appliedkubectl kustomize ./
# Cleanupcd /tmp && rm -rf drill4Вправа 5: Префікс імені та простір імен (Ціль: 2 хвилини)
Розділ «Вправа 5: Префікс імені та простір імен (Ціль: 2 хвилини)»mkdir -p /tmp/drill5 && cd /tmp/drill5
cat << 'EOF' > deployment.yamlapiVersion: apps/v1kind: Deploymentmetadata: name: appspec: selector: matchLabels: app: app template: metadata: labels: app: app spec: containers: - name: nginx image: nginxEOF
cat << 'EOF' > kustomization.yamlapiVersion: kustomize.config.k8s.io/v1beta1kind: Kustomizationresources:- deployment.yamlnamePrefix: staging-namespace: staginglabels:- pairs: env: staging includeSelectors: true includeTemplates: trueEOF
# Verify transformationskubectl kustomize ./
# Cleanupcd /tmp && rm -rf drill5Вправа 6: Повний сценарій накладки (Ціль: 6 хвилин)
Розділ «Вправа 6: Повний сценарій накладки (Ціль: 6 хвилин)»mkdir -p /tmp/drill6/{base,overlays/dev,overlays/prod}cd /tmp/drill6
# Basecat << 'EOF' > base/deployment.yamlapiVersion: apps/v1kind: Deploymentmetadata: name: apispec: replicas: 1 selector: matchLabels: app: api template: metadata: labels: app: api spec: containers: - name: api image: my-api:latest ports: - containerPort: 8080EOF
cat << 'EOF' > base/kustomization.yamlapiVersion: kustomize.config.k8s.io/v1beta1kind: Kustomizationresources:- deployment.yamlEOF
# Dev overlaycat << 'EOF' > overlays/dev/kustomization.yamlapiVersion: kustomize.config.k8s.io/v1beta1kind: Kustomizationresources:- ../../basenamePrefix: dev-namespace: devimages:- name: my-api newTag: dev-latestEOF
# Prod overlaycat << 'EOF' > overlays/prod/kustomization.yamlapiVersion: kustomize.config.k8s.io/v1beta1kind: Kustomizationresources:- ../../basenamePrefix: prod-namespace: prodimages:- name: my-api newTag: v1.0.0patches:- patch: |- apiVersion: apps/v1 kind: Deployment metadata: name: api spec: replicas: 3EOF
# Compare outputsecho "=== DEV ===" && kubectl kustomize overlays/dev/echo "=== PROD ===" && kubectl kustomize overlays/prod/
# Cleanupcd /tmp && rm -rf drill6Перевірка для того, хто навчається
Розділ «Перевірка для того, хто навчається»Та сама kustomization може оголосити кілька генераторів Secret в одному переліку — літерали для облікових даних і файли для матеріалу TLS:
Коли ви рендерите цю kustomization за допомогою kubectl kustomize, скільки об’єктів Secret має з’явитися, і що сталося б, якби ви використали два окремі ключі верхнього рівня secretGenerator: замість цього?
Sources
Розділ «Sources»- Kubernetes documentation: Managing Kubernetes objects using Kustomize
- kubectl apply reference
- kubectl kustomize reference
- Kustomize kustomization reference
- Kustomize resources reference
- Kustomize patches reference
- Kustomize images reference
- Kustomize ConfigMap generator reference
- Kustomize Secret generator reference
- Kustomize labels reference
- Kustomize namePrefix reference
- Kustomize namespace reference
Наступний модуль
Розділ «Наступний модуль»Модуль 2.4: Стратегії розгортання — патерни blue/green, canary та поступового розгортання.