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

Модуль 3.4: Інгрес

Складність: [СЕРЕДНЯ] — маршрутизація HTTP/HTTPS

Час на проходження: 45–55 хвилин

Передумови: Модуль 3.1 (Сервіси), Модуль 3.3 (DNS)


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

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

Після цього модуля ви зможете:

  • Спроєктувати маршрутизацію Інгресу на основі шляху та хоста, яка спрямовує HTTP-трафік до правильного Сервісу Kubernetes.
  • Налаштувати термінацію TLS за допомогою Secret’ів типу TLS у Kubernetes та пояснити обмеження, пов’язані з просторами імен.
  • Оцінити Інгрес-контролери, вибір IngressClass та компроміси переходу на Gateway API для кластерів Kubernetes 1.35+.
  • Діагностувати збої маршрутизації, аналізуючи статус Інгресу, логи контролера, Сервіси, Endpoint’и та правила шляхів.

Чому цей модуль важливий

Розділ «Чому цей модуль важливий»

Гіпотетичний сценарій: платформна команда перенесла п’ятнадцять внутрішніх вебзастосунків у Kubernetes, і перед запуском кожна команда застосунку просить публічний доступ через HTTPS. Якщо кластер відкриває кожне робоче навантаження окремим Сервісом типу LoadBalancer, команда отримує п’ятнадцять зовнішніх балансувальників навантаження, п’ятнадцять публічних точок входу, дубльовану роботу з TLS і жодного спільного місця, де можна було б виразити політику хостів чи шляхів. Застосунки, можливо, працюватимуть, але операційна модель стає дорогою, і нею важко керувати під тиском.

Інгрес існує, щоб розв’язати цю проблему маршрутизації на рівні 7 (Layer 7). Сервіс дає стабільний доступ до Pod’ів усередині кластера, тоді як Інгрес описує правила HTTP та HTTPS, які контролер перетворює на реальну конфігурацію проксі. Поширена ментальна модель — це стійка реєстрації в готелі: гості заходять через одні передні двері, адміністратор зчитує ім’я або запит щодо номера, і гостя спрямовують до правильного номера так, що жодному номеру не потрібен власний вхід з вулиці.

Для CKA вам потрібно вміти швидко створювати Інгрес, пояснювати, чому сам по собі ресурс Інгресу нічого не робить, і налагоджувати ситуацію, коли запит провалюється до неправильного бекенду. Для проєктування промислових систем вам також потрібен ширший контекст: API Інгресу залишається підтримуваним у Kubernetes 1.35+, але спільнотний контролер ingress-nginx був виведений з експлуатації в березні 2026 року, тож для нових розгортань варто розглядати підтримувані контролери та Gateway API, а не сприймати старіші приклади як рекомендацію для нової архітектури платформи.

Архітектура Інгресу та межі відповідальності

Розділ «Архітектура Інгресу та межі відповідальності»

Перша пастка з Інгресом — це припущення, що мережевим компонентом є сам YAML-ресурс. Це не так. Ресурс Інгресу — це документ із бажаним станом, що зберігається в API Kubernetes, а Інгрес-контролер — це запущене програмне забезпечення, яке стежить за цими документами, програмує проксі та відкриває цей проксі через власний Сервіс. Без контролера API-сервер залюбки збереже ваш Інгрес, але жоден компонент площини даних не прийматиме зовнішній трафік і не заповнить поле ADDRESS.

