Предыдущие статьи:
Kubernetes просто, часть 4: как трафик попадает в кластер, NodePort и LoadBalancer
Kubernetes просто, часть 3: зачем нужен Service и как трафик доходит до конкретного Pod
Kubernetes просто, часть 2: что происходит после kubectl apply
Kubernetes просто, часть 1: зачем Kubernetes, устройство кластера
В прошлой части мы успели разобрать, как трафик попадает в кластер извне, из Интернета и локальных сетей.
Теперь у нас есть три типа Service
ClusterIP
NodePort
LoadBalancer
И для внешнего доступа мы пришли к следующей схеме:
Internet ↓ Load Balancer ↓ Service ↓ Pods
Для одного приложения всё довольно закономерно. Но давайте представим, что наш кластер постепенно растёт. Теперь в нём работают несколько приложений:
shop.example.com
admin.example.com
api.example.com
Каждому из них нужен внешний доступ. И, конечно, можно просто собрать для каждого из них Service типа LoadBalancer для его осуществления.
В итоге получаем:

Тут возникает закономерный вопрос:
Обязательно ли каждому HTTP‑приложению создавать собственную внешнюю точку входа?
Этот подход кажется нерациональным — неужто его нельзя оптимизировать?
Хочется принимать трафик в одном месте, а уже потом решать:
shop.example.com ↓ shop-service api.example.com ↓ api-service admin.example.com ↓ admin-service
А может, даже так:
example.com/shop ↓ shop-service example.com/api ↓ api-service
Именно для такой маршрутизации в зависимости от HTTP‑адреса в Kubernetes используется Ingress. Его изучению и посвятим эту статью.
Что это такое?
Начнём с простого:
Ingress описывает правила маршрутизации HTTP/HTTPS‑трафика к Services внутри Kubernetes.
Фактически, с этим мы уже определились ранее.
До этого мы имели:
Internet ↓ Load Balancer ↓ Service ↓ Pods
А теперь появляется новый уровень:
Internet ↓ Ingress ├──→ Service A → Pods └──→ Service B → Pods
Ingress умеет «смотреть» на HTTP‑запрос и определять, какому Service его передать.
К примеру, пришёл запрос на
https://shop.example.com
Он закономерно попадёт в shop‑service.
А запрос на
https://api.example.com
Отправится в api‑service.
В итоге имеем:

Ingress ≠ Service
Давайте продублируем задачи каждого уровня, чтобы не путать их.
Мы знаем, задача Service — вести учёт работоспособных подов и распределять по ним входящий трафик.
К примеру:
backend-service ├── Pod A ├── Pod B └── Pod C
Задача Ingress похожа, но уже относительно сервисов, а не подов. Он работает на уровень выше и распределяет трафик по сервисам.

Маршрутизация по домену
Посмотрим на первый сценарий, о котором мы говорили:
Имеется два адреса и два сервиса, которые им соответствуют:
api.example.com -> api-service
shop.example.com -> shop-service
Соответственно, мы хотим получить соответствующую маршрутизацию, чтобы запросы на первый адрес попадали в api‑service и аналогично для shop.
Ingress позволяет легко описать такие правила:
apiVersion: networking.k8s.io/v1 kind: Ingress metadata: name: example-ingress spec: rules: - host: shop.example.com http: paths: - path: / pathType: Prefix backend: service: name: shop-service port: number: 80 - host: api.example.com http: paths: - path: / pathType: Prefix backend: service: name: api-service port: number: 80
На первый взгляд — YAML большой и непонятный, но идея здесь довольно лаконичная и простая.
Есть правило:
host: <адрес, к примеру api.example.com>
И backend, который его должен обслуживать:
service: name: <имя сервиса> port: number: <порт, на котором принимает запросы сервис>
Соответственно:
если host = shop.example.com ↓ отправить в shop-service:80
Аналогично для api.example.com.

Маршрутизация по пути
Ingress умеет принимать решения не только по домену, вспомните типичные адреса сайтов, на которые вы заходите, обычно они имеют вид
marketplace.com/catalog
marketplace.com/profile
И подобные. Часть после «/» обычно называется путём запроса.
Соответственно, хотелось бы иметь возможность маршрутизировать трафик именно в зависимости от пути.
marketplace.com/catalog -> catalog-service
marketplace.com/profile -> profile-service
В manifest это может быть отображено так:
rules: - host: marketplace.com http: paths: - path: /catalog pathType: Prefix backend: service: name: catalog-service port: number: 80 - path: /profile pathType: Prefix backend: service: name: profile-service port: number: 80
Теперь Ingress смотрит не только на домен запроса, но и на path (его путь).

pathType
В манифесте выше появилось:
pathType: Prefix
Сейчас достаточно понимать его как:
Путь считается префиксом для маршрутизации запросов.
Иначе говоря, запросы на
marketplace/catalog
marketplace/catalog/technic
marketplace/catalog/technic/phones
Все будут маршрутизироваться по правилу префикса /catalog сервисом catalog-service.
Есть и другие варианты pathType, но сейчас углубляться в них не будем.
Ingress — набор правил
Вполне возможно, что Ingress уже усвоился в вашей голове как набор правил по маршрутизации трафика. Так и есть!
Мы создали:
kind: Ingress
В нём написали, какие маршруты на какие сервисы ссылаются. Фактически, сам объект Ingress — просто набор правил. Но кто эти правила реализует? Кто следит за тем, чтобы они выполнялись?
Здесь появляется Ingress Controller.
Упрощённо имеем:
Ingress │ содержит правила ↓ Ingress Controller │ реализует их ↓ Services
Это похоже на уже знакомый нам принцип, с desired и actual state кластера.
Мы описываем желаемое состояние кластера, а соответствующий контроллер следит за тем, чтобы актуальное состояние стремилось к желаемому.
Так и здесь:
Мы описываем набор правил, а контроллер следит за объектами Ingress и настраивает соответствующую маршрутизацию трафика.

Собираем всё вместе
Представим, что у нас есть Интернет‑магазин.
В Kubernetes работают:
Frontend Pods
API Pods
Admin Pods
Для каждой группы подов создан свой Service.
shop-service
api-service
admin-service
Наружу мы хотим отдать:
shop.example.com
api.example.com
admin.example.com
Имеем в итоге:

И здесь уже хорошо видно разделение ответственности.
DNS ↓ Где находится внешний адрес? ---------------------------- Load Balancer ↓ Как попасть в кластер? ---------------------------- Ingress ↓ К какому HTTP backend отправить запрос? ---------------------------- Service ↓ Какие Pods стоят за этим backend? ---------------------------- Pods ↓ Где работает приложение?
Что запомнить
После этой части главное не запоминать большой Ingress YAML.
Гораздо важнее держать в голове цепочку:
Internet ↓ Ingress Controller ↓ Ingress rules ↓ Service ↓ Pods
Ingress описывает правила HTTP/HTTPS‑маршрутизации.
Например:
shop.example.com -> shop-service
api.example.com -> api-service
Ingress Controller — компонент, который реализует эти правила и фактически обрабатывает соответствующий входящий трафик.
А Service по‑прежнему решает уже знакомую задачу:
Service ↓ backend Pods
Как итог:
Ingress ≠ Service
Ingress ≠ Ingress Controller
Проверьте себя
1. Какую проблему решает Ingress, если у нас уже есть Service типа LoadBalancer?
2. Чем отличаются задачи Ingress и Service?
3. Есть правила:
shop.example.com -> shop-service
api.example.com -> api-service
Куда должен попасть запрос:
https://api.example.com