┌────────────────────────────────────────────────────────────────┐
│ Ingress Architecture │
│ │
│ External Traffic │
│ │ │
│ ▼ │
│ ┌─────────────────────────────────────────────────────────┐ │
│ │ Load Balancer / NodePort │ │
│ │ (Ingress Controller's Service) │ │
│ └────────────────────────┬────────────────────────────────┘ │
│ │ │
│ ▼ │
│ ┌─────────────────────────────────────────────────────────┐ │
│ │ Ingress Controller │ │
│ │ (nginx, traefik, etc.) │ │
│ │ │ │
│ │ Reads Ingress resources and configures routing │ │
│ └─────────────────────────┬────────────────────────────────┘ │
│ │ │
│ ┌─────────────┼─────────────┐ │
│ │ │ │ │
│ ▼ ▼ ▼ │
│ ┌──────────┐ ┌──────────┐ ┌──────────┐ │
│ │ Service │ │ Service │ │ Service │ │
│ │ /api │ │ /web │ │ /docs │ │
│ └────┬─────┘ └────┬─────┘ └────┬─────┘ │
│ │ │ │ │
│ ▼ ▼ ▼ │
│ ┌──────┐ ┌──────┐ ┌──────┐ │
│ │ Pods │ │ Pods │ │ Pods │ │
│ └──────┘ └──────┘ └──────┘ │
│ │
└────────────────────────────────────────────────────────────────┘

Архітектуру легше налагоджувати, коли ви відокремлюєте площину управління від площини даних. API Kubernetes зберігає об’єкти Ingress, Service, EndpointSlice, Secret та IngressClass. Контролер читає ці об’єкти й переписує конфігурацію свого проксі. Потім проксі приймає пакети від Сервісу контролера, застосовує правила HTTP-маршрутизації та перенаправляє трафік до бекенд-Сервісів, які своєю чергою добирають Pod’и.

ХарактеристикаNodePortLoadBalancerIngress
РівеньL4 (TCP/UDP)L4 (TCP/UDP)L7 (HTTP/HTTPS)
Маршрутизація за шляхомНіНіТак
Віртуальні хостиНіНіТак
Термінація TLSНіОбмеженаТак
ВартістьБезкоштовно$ за кожен LBОдин контролер на багато сервісів
Зовнішня IPIP вузла:ПортIP хмарного LBIP контролера

NodePort і LoadBalancer досі корисні, але вони розв’язують задачу відкриття доступу на нижчому рівні. Сервіс типу LoadBalancer може поставити один застосунок за хмарним балансувальником навантаження, і це часто правильна відповідь для TCP-сервісу, ендпоінта бази даних у приватній мережі або виділеного робочого навантаження апаратного типу. Інгрес підходить краще, коли рішення залежить від HTTP-імен хостів, шляхів, сертифікатів TLS та спільної політики маршрутизації.

КомпонентПризначенняХто створює
Інгрес-контролерВласне маршрутизує трафікАдміністратор кластера
Ресурс ІнгресуВизначає правила маршрутизаціїРозробник
Бекенд-СервісиЦільові сервісиРозробник
Secret типу TLSСертифікати HTTPSРозробник / cert-manager

Зупиніться й передбачте: якщо ви застосуєте дійсний маніфест Інгресу до кластера без встановленого Інгрес-контролера, який об’єкт Kubernetes прийме маніфест, а яке видиме поле зазвичай залишиться порожнім? API-сервер приймає об’єкт, оскільки схема дійсна, але статус, що належить контролеру, не оновлюється, бо жоден контролер не узгоджує цей ресурс.

Контролери, IngressClass та ландшафт після виведення з експлуатації

Розділ «Контролери, IngressClass та ландшафт після виведення з експлуатації»

Контролер — це вибір реалізації, а не властивість самого API Інгресу. У старіших посібниках nginx часто фігурує як стандартний контролер, тому що ingress-nginx став спільнотним прикладом, який багато кластерів використовували роками. У 2026 році безпечніша навчальна позиція точніша: Інгрес лишається стабільним API, спільнотний контролер ingress-nginx досяг кінця життєвого циклу, а промислові кластери мають використовувати підтримуваний контролер або переносити нову роботу з HTTP-маршрутизації на Gateway API, коли платформа це підтримує.

КонтролерОписНайкраще підходить для
nginxНайпоширеніший, багатий на можливостіЗагального використання
traefikАвтовиявлення, сучаснийДинамічних середовищ
haproxyВисока продуктивністьВисоконавантажених сайтів
contourНа основі EnvoyКористувачів сервісної сітки
AWS ALBНативна інтеграція з AWSСередовищ AWS

Для підготовки до іспиту та локальних лабораторних робіт ви все ще бачитимете приклади у стилі NGINX, бо вони роблять зв’язок між ресурсом, класом, контролером і бекендом легким для спостереження. Сприймайте ці приклади як навчальну ціль, а не як загальну рекомендацію для промислового застосування. Коли реальна організація обирає контролер для Kubernetes 1.35+, у рішенні слід враховувати статус підтримки, підтримку Gateway API, інтеграцію з хмарою, підтримку політик безпеки, спостережуваність і те, як пізніше переноситимуться анотації, специфічні для контролера.

Terminal window
# For kind
# retired controller — lab/learning use only; see Sources for maintained alternatives
kubectl apply -f https://raw.githubusercontent.com/kubernetes/ingress-nginx/main/deploy/static/provider/kind/deploy.yaml
# For minikube
minikube addons enable ingress
# Verify installation
kubectl get pods -n ingress-nginx
kubectl get svc -n ingress-nginx

Цей блок встановлення корисний для контрольованих навчальних середовищ, бо дає вам конкретний контролер для дослідження. Важлива операційна деталь — не сама команда; це той факт, що контролер працює як Pod’и, відкриває Сервіс і реєструє або використовує IngressClass. Якщо учень здатен знайти ці об’єкти, він може міркувати про те, чи має кластер цикл управління та площину даних, потрібні для роботи Інгресу.

Terminal window
# Check pods
kubectl get pods -n ingress-nginx
# Check service
kubectl get svc -n ingress-nginx
# Check IngressClass
kubectl get ingressclass

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

Проєктування маршрутизації за шляхом і хостом

Розділ «Проєктування маршрутизації за шляхом і хостом»

Простий Інгрес маршрутизує один або кілька HTTP-шляхів до бекенд-Сервісів. Бекенд — це ім’я Сервісу та порт Сервісу, а не IP Pod’а, тому що Kubernetes хоче, щоб правило маршрутизації переживало заміну Pod’ів і події масштабування. Така конструкція тримає Інгрес зосередженим на рішеннях рівня 7, тоді як Сервіси продовжують виконувати стабільну роботу з балансування навантаження, про яку ви дізналися раніше в напрямку про мережі.

apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: simple-ingress
spec:
ingressClassName: nginx # Which controller to use
rules:
- http:
paths:
- path: /
pathType: Prefix
backend:
service:
name: web-service # Target service
port:
number: 80 # Service port

Найпростіший маршрут вище навмисно банальний: кожен HTTP-запит, який обробляє цей Інгрес, спрямовується до web-service на порт Сервісу 80. Це не заміна для селектора Сервісу або порту контейнера Pod’а. Це останній стрибок у ланцюжку: клієнт до контролера, контролер до Сервісу, Сервіс до ендпоінтів, а ендпоінти до Pod’ів.

Маршрутизація за шляхом стає корисною, коли один хост або зовнішня адреса стоїть перед кількома застосунками. Поширений патерн — поставити /api перед API-Сервісом, /web перед вебсервісом і / перед стандартним фронтендом чи цільовою сторінкою. Хитрість у тому, що правила шляхів не оцінюються як список фаєрвола згори донизу; Kubernetes визначає правила пріоритетності так, що перемагає найбільш специфічний збіг.

apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: path-ingress
spec:
ingressClassName: nginx
rules:
- http:
paths:
- path: /api
pathType: Prefix
backend:
service:
name: api-service
port:
number: 80
- path: /web
pathType: Prefix
backend:
service:
name: web-service
port:
number: 80
- path: /
pathType: Prefix
backend:
service:
name: default-service
port:
number: 80
┌────────────────────────────────────────────────────────────────┐
│ Path-Based Routing │
│ │
│ Request: http://mysite.com/api/users │
│ │ │
│ ▼ │
│ ┌────────────────────────────────────────────────────────┐ │
│ │ Ingress │ │
│ │ │ │
│ │ /api/* ──────────► api-service │ │
│ │ /web/* ──────────► web-service │ │
│ │ /* ──────────► default-service │ │
│ │ │ │
│ └────────────────────────────────────────────────────────┘ │
│ │
└────────────────────────────────────────────────────────────────┘
PathTypeПоведінкаПриклад
ExactЛише точний збіг/api збігається з /api, але не з /api/
PrefixЗбіг за префіксом/api збігається з /api, /api/users
ImplementationSpecificВирішує контролерЗалежить від контролера

Prefix зазвичай зручний вибір для CKA, бо він покриває і базовий шлях, і дочірні шляхи. Exact цінний, коли один ендпоінт треба ізолювати від сусідніх шляхів, наприклад /healthz або callback-маршрут, який не повинен збігатися з /healthz/debug. ImplementationSpecific може відкрити поведінку, специфічну для контролера, зокрема збіги в стилі регулярних виразів у деяких контролерах, але він обмінює переносність на потужність, і його варто використовувати лише тоді, коли ви знаєте, який контролер оброблятиме ресурс.

Зупиніться й передбачте: у вас є два правила шляхів Інгресу — /api з pathType: Prefix і /api/v1 з pathType: Exact. Надходить запит на /api/v1/users, а другий запит надходить на /api/v1; яке правило обробляє кожен запит? Довший точний шлях обробляє лише /api/v1, тоді як /api/v1/users повертається до префікса /api, який у цьому прикладі є єдиним префіксом, що збігається з /api/v1/users.

Маршрутизація за хостом, яку також називають віртуальним хостингом, використовує HTTP-заголовок Host для вибору бекенду. Це та сама ідея, що дозволяє одному вебсерверу розміщувати кілька вебсайтів на одній IP-адресі. У Kubernetes вона дозволяє одному Сервісу контролера приймати трафік для api.example.com та web.example.com, спрямовуючи кожне ім’я хоста до іншого внутрішнього Сервісу.

apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: virtual-host-ingress
spec:
ingressClassName: nginx
rules:
- host: api.example.com
http:
paths:
- path: /
pathType: Prefix
backend:
service:
name: api-service
port:
number: 80
- host: web.example.com
http:
paths:
- path: /
pathType: Prefix
backend:
service:
name: web-service
port:
number: 80
┌────────────────────────────────────────────────────────────────┐
│ Host-Based Routing │
│ │
│ api.example.com ──────────► api-service │
│ web.example.com ──────────► web-service │
│ *.example.com ──────────► default-service (if configured) │
│ │
└────────────────────────────────────────────────────────────────┘

Правила за хостом і за шляхом чисто компонуються, коли вам потрібна форма реального застосунку. Одне ім’я хоста може маршрутизувати /api до бекенд-API, а / — до фронтенду, тоді як інше ім’я хоста маршрутизує все до адміністративного застосунку. Саме тут Інгрес починає відчуватися як невеликий HTTP-маршрутизатор, а не як проста ручка для відкриття доступу.

apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: combined-ingress
spec:
ingressClassName: nginx
rules:
- host: app.example.com
http:
paths:
- path: /api
pathType: Prefix
backend:
service:
name: api-service
port:
number: 80
- path: /
pathType: Prefix
backend:
service:
name: web-service
port:
number: 80
- host: admin.example.com
http:
paths:
- path: /
pathType: Prefix
backend:
service:
name: admin-service
port:
number: 80

Перед запуском цього в лабораторній роботі, який вивід ви очікуєте від kubectl describe ingress, якщо імена бекенд-Сервісів існують, але жоден Pod не збігається з селекторами Сервісів? Правило Інгресу все ще може виглядати дійсним, бо воно вказує на Сервіси, тоді як власне шлях запиту зазнає невдачі пізніше, тому що Сервіси не мають ендпоінтів.

Термінація TLS та поведінка, специфічна для контролера

Розділ «Термінація TLS та поведінка, специфічна для контролера»

Термінація TLS — це точка, де зашифрований HTTPS-трафік стає розшифрованим HTTP-трафіком. За типового налаштування Інгресу клієнт спілкується з контролером через HTTPS, контролер пред’являє сертифікат із Secret’а типу TLS у Kubernetes, а контролер перенаправляє звичайний HTTP до бекенд-Сервісу всередині кластера. Деякі середовища також шифрують стрибок до бекенду, але це не частина базового контракту Інгресу й залежить від можливостей контролера чи політики сервісної сітки.

Terminal window
# Generate self-signed certificate (for testing)
# self-signed, no SAN — modern curl needs --insecure (lab/testing only)
openssl req -x509 -nodes -days 365 -newkey rsa:2048 \
-keyout tls.key -out tls.crt \
-subj "/CN=example.com"
# Create secret
kubectl create secret tls example-tls --cert=tls.crt --key=tls.key

Цей Secret має перебувати в тому самому просторі імен, що й Інгрес. Це правило простору імен — не примха контролера; це частина того, як API Інгресу посилається на Secret’и. Якщо ви створите example-tls у default, а Інгрес у production, контролер не зможе використати цей Secret через посилання в Інгресі, і ви можете побачити стандартний сертифікат або помилку TLS — залежно від контролера.

apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: tls-ingress
spec:
ingressClassName: nginx
tls:
- hosts:
- example.com
- www.example.com
secretName: example-tls # TLS secret name
rules:
- host: example.com
http:
paths:
- path: /
pathType: Prefix
backend:
service:
name: web-service
port:
number: 80
┌────────────────────────────────────────────────────────────────┐
│ TLS Termination │
│ │
│ Client (HTTPS) │
│ │ │
│ │ TLS/SSL encrypted │
│ ▼ │
│ ┌─────────────────────────────────────────────────────────┐ │
│ │ Ingress Controller │ │
│ │ (TLS terminates here) │ │
│ │ │ │
│ │ Uses certificate from Secret: example-tls │ │
│ └─────────────────────────────────────────────────────────┘ │
│ │ │
│ │ Plain HTTP (inside cluster) │
│ ▼ │
│ ┌──────────────────┐ │
│ │ Service │ │
│ │ (port 80) │ │
│ └──────────────────┘ │
│ │
└────────────────────────────────────────────────────────────────┘

Анотації — це місце, де Інгрес стає потужним і заплутаним. API Інгресу Kubernetes визначає хости, шляхи, TLS, стандартні бекенди та посилання на бекенди, але він не стандартизує кожну поведінку проксі, на яку розраховують команди. Тому контролери відкривають такі можливості, як перенаправлення, переписування, тайм-аути, обмеження частоти запитів і CORS, через анотації, а це означає, що YAML може стати прив’язаним до однієї реалізації контролера.

apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: annotated-ingress
annotations:
# Rewrite URL path
nginx.ingress.kubernetes.io/rewrite-target: /
# SSL redirect
nginx.ingress.kubernetes.io/ssl-redirect: "true"
# Timeouts
nginx.ingress.kubernetes.io/proxy-connect-timeout: "30"
nginx.ingress.kubernetes.io/proxy-read-timeout: "60"
# Rate limiting
nginx.ingress.kubernetes.io/limit-rps: "10"
# CORS
nginx.ingress.kubernetes.io/enable-cors: "true"
spec:
ingressClassName: nginx
rules:
- http:
paths:
- path: /
pathType: Prefix
backend:
service:
name: web-service
port:
number: 80

Переписування URL — класичний приклад цього компромісу переносності. Бекенд може віддавати /dashboard, тоді як публічна URL-адреса має бути /app/dashboard; без переписування бекенд отримує публічний префікс і може повернути коректну 404 на рівні застосунку. Анотація нижче показує стиль, специфічний для контролера, з яким стикається багато учнів, тоді як Gateway API пізніше дає вам більш переносний спосіб виразити подібну поведінку через фільтри.

# Route /app/(.*) to backend /($1)
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: rewrite-ingress
annotations:
nginx.ingress.kubernetes.io/rewrite-target: /$1
spec:
ingressClassName: nginx
rules:
- http:
paths:
- path: /app/(.*)
pathType: ImplementationSpecific
backend:
service:
name: web-service
port:
number: 80

Зупиніться й подумайте: ваш Інгрес обслуговує і api.example.com, і web.example.com, і ви хочете HTTPS для обох з різними сертифікатами. Вам потрібні два Secret’и типу TLS, якщо сертифікати різні; обидва Secret’и мають бути в тому самому просторі імен, що й Інгрес, який на них посилається; а термінація відбувається на контролері, якщо ви навмисно не налаштуєте іншу модель шифрування бекенду.

Діагностика збоїв маршрутизації Інгресу

Розділ «Діагностика збоїв маршрутизації Інгресу»

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

Ingress Not Working?
├── kubectl get ingress (check ADDRESS)
│ │
│ ├── No ADDRESS → Controller not processing
│ │ Check IngressClass
│ │
│ └── Has ADDRESS → Continue debugging
├── kubectl describe ingress (check events)
│ │
│ └── Errors? → Fix configuration
├── Check backend service
│ kubectl get svc,endpoints
│ │
│ └── No endpoints? → Service has no pods
├── Check Ingress controller logs
│ kubectl logs -n ingress-nginx <controller-pod>
└── Test from inside cluster
kubectl run test --rm -i --image=curlimages/curl -- \
curl -s <service>
Terminal window
# List ingresses
kubectl get ingress
kubectl get ing # Short form
# Describe ingress
kubectl describe ingress my-ingress
# Get ingress YAML
kubectl get ingress my-ingress -o yaml
# Check IngressClass
kubectl get ingressclass
# Check Ingress controller pods
kubectl get pods -n ingress-nginx
# View controller logs
kubectl logs -n ingress-nginx -l app.kubernetes.io/name=ingress-nginx
СимптомПричинаРозв’язання
Не призначено ADDRESSНемає Інгрес-контролераВстановіть інгрес-контролер
ADDRESS призначено, але 404Шлях не збігаєтьсяПеревірте path і pathType
503 Service UnavailableНемає ендпоінтівПеревірте селектор сервісу / pod’и
Помилка SSLНеправильний/відсутній TLS-secretПереконайтеся, що secret існує й відповідає хосту
Неправильний IngressClassКілька контролерівВкажіть правильний ingressClassName

Порожнє поле ADDRESS зазвичай означає, що контролер не перехопив і не узгодив Інгрес. Причиною може бути відсутній контролер, неправильний ingressClassName, клас, що вказує на інший контролер, або контролер, якому бракує дозволу оновлювати статус. 404 зазвичай означає, що контролер живий, але запит не збігся з тією комбінацією хоста й шляху, на яку ви очікували. 503 зазвичай означає, що маршрут збігся, але бекенд-Сервіс не має придатних ендпоінтів.

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

apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: default-backend-ingress
spec:
ingressClassName: nginx
defaultBackend: # Catch-all
service:
name: default-service
port:
number: 80
rules:
- host: api.example.com
http:
paths:
- path: /
pathType: Prefix
backend:
service:
name: api-service
port:
number: 80

Сценарій вправи: ви застосовуєте Інгрес з ingressClassName: nginx, kubectl get ingress показує адресу, а /api/users повертає сторінку фронтенду. Найкраща перша перевірка — не лічильник перезапусків Pod’а контролера; це те, чи використовує шлях /api Prefix, чи існує більш специфічне правило для цього імені хоста і чи містить запит заголовок хоста, що збігається з правилом, яке ви, на вашу думку, тестуєте.

Покроковий розбір запиту

Розділ «Покроковий розбір запиту»

Уявіть запит на https://app.example.com/api/users, що входить у кластер через зовнішній балансувальник навантаження перед контролером. DNS уже розв’язав ім’я хоста в публічну адресу контролера, і клієнт тепер відкриває TLS-з’єднання з цим контролером. У цей момент Сервіси Kubernetes для api та web не видимі клієнту; клієнт бачить лише ендпоінт, відкритий Сервісом контролера.

Контролер отримує TLS-рукостискання й добирає сертифікат, використовуючи запитане ім’я сервера та записи tls.hosts зі збіжних ресурсів Інгресу. Якщо Secret сертифіката існує в правильному просторі імен і містить придатний матеріал сертифіката, контролер може завершити рукостискання. Якщо Secret неправильний, збій усе одно стається до того, як будь-який Сервіс чи Pod отримає трафік, — ось чому помилки TLS не повинні відразу спрямовувати вас до налагодження Деплойменту.

Після термінації TLS контролер читає рядок HTTP-запиту й заголовки. Заголовок Host вирішує, яке правило хоста є придатним, а шлях вирішує, який бекенд під цим хостом має отримати запит. Цей порядок важливий, тому що /api під app.example.com відрізняється від /api під admin.example.com; шлях, який виглядає правильним в одному блоці хоста, нічого не робить для запиту, що несе інше значення хоста.

Для pathType: Prefix Kubernetes у звичайному випадку визначає елементи шляху, а не наївний строковий префікс. Маршрут для /api має збігатися з /api та /api/users, але ви все одно маєте бути точними, коли з’являються кінцеві слеші або схоже названі шляхи. Маршрут для /api не слід трактувати як випадковий збіг для кожного шляху застосунку, який просто починається з тих самих літер, і документацію контролера варто почитати, коли поведінка стає тонкою.

Щойно правило збіглося, контролер перенаправляє запит до названого Сервісу й порту. Саме тут руйнується багато неправильних ментальних моделей. Бекенд Інгресу не вказує на Деплоймент, ReplicaSet чи селектор міток Pod’а; він вказує на Сервіс, а Сервіс уже вказує на ендпоінти, отримані з дібраних Pod’ів, готових достатньо, щоб приймати трафік.

Це розділення дає вам чисту послідовність усунення несправностей. Якщо правило Інгресу називає api на порту 80, почніть з підтвердження того, що Сервіс на ім’я api існує в тому самому просторі імен і відкриває порт 80. Потім підтвердьте, що селектор Сервісу збігається з потрібними Pod’ами. Нарешті підтвердьте, що Pod’и запущені й готові, бо Сервіс без ендпоінтів — поширена причина відповідей «маршрут збігся, але бекенд недоступний».

Шлях відповіді проходить у зворотному напрямку, але важливі межі відповідальності залишаються тими самими. Код застосунку володіє статусом і тілом відповіді після того, як запит досягає Pod’а. Сервіс володіє добором ендпоінтів. Контролер володіє HTTP-збігами, термінацією TLS та поведінкою проксі. Зовнішній балансувальник навантаження або NodePort володіє першою точкою входу в мережу до контролера.

Ця модель меж допомагає інтерпретувати коди стану. Сповіщення TLS зазвичай указує на добір сертифіката, форму Secret’а чи довіру клієнта. Згенерована контролером 404 зазвичай указує на незбіжні правила хоста чи шляху. 503 зазвичай указує на недоступний бекенд після того, як маршрут збігся. Згенерована бекендом 404 зазвичай означає, що запит дійшов до застосунку, але застосунок не розпізнав отриманий шлях.

Під час переписування чи відрізання префіксів будьте особливо уважні, щоб визначити, який компонент створив 404. Якщо контролер ніколи не збігав маршрут, анотації переписування не допоможуть, бо запит не дійшов до цього правила. Якщо бекенд отримав /app/dashboard, а очікував /dashboard, переписування може допомогти, але тепер ваша переносність залежить від обраного контролера та точної семантики його анотацій.

Ось чому curl-тести мають включати заголовок хоста, коли DNS не налаштовано. Тестування curl http://controller-ip/api без -H "Host: app.example.com" не задіює те саме правило, що й реальний запит браузера для app.example.com. На іспитових лабораторних роботах локальні кластери часто полегшують про це забути, бо все начебто досяжне через localhost, але рішення HTTP-маршрутизації все одно залежать від значення хоста.

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

Простори імен додають ще одну межу, яку легко не помітити. Посилання бекенд-Сервісу в Інгресі прив’язане до простору імен, тож маршрут вказує на Сервіси в тому самому просторі імен, що й Інгрес. Посилання Secret’а типу TLS також прив’язане до простору імен. Якщо платформним командам потрібні моделі прив’язки між просторами імен, їм слід оцінити Gateway API, бо він має явні концепції делегування та дозволу на посилання, замість того щоб покладатися на випадкові припущення про роботу між просторами імен.

Готовність до промислової експлуатації та нотатки про перехід

Розділ «Готовність до промислової експлуатації та нотатки про перехід»

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

Виведення з експлуатації спільнотного ingress-nginx ставить це розрізнення прямо. Наявні кластери все ще можуть містити багато ресурсів Інгресу, які є дійсними об’єктами API Kubernetes, але контролер площини даних за ними може більше не отримувати підтримки. Це означає, що план переходу має інвентаризувати Деплойменти контролерів, IngressClass’и, анотації, вебхуки допуску, кастомні сніпети, автоматизацію TLS та операційні дашборди, а не просто рахувати об’єкти Інгресу.

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

Для цілей CKA зосередьтеся на стабільних поведінках Інгресу, які переносяться між контролерами: вибір класу, правила хостів, правила шляхів, бекенд-Сервіси, посилання на Secret’и типу TLS та базове усунення несправностей. Не намагайтеся запам’ятати кожну анотацію від одного контролера. Іспит очікує, що ви застосуєте основні концепції мереж Kubernetes, а можливості, специфічні для контролера, радше з’являться як контекстні підказки, ніж як головна навчальна ціль.

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

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

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

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

Планування ємності теж належить до рівня контролера. Один спільний контролер може спростити зовнішнє відкриття доступу, але він також може стати спільним вузьким місцем, якщо нехтувати запитами ресурсів, автомасштабуванням та налаштуваннями балансувальника навантаження. Висока доступність зазвичай означає кілька реплік контролера, бюджети на порушення роботи (disruption budgets), ретельне розміщення на вузлах і достатню перевірку справності балансувальника навантаження, щоб не надсилати трафік до зламаного проксі.

Бекенд-Сервіси все ще мають значення, коли контролер справний. Якщо проби готовності надто суворі, Деплоймент може мати запущені Pod’и, але не мати ендпоінтів, через що трафік зі збіглим маршрутом зазнає невдачі. Якщо проби готовності надто слабкі, Сервіс може надсилати трафік до Pod’ів, які насправді не готові. Налагодження Інгресу часто виявляє проблеми готовності застосунку, бо HTTP-трафік концентрується через видиму точку входу.

Володіння шляхами слід записувати для спільних імен хостів. Якщо одна команда володіє /api, а інша — /api/admin, командам потрібна домовленість про пріоритетність, переписування, автентифікацію та порядок розгортання. Інакше нешкідливий на вигляд маршрут може затінити більш специфічний маршрут або змінити шлях, який отримує бекенд. Межі «один хост на продукт» часто легше експлуатувати, бо володіння видиме в DNS і сертифікатах.

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

Порівнюючи Інгрес і Gateway API, не формулюйте вибір лише як «старе проти нового». Практичне питання — хто володіє слухачем, хто володіє маршрутом, наскільки переносною має бути поведінка та скільки можливостей, специфічних для контролера, уже використовується. Невеликий наявний Інгрес з одним хостом і одним Сервісом може не заслуговувати на терміновий перехід, тоді як нова спільна платформа має рішуче віддавати перевагу чіткішій моделі володіння Gateway API.

Для іспиту практикуйте написання нудного правильного маніфесту, перш ніж тягнутися до просунутої поведінки. Установіть клас, установіть хост, коли потрібно, обирайте Prefix чи Exact навмисно, коректно посилайтеся на порт Сервісу та перевіряйте ендпоінти, перш ніж винуватити контролер. Ця рутина розв’язує більше збоїв, ніж запам’ятовування рідкісних анотацій, і вона дає вам надійний запасний варіант, коли тиск часу робить складне налагодження спокусливим.

Остання операційна звичка — тримати тести маршрутів реалістичними. Включайте заголовок хоста, використовуйте правильну схему, тестуйте точний шлях і знайте, чи тестуєте ви ззовні кластера, з вузла чи з тимчасового Pod’а. Кожне місце обходить або включає різні частини шляху запиту. Успішний внутрішньокластерний curl до Сервісу доводить, що бекенд працює, але він не доводить TLS, збіг хоста чи поведінку зовнішнього балансувальника навантаження.

Читання маніфестів Інгресу під тиском іспиту

Розділ «Читання маніфестів Інгресу під тиском іспиту»

Коли ви читаєте маніфест Інгресу під час CKA, переглядайте його в тому самому порядку, у якому його використовує запит. Почніть з ingressClassName, бо чудово написаний маршрут інертний, якщо його не обробляє жоден збіжний контролер. Потім перегляньте tls на предмет покриття хостів та імен Secret’ів. Нарешті прочитайте кожне правило хоста й шляху, перевіривши, що кожне ім’я та порт бекенд-Сервісу може існувати в тому самому просторі імен, що й Інгрес.

Порт бекенду заслуговує на навмисну паузу. Kubernetes дозволяє Сервісу відкривати один порт, перенаправляючи на інший цільовий порт на Pod’ах, а бекенд Інгресу посилається на порт Сервісу. Якщо Деплоймент слухає на порту контейнера 8080, Сервіс відкриває порт 80, а Інгрес указує на порт 8080, маршрут може зазнати невдачі, бо Сервіс не відкриває цей номер порту.

Читайте маніфест і на предмет прихованих припущень про контролер. Ключ анотації, що починається з nginx.ingress.kubernetes.io, говорить вам, що маніфест очікує поведінку, сумісну з NGINX, а не загальну поведінку Інгресу. Майбутній контролер може проігнорувати цю анотацію або інтерпретувати схожу можливість інакше. На іспиті ця підказка допомагає вам зрозуміти задуману поведінку; у промисловій експлуатації вона стає інвентарем для переходу.

Імена хостів мають змусити вас запитати, як сформовано тестовий запит. Якщо правило Інгресу каже host: api.example.com, то curl до IP-адреси без заголовка хоста — не достовірний тест. Контролер бачить значення HTTP-хоста, а не коментар, який ви тримали в думці. Ось чому багато локальних тестів використовують curl -H "Host: api.example.com", поки DNS усе ще відсутній.

Для правил шляхів перевірте, чи потрібні родині маршрутів дочірні шляхи. Маршрут фронтенду для / з Prefix широкий за задумом, тож будь-який більш специфічний маршрут має бути достатньо правильним, щоб його перемогти. Якщо /api/users провалюється до /, проблема зазвичай у шляху Exact, незбігу хоста або в тестовому запиті, який ніколи не дійшов до потрібного блоку хоста.

Описи та події швидші за здогадки. kubectl describe ingress зазвичай показує правила в компактній формі, клас, адресу й нещодавні події контролера. Якщо контролер відхилив правило, не зміг знайти Сервіс чи мав проблеми із завантаженням Secret’а типу TLS, потік подій може дати вам пряму підказку. Сприймайте вивід describe як міст між наміром YAML і узгодженням контролера.

Логи контролера додають деталей, коли подій недостатньо, але вони не повинні бути першою зупинкою для кожного збою. Логи можуть бути галасливими, особливо на спільних контролерах, що обслуговують багато просторів імен. Спочатку звузьте проблему за допомогою об’єкта Інгресу, Сервісу, ендпоінтів і реалістичного curl-тесту. Потім використовуйте логи, щоб підтвердити, чи контролер збіг маршрут, дібрав висхідний потік чи сам згенерував відповідь.

Інспекція ендпоінтів — найкоротший шлях через багато збоїв 503. Сервіс може існувати, мати правильний порт і все одно не мати готових ендпоінтів, бо мітки Pod’а не збігаються, проби готовності зазнають невдачі або Деплоймент не розгорнувся. У цьому випадку редагування Інгресу лише додає метушні. Виправте проблему доступності бекенду, потім перетестуйте той самий маршрут, не змінюючи правило маршрутизації.

Збої TLS заслуговують на власну гілку у вашому ментальному чекліст. Підтвердьте, що тип Secret’а — kubernetes.io/tls, що Secret містить дані сертифіката й ключа, і що Secret у тому самому просторі імен, що й Інгрес. Потім підтвердьте, що хост у секції TLS збігається з іменем хоста, яке клієнти насправді використовують. Сертифікат для неправильного імені може виглядати як збій Інгресу, навіть коли маршрутизація в іншому коректна.

Нарешті пам’ятайте, що Інгрес — це один рівень у довшому ланцюжку. DNS, хмарні балансувальники навантаження, мережа вузлів, Pod’и контролера, правила Інгресу, Сервіси, EndpointSlice’и, готовність Pod’ів та маршрутизація застосунку — усе бере участь у фінальному досвіді користувача. Практична навичка — не вгадувати правильний рівень за інстинктом; це проходити ланцюжок достатньо швидко, щоб кожне спостереження одразу відкидало кілька хибних теорій.

Найбезпечніша стратегія на іспиті — тримати ваш перший маніфест консервативним. Уникайте необов’язкових анотацій, доки не запрацює потрібний маршрут, використовуйте Prefix лише там, де родині маршрутів потрібні дочірні шляхи, і тримайте правила хостів очевидними. Щойно основний маршрут стане справним, додавайте TLS чи переписування по одній зміні за раз, щоб наступний збій мав малий простір пошуку.

У промисловій експлуатації та сама звичка стає керуванням змінами. Зміна маршруту, зміна сертифіката та зміна переписування в одному pull request можуть зробити відкат неясним, бо будь-яке з цих редагувань може змінити поведінку, видиму користувачу. Менші зміни маршрутів легше переглядати, легше тестувати реалістичними curl-командами та легше повертати назад, якщо контролер прийме маніфест, але трафік поведеться несподівано.

Якщо ви запам’ятаєте лише одне речення про налагодження, нехай це буде воно: відсутня адреса вказує на узгодження контролера чи класу, 404 вказує на збіг хоста й шляху, а 503 вказує на збіглі маршрути з недоступними бекендами. Цей скорочений запис не замінює доказів, але дає вам швидку стартову гіпотезу, яка чисто лягає на об’єкти Kubernetes, які ви можете дослідити.

Патерни та антипатерни

Розділ «Патерни та антипатерни»

Патерни Інгресу менше про запам’ятовування YAML і більше про те, щоб зробити володіння маршрутизацією явним. Хороший патерн дозволяє команді застосунку випустити маршрут, не захопивши випадково ім’я хоста іншої команди, тоді як хороший платформний патерн дозволяє адміністраторам кластера змінювати контролери, не переписуючи кожен застосунок з нуля. Таблиця нижче зосереджена на рішеннях, які ви можете обґрунтувати в поясненні на іспиті та в огляді архітектури.

ПатернКоли використовуватиЧому працюєМіркування щодо масштабування
Один спільний контролер з явним ingressClassNameКільком командам потрібна HTTP-маршрутизація через одну точку входу платформиКожен Інгрес каже, який контролер ним володіє, уникаючи випадкової стандартної поведінкиДодайте політику допуску чи шаблони, щоб команди не пропускали клас
Маршрутизація за хостом для меж застосункуРізним застосункам потрібні незалежні DNS-іменаІмена хостів створюють чисте володіння й уникають зв’язаності через префікс шляхуАвтоматизація сертифікатів стає важливою, коли кількість хостів зростає
Маршрутизація за шляхом усередині однієї поверхні продуктуОдин публічний застосунок має кілька внутрішніх бекендівКористувачі бачать одне ім’я хоста, тоді як сервіси лишаються розгортуваними окремоДокументуйте володіння префіксами, щоб команди не зіткнулися на /api чи /admin
Secret’и типу TLS, керовані автоматизацієюСертифікати регулярно ротуються або існує багато хостівРучна заміна Secret’ів стає операційним ризикомВикористовуйте cert-manager чи платформні засоби з чіткими правилами просторів імен

Головний антипатерн — трактувати анотації як нешкідливе оздоблення. Анотація на кшталт правила переписування, перенаправлення чи тайм-ауту може змінити семантику запиту так само, як і правило маршруту. Якщо ці анотації прив’язані до одного контролера, їх слід задокументувати як поведінку, специфічну для реалізації, і вважати роботою з переходу, коли організація оцінює Gateway API чи інший контролер.

АнтипатернЩо йде не такКраща альтернатива
Пропуск ingressClassName у кластерах з кількома контролерамиЖоден контролер не перехоплює маршрут, або це робить неправильний стандартний контролерВимагайте явних імен класів у маніфестах і політиці
Поставити один непов’язаний флот за префіксами шляхівБекенди стають зв’язаними з публічною структурою шляхів, а переписувань стає більшеВіддавайте перевагу маршрутизації за хостом, коли продукти мають окреме володіння
Зберігати Secret типу TLS в іншому просторі іменІнгрес не може послатися на сертифікатТримайте Secret поруч з Інгресом або використовуйте механізми Gateway API для роботи між просторами імен, де доречно
Використовувати ImplementationSpecific для звичайних префіксівПоведінка змінюється, коли змінюються контролериВикористовуйте Prefix чи Exact, доки не потрібна можливість, специфічна для контролера

Рамка для прийняття рішень

Розділ «Рамка для прийняття рішень»

Обирайте Інгрес, коли задача маршрутизації — це HTTP чи HTTPS, кластер уже має підтримуваний контролер, а потрібні можливості вкладаються в стабільний API Інгресу плюс невелику кількість прийнятих анотацій. Обирайте Сервіс типу LoadBalancer, коли робоче навантаження не обізнане з HTTP або заслуговує на власний виділений ендпоінт L4. Обирайте Gateway API для нових архітектур платформи, яким потрібні багатші й краще переносні можливості маршрутизації, окреме володіння інфраструктурою та застосунками або чистіше делегування між просторами імен.

ПитанняВіддайте перевагу цьомуПричина
Вам потрібен TCP чи UDP без рішень за HTTP-хостом/шляхом?Сервіс LoadBalancerІнгрес HTTP-орієнтований і додає зайвий механізм рівня 7
Вам потрібно багато HTTP-застосунків за однією зовнішньою точкою входу?Ingress або Gateway APIОбидва можуть маршрутизувати за хостом і шляхом через спільну інфраструктуру
Ви будуєте нову платформу Kubernetes 1.35+?Gateway APIЦе наступна модель з кращим розділенням ролей і багатшими концепціями маршрутизації
Ви підтримуєте наявні маніфести Інгресу?Ingress з плануванням переходуAPI лишається підтримуваним, але вибір контролера й анотацій потребує перегляду
Ви сильно покладаєтеся на анотації, специфічні для контролера?Оцініть зусилля на перехідЦі анотації — центр витрат, коли контролери змінюються

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

  • API Інгресу перейшов на networking.k8s.io/v1 і є стабільною формою API від Kubernetes 1.19, ось чому сучасні приклади мають включати pathType та структурований формат бекенду service.name.
  • Виведення з експлуатації спільнотного контролера ingress-nginx було оголошено керівництвом проєкту Kubernetes на березень 2026 року, але це виведення не позначило застарілим сам API Інгресу Kubernetes.
  • Один Інгрес може містити кілька правил хостів і кілька правил шляхів, але Secret’и типу TLS, на які посилається цей Інгрес, усе одно мають перебувати в тому самому просторі імен, що й об’єкт Інгресу.
  • Збіг шляхів у Kubernetes використовує пріоритетність за найдовшим шляхом, і коли збіги Exact та Prefix рівні за найдовшим шляхом, перемагає збіг Exact.
ПомилкаЧому трапляєтьсяЯк виправити
Створення Інгресу до того, як з’явився будь-який контролерAPI приймає об’єкт, тож учні припускають, що маршрутизація існуєУстановіть або визначте контролер, потім перевірте Pod’и, Сервіс і IngressClass
Пропуск ingressClassName у спільному кластеріЛокальні лабораторії часто мають один стандартний клас, що приховує залежністьУстановіть spec.ingressClassName явно й підтвердьте, що він збігається з kubectl get ingressclass
Надсилання бекенду Інгресу на порт контейнера замість порту СервісуБлок бекенду каже port, тож легко думати про Pod першочерговоЗіставте бекенд Інгресу з портом Сервісу, що стоїть перед Pod’ами
Використання Exact для шляхів, яким потрібні дочірні/api працює у швидкому тесті, але /api/users провалюєтьсяВикористовуйте Prefix для родин маршрутів і резервуйте Exact для окремих ендпоінтів
Очікування, що Secret’и типу TLS працюватимуть між просторами іменІмена Secret’ів виглядають глобальними при швидкому читанніСтворіть Secret типу TLS у тому самому просторі імен, що й Інгрес
Трактування 404 і 503 як одного й того самого збоюОбидва видимі користувачам як зламані сторінкиВикористовуйте 404 як підказку збігу/маршрутизації, а 503 — як підказку ендпоінта бекенду
Копіювання анотацій, специфічних для контролера, без читання його документаціїПриклади часто приховують припущення про переносністьДокументуйте залежність від контролера або використовуйте можливості Gateway API, де доступно
Питання 1: Ваша команда запускає кілька HTTPS-вебсервісів і пропонує один Сервіс `LoadBalancer` на кожне робоче навантаження. Яку архітектуру ви порекомендуєте і про який компроміс варто згадати?

Використовуйте маршрут Інгресу чи Gateway API через спільний контролер, коли трафік — це HTTP чи HTTPS і платформі потрібна маршрутизація за хостом або шляхом. Окремий LoadBalancer на робоче навантаження може бути доречним для виділених ендпоінтів, але він збільшує кількість зовнішніх IP, вартість хмарних балансувальників навантаження, дублювання сертифікатів та операційну поверхню. Для нової платформи Kubernetes 1.35+ згадайте, що Gateway API — переважний напрямок, тоді як Інгрес лишається поширеним і підтримуваним для наявної маршрутизації.

Питання 2: Ви застосовуєте Інгрес, і `kubectl get ingress` не показує адресу через кілька хвилин. Що слід дослідити першим?

Почніть з перевірки, чи встановлено й справний Інгрес-контролер, бо API-сервер сам по собі не маршрутизує трафік. Потім дослідіть kubectl get ingressclass і порівняйте ім’я класу з spec.ingressClassName на Інгресі. Якщо контролер і клас виглядають правильними, опишіть Інгрес і дослідіть логи контролера, щоб побачити, чи контролер відхилив ресурс або чи йому бракує дозволу оновлювати статус.

Питання 3: Запити на `/api/users` повертають сторінку фронтенду, тоді як `/` призначено для фронтенду, а `/api` — для API. Яка ймовірна помилка маршрутизації?

Найімовірніша помилка в тому, що шлях /api використовує Exact, прив’язаний до іншого правила хоста або не збігається, бо тестовому запиту бракує очікуваного заголовка хоста. З pathType: Prefix /api/users має збігтися з /api й перемогти префікс /, бо Kubernetes використовує пріоритетність за найдовшим шляхом. Після перевірки типу шляху й хоста дослідіть оброблений Інгрес через kubectl describe ingress і підтвердьте ім’я та порт бекенд-Сервісу.

Питання 4: TLS-Інгрес посилається на `secretName: prod-tls`, але клієнти бачать стандартний сертифікат. Яке правило простору імен слід перевірити?

Перевірте, що prod-tls існує в тому самому просторі імен, що й об’єкт Інгресу. API Інгресу не дозволяє маршруту в одному просторі імен напряму посилатися на Secret типу TLS в іншому просторі імен. Якщо Secret відсутній, у неправильному просторі імен, неправильно сформований або не є Secret’ом типу TLS у Kubernetes, контролер може віддавати запасний сертифікат або повідомити про помилку в подіях і логах.

Питання 5: Бекенд віддає `/dashboard`, але користувачі відвідують `/app/dashboard` через Інгрес і отримують 404 застосунку. Як ви діагностуєте різницю між маршрутизацією Інгресу та маршрутизацією застосунку?

Спершу підтвердьте, чи запит досягає потрібного бекенду, перевіривши логи доступу контролера, ендпоінти Сервісу та прямий внутрішньокластерний запит до Сервісу. Якщо бекенд отримує /app/dashboard, але віддає лише /dashboard, Інгрес збігся коректно, а проблема, що лишилася, — форма URL. Анотація переписування, специфічна для контролера, може відрізати префікс /app, але це слід задокументувати, бо поведінка переписування не переносна між усіма контролерами.

Питання 6: Платформа має і публічний, і приватний Інгрес-контролери. Чому явний `ingressClassName` — частина безпекової позиції?

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

Питання 7: Інгрес повертає 503 для шляху, який начебто збігається коректно. Які перевірки бекенду слід виконати перед редагуванням маршруту?

503 зазвичай означає, що контролер збіг маршрут, але не зміг дістатися справних ендпоінтів бекенду. Перевірте ім’я та порт Сервісу, на які посилається Інгрес, потім запустіть kubectl get svc,endpoints або дослідіть EndpointSlice’и для Сервісу. Якщо ендпоінтів немає, виправте селектор Сервісу, мітки Pod’а, готовність Pod’а чи справність Деплойменту, перш ніж змінювати правила шляхів.

Сценарій вправи: побудуйте невелику конструкцію HTTP-маршрутизації з двома Сервісами, одним Інгресом за шляхом, одним Інгресом за хостом та одним TLS-Інгресом. Лабораторна робота передбачає навчальний кластер з Інгрес-контролером і доступним IngressClass nginx; якщо ваш кластер використовує інший підтримуваний контролер, збережіть ту саму структуру API, але замініть ім’я класу й анотації, специфічні для контролера, відповідно до документації цього контролера.

Завдання 1: Створіть бекенд-Сервіси

Розділ «Завдання 1: Створіть бекенд-Сервіси»

Створіть два простих Деплойменти й відкрийте їх як Сервіси ClusterIP. Образи навмисно банальні, бо мета — поведінка маршрутизації, а не логіка застосунку. Після створення перевірте обидва Деплойменти й Сервіси, перш ніж писати будь-яке правило Інгресу, бо правильний маршрут не врятує відсутній бекенд.

Terminal window
# API service
kubectl create deployment api --image=nginx
kubectl expose deployment api --port=80
# Web service
kubectl create deployment web --image=nginx
kubectl expose deployment web --port=80
Terminal window
kubectl get deployment api web
kubectl get svc api web
Нотатки до розв'язання Завдання 1

Обидва Деплойменти мають показати доступні репліки після запуску образу, а обидва Сервіси мають показати TYPE як ClusterIP з портом 80. Якщо Деплойменти ще не доступні, дочекайтеся Pod’ів, перш ніж налагоджувати Інгрес. Якщо Сервіси відсутні або мають несподівані імена, пізніші посилання бекенду Інгресу спричинять заплутані збої в стилі 503.

Завдання 2: Створіть маршрутизацію за шляхом

Розділ «Завдання 2: Створіть маршрутизацію за шляхом»

Створіть один Інгрес, який спрямовує /api до API-Сервісу, а / — до вебсервісу. Це найменша корисна форма маршрутизації для іспиту, бо вона змушує вас пов’язати пріоритетність шляхів, імена Сервісів, порти Сервісів та обраний IngressClass в одному маніфесті.

Terminal window
cat << 'EOF' | kubectl apply -f -
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: multi-path-ingress
spec:
ingressClassName: nginx
rules:
- http:
paths:
- path: /api
pathType: Prefix
backend:
service:
name: api
port:
number: 80
- path: /
pathType: Prefix
backend:
service:
name: web
port:
number: 80
EOF
Terminal window
kubectl get ingress
kubectl describe ingress multi-path-ingress
Terminal window
# Get ingress address (fallback to localhost if no LB IP is assigned in local clusters)
INGRESS_IP=$(kubectl get ingress multi-path-ingress -o jsonpath='{.status.loadBalancer.ingress[0].ip}')
[ -z "$INGRESS_IP" ] && INGRESS_IP="localhost"
# Test paths directly from the host node (since INGRESS_IP might be localhost)
curl -s http://$INGRESS_IP/api
curl -s http://$INGRESS_IP/
Нотатки до розв'язання Завдання 2

Важливий сигнал успіху — те, що Інгрес має правила, які вказують на Сервіси api та web на порту 80. У локальних кластерах значення ADDRESS може відрізнятися, тож не підлаштовуйтеся надмірно під зовнішню IP у хмарному стилі. Якщо /api зазнає невдачі, але / працює, дослідіть тип шляху й ендпоінти бекенд-Сервісу, перш ніж редагувати непов’язані налаштування TLS чи анотацій.

Завдання 3: Створіть маршрутизацію за хостом

Розділ «Завдання 3: Створіть маршрутизацію за хостом»

Створіть Інгрес, що маршрутизує два різних імені хостів до двох Сервісів. Маршрутизація за хостом — найчистіший спосіб розділити володіння між застосунками, бо кожна команда може міркувати про власне DNS-ім’я, не ділячись префіксами шляхів під одним публічним сайтом.

Terminal window
cat << 'EOF' | kubectl apply -f -
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: host-ingress
spec:
ingressClassName: nginx
rules:
- host: api.example.com
http:
paths:
- path: /
pathType: Prefix
backend:
service:
name: api
port:
number: 80
- host: web.example.com
http:
paths:
- path: /
pathType: Prefix
backend:
service:
name: web
port:
number: 80
EOF
Terminal window
kubectl describe ingress host-ingress
Нотатки до розв'язання Завдання 3

Вивід describe має показати два правила хостів, кожне з префіксом / та іншим бекенд-Сервісом. Щоб протестувати цю форму, вам потрібно надіслати правильний заголовок Host або налаштувати локальний DNS. Запит без очікуваного заголовка хоста може потрапити до стандартного бекенду, навіть коли Інгрес ідеально дійсний.

Завдання 4: Додайте термінацію TLS

Розділ «Завдання 4: Додайте термінацію TLS»

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

Terminal window
# self-signed, no SAN — modern curl needs --insecure (lab/testing only)
openssl req -x509 -nodes -days 365 -newkey rsa:2048 \
-keyout tls.key -out tls.crt \
-subj "/CN=example.com"
kubectl create secret tls example-tls --cert=tls.crt --key=tls.key
Terminal window
kubectl get secret example-tls
Terminal window
cat << 'EOF' | kubectl apply -f -
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: tls-ingress
spec:
ingressClassName: nginx
tls:
- hosts:
- secure.example.com
secretName: example-tls
rules:
- host: secure.example.com
http:
paths:
- path: /
pathType: Prefix
backend:
service:
name: web
port:
number: 80
EOF
Terminal window
kubectl describe ingress tls-ingress
Нотатки до розв'язання Завдання 4

Секція TLS має посилатися на example-tls, а Secret має бути в тому самому просторі імен, що й tls-ingress. Якщо ваш контролер віддає запасний сертифікат, перевірте тип Secret’а, простір імен, загальне ім’я сертифіката чи альтернативні імена суб’єкта (SAN) та події контролера. У промисловому кластері автоматизація сертифікатів зазвичай володіє цим Secret’ом, а не людина, що запускає openssl вручну.

Завдання 5: Прибирання та перевірка успіху

Розділ «Завдання 5: Прибирання та перевірка успіху»

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

Terminal window
kubectl delete ingress multi-path-ingress host-ingress tls-ingress
kubectl delete deployment api web
kubectl delete svc api web
kubectl delete secret example-tls
rm tls.key tls.crt

Критерії успіху:

  • Спроєктувати маршрутизацію Інгресу за шляхом і за хостом для двох бекенд-Сервісів.
  • Налаштувати термінацію TLS з Secret’ом типу TLS у Kubernetes у правильному просторі імен.
  • Оцінити, чи має кластер відповідний IngressClass і контролер для маршруту.
  • Діагностувати збої маршрутизації за допомогою kubectl describe ingress, Сервісів, Endpoint’ів та логів контролера.
  • Пояснити, коли Gateway API був би кращою наступною архітектурою, ніж додавання нових анотацій до Інгресу.

Хронометровані практичні дрилі

Розділ «Хронометровані практичні дрилі»

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

Дриль 1: Базовий Інгрес

Розділ «Дриль 1: Базовий Інгрес»
Terminal window
# Create service
kubectl create deployment drill-app --image=nginx
kubectl expose deployment drill-app --port=80
# Create Ingress
cat << 'EOF' | kubectl apply -f -
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: drill-ingress
spec:
ingressClassName: nginx
rules:
- http:
paths:
- path: /
pathType: Prefix
backend:
service:
name: drill-app
port:
number: 80
EOF
# Check
kubectl get ingress drill-ingress
kubectl describe ingress drill-ingress
# Cleanup
kubectl delete ingress drill-ingress
kubectl delete deployment drill-app
kubectl delete svc drill-app

Дриль 2: Інгрес з кількома шляхами

Розділ «Дриль 2: Інгрес з кількома шляхами»
Terminal window
# Create services
kubectl create deployment api --image=nginx
kubectl create deployment web --image=nginx
kubectl expose deployment api --port=80
kubectl expose deployment web --port=80
# Create Ingress
cat << 'EOF' | kubectl apply -f -
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: multi-path
spec:
ingressClassName: nginx
rules:
- http:
paths:
- path: /api
pathType: Prefix
backend:
service:
name: api
port:
number: 80
- path: /
pathType: Prefix
backend:
service:
name: web
port:
number: 80
EOF
# Verify
kubectl describe ingress multi-path
# Cleanup
kubectl delete ingress multi-path
kubectl delete deployment api web
kubectl delete svc api web

Дриль 3: Інгрес за хостом

Розділ «Дриль 3: Інгрес за хостом»
Terminal window
# Create services
kubectl create deployment app1 --image=nginx
kubectl create deployment app2 --image=nginx
kubectl expose deployment app1 --port=80
kubectl expose deployment app2 --port=80
# Create Ingress
cat << 'EOF' | kubectl apply -f -
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: host-based
spec:
ingressClassName: nginx
rules:
- host: app1.example.com
http:
paths:
- path: /
pathType: Prefix
backend:
service:
name: app1
port:
number: 80
- host: app2.example.com
http:
paths:
- path: /
pathType: Prefix
backend:
service:
name: app2
port:
number: 80
EOF
# Verify
kubectl get ingress host-based
kubectl describe ingress host-based
# Cleanup
kubectl delete ingress host-based
kubectl delete deployment app1 app2
kubectl delete svc app1 app2
Terminal window
# Create service
kubectl create deployment secure-app --image=nginx
kubectl expose deployment secure-app --port=80
# Generate certificate
# self-signed, no SAN — modern curl needs --insecure (lab/testing only)
openssl req -x509 -nodes -days 1 -newkey rsa:2048 \
-keyout tls.key -out tls.crt -subj "/CN=secure.local"
# Create secret
kubectl create secret tls tls-secret --cert=tls.crt --key=tls.key
# Create Ingress with TLS
cat << 'EOF' | kubectl apply -f -
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: tls-ingress
spec:
ingressClassName: nginx
tls:
- hosts:
- secure.local
secretName: tls-secret
rules:
- host: secure.local
http:
paths:
- path: /
pathType: Prefix
backend:
service:
name: secure-app
port:
number: 80
EOF
# Verify
kubectl describe ingress tls-ingress
# Cleanup
kubectl delete ingress tls-ingress
kubectl delete deployment secure-app
kubectl delete svc secure-app
kubectl delete secret tls-secret
rm tls.key tls.crt

Дриль 5: Перевірка IngressClass

Розділ «Дриль 5: Перевірка IngressClass»
Terminal window
# List IngressClasses
kubectl get ingressclass
# Describe
kubectl describe ingressclass nginx
# Check which is default
kubectl get ingressclass -o jsonpath="{range .items[*]}{.metadata.name}{\"\\t\"}{.metadata.annotations['ingressclass\\.kubernetes\\.io/is-default-class']}{\"\\n\"}{end}"

Дриль 6: Інгрес з анотаціями

Розділ «Дриль 6: Інгрес з анотаціями»
Terminal window
# Create service
kubectl create deployment annotated-app --image=nginx
kubectl expose deployment annotated-app --port=80
# Create Ingress with annotations
cat << 'EOF' | kubectl apply -f -
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: annotated-ingress
annotations:
nginx.ingress.kubernetes.io/ssl-redirect: "false"
nginx.ingress.kubernetes.io/proxy-connect-timeout: "30"
spec:
ingressClassName: nginx
rules:
- http:
paths:
- path: /
pathType: Prefix
backend:
service:
name: annotated-app
port:
number: 80
EOF
# Check annotations
kubectl get ingress annotated-ingress -o yaml | grep -A5 annotations
# Cleanup
kubectl delete ingress annotated-ingress
kubectl delete deployment annotated-app
kubectl delete svc annotated-app

Дриль 7: Налагодження Інгресу

Розділ «Дриль 7: Налагодження Інгресу»
Terminal window
# Create Ingress with wrong service name (intentionally broken)
cat << 'EOF' | kubectl apply -f -
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: broken-ingress
spec:
ingressClassName: nginx
rules:
- http:
paths:
- path: /
pathType: Prefix
backend:
service:
name: nonexistent-service
port:
number: 80
EOF
# Debug
kubectl describe ingress broken-ingress
# Look for warnings about backend
# Check ingress controller logs (if installed)
kubectl logs -n ingress-nginx -l app.kubernetes.io/name=ingress-nginx --tail=10
# Fix: create the missing service
kubectl create deployment fix-app --image=nginx
kubectl expose deployment fix-app --port=80 --name=nonexistent-service
# Verify
kubectl describe ingress broken-ingress
# Cleanup
kubectl delete ingress broken-ingress
kubectl delete deployment fix-app
kubectl delete svc nonexistent-service

Дриль 8: Виклик — повне налаштування Інгресу

Розділ «Дриль 8: Виклик — повне налаштування Інгресу»

Не заглядаючи в розв’язання, створіть деплойменти на ім’я api та frontend, відкрийте обидва як Сервіси ClusterIP на порту 80, створіть Інгрес для хоста myapp.local, маршрутизуйте /api до api, маршрутизуйте / до frontend, додайте Secret типу TLS, перевірте через describe й приберіть усе.

Terminal window
# YOUR TASK: Complete the challenge in under 7 minutes
Розв'язання
Terminal window
# 1. Create deployments
kubectl create deployment api --image=nginx
kubectl create deployment frontend --image=nginx
# 2. Expose as ClusterIP
kubectl expose deployment api --port=80
kubectl expose deployment frontend --port=80
# 3. Create Ingress
cat << 'EOF' | kubectl apply -f -
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: challenge-ingress
spec:
ingressClassName: nginx
rules:
- host: myapp.local
http:
paths:
- path: /api
pathType: Prefix
backend:
service:
name: api
port:
number: 80
- path: /
pathType: Prefix
backend:
service:
name: frontend
port:
number: 80
EOF
# 4. Add TLS
# self-signed, no SAN — modern curl needs --insecure (lab/testing only)
openssl req -x509 -nodes -days 1 -newkey rsa:2048 \
-keyout tls.key -out tls.crt -subj "/CN=myapp.local"
kubectl create secret tls myapp-tls --cert=tls.crt --key=tls.key
# Update Ingress with TLS
cat << 'EOF' | kubectl apply -f -
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: challenge-ingress
spec:
ingressClassName: nginx
tls:
- hosts:
- myapp.local
secretName: myapp-tls
rules:
- host: myapp.local
http:
paths:
- path: /api
pathType: Prefix
backend:
service:
name: api
port:
number: 80
- path: /
pathType: Prefix
backend:
service:
name: frontend
port:
number: 80
EOF
# 5. Verify
kubectl describe ingress challenge-ingress
# 6. Cleanup
kubectl delete ingress challenge-ingress
kubectl delete deployment api frontend
kubectl delete svc api frontend
kubectl delete secret myapp-tls
rm tls.key tls.crt

Модуль 3.5: Gateway API — наступне покоління інгресу Kubernetes з багатшими ресурсами маршрутів і чіткішими межами володіння на платформі.

Перевірка для учня

Розділ «Перевірка для учня»

Якщо ви запам’ятаєте лише одне речення про налагодження, нехай це буде воно: відсутня адреса вказує на узгодження контролера чи класу, 404 вказує на збіг хоста й шляху, а 503 вказує на збіглі маршрути з недоступними бекендами.